From cfebe66762d9c0ee7e8de979e9a12ea8f29b7c68 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Wed, 1 May 2019 08:28:09 +0930 Subject: [PATCH] openingd: support receipt of upfront_shutdown_script. Signed-off-by: Rusty Russell --- common/features.c | 1 + lightningd/opening_control.c | 20 ++++-- openingd/Makefile | 1 + openingd/opening_wire.csv | 6 ++ openingd/openingd.c | 133 ++++++++++++++++++++++++++++------- tests/test_connection.py | 6 +- 6 files changed, 131 insertions(+), 36 deletions(-) diff --git a/common/features.c b/common/features.c index 426cf8157..debb63f13 100644 --- a/common/features.c +++ b/common/features.c @@ -6,6 +6,7 @@ static const u32 our_localfeatures[] = { LOCAL_DATA_LOSS_PROTECT, LOCAL_INITIAL_ROUTING_SYNC, + LOCAL_UPFRONT_SHUTDOWN_SCRIPT, LOCAL_GOSSIP_QUERIES }; diff --git a/lightningd/opening_control.c b/lightningd/opening_control.c index c7f3d9429..83e3f5a43 100644 --- a/lightningd/opening_control.c +++ b/lightningd/opening_control.c @@ -152,7 +152,8 @@ wallet_commit_channel(struct lightningd *ld, struct amount_msat push, u8 channel_flags, struct channel_info *channel_info, - u32 feerate) + u32 feerate, + const u8 *remote_upfront_shutdown_script) { struct channel *channel; struct amount_msat our_msat; @@ -226,7 +227,7 @@ wallet_commit_channel(struct lightningd *ld, NULL, ld->config.fee_base, ld->config.fee_per_satoshi, - NULL); + remote_upfront_shutdown_script); /* Now we finally put it in the database. */ wallet_channel_insert(ld->wallet, channel); @@ -297,6 +298,7 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, struct amount_sat change; struct channel *channel; struct lightningd *ld = openingd->ld; + u8 *remote_upfront_shutdown_script; assert(tal_count(fds) == 2); @@ -317,7 +319,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, &channel_info.remote_fundingkey, &expected_txid, &feerate, - &fc->uc->our_config.channel_reserve)) { + &fc->uc->our_config.channel_reserve, + &remote_upfront_shutdown_script)) { log_broken(fc->uc->log, "bad OPENING_FUNDER_REPLY %s", tal_hex(resp, resp)); @@ -405,7 +408,8 @@ static void opening_funder_finished(struct subd *openingd, const u8 *resp, fc->push, fc->channel_flags, &channel_info, - feerate); + feerate, + remote_upfront_shutdown_script); if (!channel) { was_pending(command_fail(fc->cmd, LIGHTNINGD, "Key generation failure")); @@ -485,6 +489,7 @@ static void opening_fundee_finished(struct subd *openingd, u32 feerate; u8 channel_flags; struct channel *channel; + u8 *remote_upfront_shutdown_script; log_debug(uc->log, "Got opening_fundee_finish_response"); assert(tal_count(fds) == 2); @@ -510,7 +515,8 @@ static void opening_fundee_finished(struct subd *openingd, &channel_flags, &feerate, &funding_signed, - &uc->our_config.channel_reserve)) { + &uc->our_config.channel_reserve, + &remote_upfront_shutdown_script)) { log_broken(uc->log, "bad OPENING_FUNDEE_REPLY %s", tal_hex(reply, reply)); uncommitted_channel_disconnect(uc, "bad OPENING_FUNDEE_REPLY"); @@ -534,7 +540,8 @@ static void opening_fundee_finished(struct subd *openingd, push, channel_flags, &channel_info, - feerate); + feerate, + remote_upfront_shutdown_script); if (!channel) { uncommitted_channel_disconnect(uc, "Commit channel failed"); goto failed; @@ -825,6 +832,7 @@ void peer_start_openingd(struct peer *peer, feerate_min(peer->ld, NULL), feerate_max(peer->ld, NULL), !peer_active_channel(peer), + peer->localfeatures, send_msg); subd_send_msg(uc->openingd, take(msg)); } diff --git a/openingd/Makefile b/openingd/Makefile index 01847d90a..cf85aa349 100644 --- a/openingd/Makefile +++ b/openingd/Makefile @@ -46,6 +46,7 @@ OPENINGD_COMMON_OBJS := \ common/daemon_conn.o \ common/derive_basepoints.o \ common/dev_disconnect.o \ + common/features.o \ common/funding_tx.o \ common/gen_status_wire.o \ common/gen_peer_status_wire.o \ diff --git a/openingd/opening_wire.csv b/openingd/opening_wire.csv index 6e8a30fb3..30bc7b138 100644 --- a/openingd/opening_wire.csv +++ b/openingd/opening_wire.csv @@ -18,6 +18,8 @@ opening_init,,minimum_depth,u32 opening_init,,min_feerate,u32 opening_init,,max_feerate,u32 opening_init,,can_open_channel,bool +opening_init,,lfeatures_len,u16 +opening_init,,lfeatures,lfeatures_len*u8 # Optional msg to send. opening_init,,len,u16 opening_init,,msg,len*u8 @@ -57,6 +59,8 @@ opening_funder_reply,,remote_fundingkey,struct pubkey opening_funder_reply,,funding_txid,struct bitcoin_txid opening_funder_reply,,feerate_per_kw,u32 opening_funder_reply,,our_channel_reserve_satoshis,struct amount_sat +opening_funder_reply,,shutdown_len,u16 +opening_funder_reply,,shutdown_scriptpubkey,shutdown_len*u8 # Openingd->master: we failed to negotiation channel opening_funder_failed,6004 @@ -85,6 +89,8 @@ opening_fundee,,feerate_per_kw,u32 opening_fundee,,msglen,u16 opening_fundee,,funding_signed_msg,msglen*u8 opening_fundee,,our_channel_reserve_satoshis,struct amount_sat +opening_fundee,,shutdown_len,u16 +opening_fundee,,shutdown_scriptpubkey,shutdown_len*u8 # master -> openingd: do you have a memleak? opening_dev_memleak,6033 diff --git a/openingd/openingd.c b/openingd/openingd.c index b127d7099..3a30615ca 100644 --- a/openingd/openingd.c +++ b/openingd/openingd.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -58,6 +59,9 @@ struct state { * featured in BOLT #8) */ struct crypto_state cs; + /* Features they offered */ + u8 *localfeatures; + /* Constraints on a channel they open. */ u32 minimum_depth; u32 min_feerate, max_feerate; @@ -84,6 +88,8 @@ struct state { u32 feerate_per_kw; struct bitcoin_txid funding_txid; u16 funding_txout; + /* If set, this is the scriptpubkey they *must* close with */ + u8 *remote_upfront_shutdown_script; /* This is a cluster of fields in open_channel and accept_channel which * indicate the restrictions each side places on the channel. */ @@ -481,8 +487,19 @@ static u8 *funder_channel(struct state *state, "push-msat must be < %s", type_to_string(tmpctx, struct amount_sat, &state->funding)); - - msg = towire_open_channel(NULL, + /* BOLT #2: + * + * - if both nodes advertised the `option_upfront_shutdown_script` + * feature: + * - MUST include either a valid `shutdown_scriptpubkey` as required + * by `shutdown` `scriptpubkey`, or a zero-length + * `shutdown_scriptpubkey`. + * - otherwise: + * - MAY include a`shutdown_scriptpubkey`. + */ + /* We don't use shutdown_scriptpubkey (at least for now), so leave it + * NULL. */ + msg = towire_open_channel_option_upfront_shutdown_script(NULL, &state->chainparams->genesis_blockhash, &state->channel_id, state->funding, @@ -500,7 +517,7 @@ static u8 *funder_channel(struct state *state, &state->our_points.delayed_payment, &state->our_points.htlc, &state->first_per_commitment_point[LOCAL], - channel_flags); + channel_flags, NULL); sync_crypto_write(&state->cs, PEER_FD, take(msg)); /* This is usually a very transient state... */ @@ -511,6 +528,10 @@ static u8 *funder_channel(struct state *state, if (!msg) goto fail; + /* Default is no shutdown_scriptpubkey: free any leftover one. */ + state->remote_upfront_shutdown_script + = tal_free(state->remote_upfront_shutdown_script); + /* BOLT #2: * * The receiving node MUST fail the channel if: @@ -519,7 +540,28 @@ static u8 *funder_channel(struct state *state, * `payment_basepoint`, or `delayed_payment_basepoint` are not * valid DER-encoded compressed secp256k1 pubkeys. */ - if (!fromwire_accept_channel(msg, &id_in, + if (local_feature_negotiated(state->localfeatures, + LOCAL_UPFRONT_SHUTDOWN_SCRIPT)) { + if (!fromwire_accept_channel_option_upfront_shutdown_script(state, + msg, &id_in, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &minimum_depth, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &their_funding_pubkey, + &theirs.revocation, + &theirs.payment, + &theirs.delayed_payment, + &theirs.htlc, + &state->first_per_commitment_point[REMOTE], + &state->remote_upfront_shutdown_script)) + peer_failed(&state->cs, + &state->channel_id, + "Parsing accept_channel with option_upfront_shutdown_script %s", tal_hex(msg, msg)); + } else if (!fromwire_accept_channel(msg, &id_in, &state->remoteconf.dust_limit, &state->remoteconf.max_htlc_value_in_flight, &state->remoteconf.channel_reserve, @@ -822,7 +864,8 @@ static u8 *funder_channel(struct state *state, &their_funding_pubkey, &state->funding_txid, state->feerate_per_kw, - state->localconf.channel_reserve); + state->localconf.channel_reserve, + state->remote_upfront_shutdown_script); fail_2: tal_free(wscript); @@ -847,6 +890,10 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) u8 channel_flags; char* err_reason; + /* Default is no shutdown_scriptpubkey: free any leftover one. */ + state->remote_upfront_shutdown_script + = tal_free(state->remote_upfront_shutdown_script); + /* BOLT #2: * * The receiving node MUST fail the channel if: @@ -855,24 +902,49 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) * `payment_basepoint`, or `delayed_payment_basepoint` are not valid * DER-encoded compressed secp256k1 pubkeys. */ - if (!fromwire_open_channel(open_channel_msg, &chain_hash, - &state->channel_id, - &state->funding, - &state->push_msat, - &state->remoteconf.dust_limit, - &state->remoteconf.max_htlc_value_in_flight, - &state->remoteconf.channel_reserve, - &state->remoteconf.htlc_minimum, - &state->feerate_per_kw, - &state->remoteconf.to_self_delay, - &state->remoteconf.max_accepted_htlcs, - &their_funding_pubkey, - &theirs.revocation, - &theirs.payment, - &theirs.delayed_payment, - &theirs.htlc, - &state->first_per_commitment_point[REMOTE], - &channel_flags)) + if (local_feature_negotiated(state->localfeatures, + LOCAL_UPFRONT_SHUTDOWN_SCRIPT)) { + if (!fromwire_open_channel_option_upfront_shutdown_script(state, + open_channel_msg, &chain_hash, + &state->channel_id, + &state->funding, + &state->push_msat, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &state->feerate_per_kw, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &their_funding_pubkey, + &theirs.revocation, + &theirs.payment, + &theirs.delayed_payment, + &theirs.htlc, + &state->first_per_commitment_point[REMOTE], + &channel_flags, + &state->remote_upfront_shutdown_script)) + peer_failed(&state->cs, + &state->channel_id, + "Parsing open_channel with option_upfront_shutdown_script %s", tal_hex(tmpctx, open_channel_msg)); + } else if (!fromwire_open_channel(open_channel_msg, &chain_hash, + &state->channel_id, + &state->funding, + &state->push_msat, + &state->remoteconf.dust_limit, + &state->remoteconf.max_htlc_value_in_flight, + &state->remoteconf.channel_reserve, + &state->remoteconf.htlc_minimum, + &state->feerate_per_kw, + &state->remoteconf.to_self_delay, + &state->remoteconf.max_accepted_htlcs, + &their_funding_pubkey, + &theirs.revocation, + &theirs.payment, + &theirs.delayed_payment, + &theirs.htlc, + &state->first_per_commitment_point[REMOTE], + &channel_flags)) peer_failed(&state->cs, NULL, "Bad open_channel %s", tal_hex(open_channel_msg, open_channel_msg)); @@ -994,7 +1066,7 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) return NULL; /* OK, we accept! */ - msg = towire_accept_channel(NULL, &state->channel_id, + msg = towire_accept_channel_option_upfront_shutdown_script(NULL, &state->channel_id, state->localconf.dust_limit, state->localconf.max_htlc_value_in_flight, state->localconf.channel_reserve, @@ -1007,7 +1079,8 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) &state->our_points.payment, &state->our_points.delayed_payment, &state->our_points.htlc, - &state->first_per_commitment_point[LOCAL]); + &state->first_per_commitment_point[LOCAL], + NULL); sync_crypto_write(&state->cs, PEER_FD, take(msg)); @@ -1174,7 +1247,8 @@ static u8 *fundee_channel(struct state *state, const u8 *open_channel_msg) channel_flags, state->feerate_per_kw, msg, - state->localconf.channel_reserve); + state->localconf.channel_reserve, + state->remote_upfront_shutdown_script); } /*~ Standard "peer sent a message, handle it" demuxer. Though it really only @@ -1367,7 +1441,7 @@ int main(int argc, char *argv[]) /*~ The very first thing we read from lightningd is our init msg */ msg = wire_sync_read(tmpctx, REQ_FD); - if (!fromwire_opening_init(tmpctx, msg, + if (!fromwire_opening_init(state, msg, &chain_hash, &state->localconf, &state->max_to_self_delay, @@ -1378,6 +1452,7 @@ int main(int argc, char *argv[]) &state->minimum_depth, &state->min_feerate, &state->max_feerate, &state->can_accept_channel, + &state->localfeatures, &inner)) master_badmsg(WIRE_OPENING_INIT, msg); @@ -1386,6 +1461,7 @@ int main(int argc, char *argv[]) if (inner != NULL) { sync_crypto_write(&state->cs, PEER_FD, inner); fail_if_all_error(inner); + tal_free(inner); } /*~ Even though I only care about bitcoin, there's still testnet and @@ -1397,6 +1473,9 @@ int main(int argc, char *argv[]) memset(&state->channel_id, 0, sizeof(state->channel_id)); state->channel = NULL; + /*~ We set this to NULL, meaning no requirements on shutdown */ + state->remote_upfront_shutdown_script = NULL; + /*~ We need an initial per-commitment point whether we're funding or * they are, and lightningd has reserved a unique dbid for us already, * so we might as well get the hsm daemon to generate it now. */ diff --git a/tests/test_connection.py b/tests/test_connection.py index 0785bc759..539d4bc40 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1081,7 +1081,7 @@ def test_forget_channel(node_factory): def test_peerinfo(node_factory, bitcoind): l1, l2 = node_factory.line_graph(2, fundchannel=False, opts={'may_reconnect': True}) - lfeatures = '8a' + lfeatures = 'aa' # Gossiping but no node announcement yet assert l1.rpc.getpeer(l2.info['id'])['connected'] assert len(l1.rpc.getpeer(l2.info['id'])['channels']) == 0 @@ -1338,8 +1338,8 @@ def test_dataloss_protection(node_factory, bitcoind): "0000" # lflen == 1 "0001" - # Local features 1, 3 and 7 (0x8a). - "8a") + # Local features 1, 3, 5 and 7 (0xaa). + "aa") l1.fund_channel(l2, 10**6) l2.stop()