mirror of
https://github.com/ElementsProject/lightning.git
synced 2024-11-19 18:11:28 +01:00
daemon: keep track of simple addresses for injecting funds.
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>
This commit is contained in:
parent
6b956ea22a
commit
51de503096
@ -25,6 +25,7 @@ DAEMON_SRC := \
|
||||
daemon/packets.c \
|
||||
daemon/secrets.c \
|
||||
daemon/timeout.c \
|
||||
daemon/wallet.c \
|
||||
daemon/watch.c \
|
||||
names.c \
|
||||
state.c
|
||||
@ -52,6 +53,7 @@ DAEMON_HEADERS := \
|
||||
daemon/pseudorand.h \
|
||||
daemon/secrets.h \
|
||||
daemon/timeout.h \
|
||||
daemon/wallet.h \
|
||||
daemon/watch.h
|
||||
|
||||
$(DAEMON_OBJS) $(DAEMON_LIB_OBJS) $(DAEMON_CLI_OBJS): $(DAEMON_HEADERS) $(DAEMON_JSMN_HEADERS) $(BITCOIN_HEADERS) $(CORE_HEADERS) $(GEN_HEADERS) $(CCAN_HEADERS)
|
||||
|
@ -254,6 +254,7 @@ static const struct json_command *cmdlist[] = {
|
||||
&failhtlc_command,
|
||||
&commit_command,
|
||||
&close_command,
|
||||
&newaddr_command,
|
||||
/* Developer/debugging options. */
|
||||
&echo_command,
|
||||
&rhash_command,
|
||||
|
@ -64,4 +64,5 @@ extern const struct json_command failhtlc_command;
|
||||
extern const struct json_command commit_command;
|
||||
extern const struct json_command mocktime_command;
|
||||
extern const struct json_command close_command;
|
||||
extern const struct json_command newaddr_command;
|
||||
#endif /* LIGHTNING_DAEMON_JSONRPC_H */
|
||||
|
@ -183,6 +183,7 @@ static struct lightningd_state *lightningd_state(void)
|
||||
| SECP256K1_CONTEXT_SIGN);
|
||||
default_config(&dstate->config);
|
||||
list_head_init(&dstate->bitcoin_req);
|
||||
list_head_init(&dstate->wallet);
|
||||
dstate->bitcoin_req_running = false;
|
||||
return dstate;
|
||||
}
|
||||
|
@ -81,5 +81,8 @@ struct lightningd_state {
|
||||
/* Outstanding bitcoind requests. */
|
||||
struct list_head bitcoin_req;
|
||||
bool bitcoin_req_running;
|
||||
|
||||
/* Wallet addresses we maintain. */
|
||||
struct list_head wallet;
|
||||
};
|
||||
#endif /* LIGHTNING_DAEMON_LIGHTNING_H */
|
||||
|
107
daemon/wallet.c
Normal file
107
daemon/wallet.c
Normal file
@ -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"
|
||||
};
|
18
daemon/wallet.h
Normal file
18
daemon/wallet.h
Normal file
@ -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
Block a user