Browse Source
We need to control the *inputs* to the anchor tx, to make sure they pay to witness scripts (thus the anchor is immalleable). The easiest way to do this is to hand out P2SH addresses for the user, and have them pay into those. Then they hand us that tx and we use it to create the anchor. This is not a long-term solution! Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>ppa-0.6.1
Rusty Russell
9 years ago
7 changed files with 133 additions and 0 deletions
@ -0,0 +1,107 @@ |
|||
/* Poor man's wallet.
|
|||
* Needed because bitcoind doesn't (yet) produce segwit outputs, and we need |
|||
* such outputs for our anchor tx to make it immalleable. |
|||
*/ |
|||
#include "bitcoin/base58.h" |
|||
#include "bitcoin/privkey.h" |
|||
#include "bitcoin/script.h" |
|||
#include "bitcoin/signature.h" |
|||
#include "bitcoin/tx.h" |
|||
#include "jsonrpc.h" |
|||
#include "lightningd.h" |
|||
#include "log.h" |
|||
#include "wallet.h" |
|||
#include <ccan/structeq/structeq.h> |
|||
#include <openssl/rand.h> |
|||
|
|||
struct wallet { |
|||
struct list_node list; |
|||
struct privkey privkey; |
|||
struct pubkey pubkey; |
|||
struct ripemd160 p2sh; |
|||
}; |
|||
|
|||
static void new_keypair(struct lightningd_state *dstate, |
|||
struct privkey *privkey, struct pubkey *pubkey) |
|||
{ |
|||
do { |
|||
if (RAND_bytes(privkey->secret, sizeof(privkey->secret)) != 1) |
|||
fatal("Could not get random bytes for privkey"); |
|||
} while (!pubkey_from_privkey(dstate->secpctx, |
|||
privkey, pubkey, SECP256K1_EC_COMPRESSED)); |
|||
} |
|||
|
|||
void wallet_add_signed_input(struct lightningd_state *dstate, |
|||
const struct wallet *w, |
|||
struct bitcoin_tx *tx, |
|||
unsigned int input_num) |
|||
{ |
|||
u8 *redeemscript; |
|||
struct bitcoin_signature sig; |
|||
assert(input_num < tx->input_count); |
|||
|
|||
redeemscript = bitcoin_redeem_single(tx, &w->pubkey); |
|||
|
|||
sig.stype = SIGHASH_ALL; |
|||
sign_tx_input(dstate->secpctx, tx, input_num, |
|||
redeemscript, tal_count(redeemscript), |
|||
NULL, |
|||
&w->privkey, |
|||
&w->pubkey, |
|||
&sig.sig); |
|||
|
|||
tx->input[input_num].script |
|||
= scriptsig_p2sh_single_sig(tx->input, |
|||
redeemscript, |
|||
tal_count(redeemscript), |
|||
&sig); |
|||
tx->input[input_num].script_length |
|||
= tal_count(tx->input[input_num].script); |
|||
} |
|||
|
|||
struct wallet *wallet_can_spend(struct lightningd_state *dstate, |
|||
const struct bitcoin_tx_output *output) |
|||
{ |
|||
struct ripemd160 h; |
|||
struct wallet *w; |
|||
|
|||
if (!is_p2sh(output->script, output->script_length)) |
|||
return NULL; |
|||
|
|||
memcpy(&h, output->script + 2, 20); |
|||
list_for_each(&dstate->wallet, w, list) { |
|||
if (structeq(&h, &w->p2sh)) |
|||
return w; |
|||
} |
|||
return NULL; |
|||
} |
|||
|
|||
static void json_newaddr(struct command *cmd, |
|||
const char *buffer, const jsmntok_t *params) |
|||
{ |
|||
struct json_result *response = new_json_result(cmd); |
|||
struct wallet *w = tal(cmd->dstate, struct wallet); |
|||
u8 *redeemscript; |
|||
struct sha256 h; |
|||
|
|||
new_keypair(cmd->dstate, &w->privkey, &w->pubkey); |
|||
redeemscript = bitcoin_redeem_single(cmd, &w->pubkey); |
|||
sha256(&h, redeemscript, tal_count(redeemscript)); |
|||
ripemd160(&w->p2sh, h.u.u8, sizeof(h)); |
|||
|
|||
list_add_tail(&cmd->dstate->wallet, &w->list); |
|||
|
|||
json_object_start(response, NULL); |
|||
json_add_string(response, "address", |
|||
p2sh_to_base58(cmd, cmd->dstate->config.testnet, |
|||
&w->p2sh)); |
|||
json_object_end(response); |
|||
command_success(cmd, response); |
|||
} |
|||
|
|||
const struct json_command newaddr_command = { |
|||
"newaddr", |
|||
json_newaddr, |
|||
"Get a new address to fund a channel", |
|||
"Returns {address} a p2sh address" |
|||
}; |
@ -0,0 +1,18 @@ |
|||
#ifndef LIGHTNING_DAEMON_WALLET_H |
|||
#define LIGHTNING_DAEMON_WALLET_H |
|||
#include "config.h" |
|||
|
|||
struct wallet; |
|||
struct lightningd_state; |
|||
struct bitcoin_tx; |
|||
struct bitcoin_tx_output; |
|||
|
|||
void wallet_add_signed_input(struct lightningd_state *dstate, |
|||
const struct wallet *w, |
|||
struct bitcoin_tx *tx, |
|||
unsigned int input_num); |
|||
|
|||
struct wallet *wallet_can_spend(struct lightningd_state *dstate, |
|||
const struct bitcoin_tx_output *output); |
|||
|
|||
#endif /* LIGHTNING_DAEMON_WALLET_H */ |
Loading…
Reference in new issue