From 1cfb7b84d0716e40ab428b14a4b9d3899a581b1a Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Tue, 16 Mar 2021 06:55:54 +1030 Subject: [PATCH] closingd: add support for handling wrong_funding. Signed-off-by: Rusty Russell --- bitcoin/tx.c | 13 +++++ bitcoin/tx.h | 7 +++ closingd/closingd.c | 105 +++++++++++++++++++++++------------ closingd/closingd_wire.csv | 1 + closingd/closingd_wiregen.c | 18 +++++- closingd/closingd_wiregen.h | 6 +- lightningd/closing_control.c | 49 ++++++++-------- 7 files changed, 134 insertions(+), 65 deletions(-) diff --git a/bitcoin/tx.c b/bitcoin/tx.c index 6e3002ce3..5dac3209f 100644 --- a/bitcoin/tx.c +++ b/bitcoin/tx.c @@ -399,6 +399,19 @@ void bitcoin_tx_input_get_txid(const struct bitcoin_tx *tx, int innum, wally_tx_input_get_txid(&tx->wtx->inputs[innum], out); } +void bitcoin_tx_input_set_txid(struct bitcoin_tx *tx, int innum, + const struct bitcoin_txid *txid, + u32 index) +{ + struct wally_tx_input *in; + assert(innum < tx->wtx->num_inputs); + + in = &tx->wtx->inputs[innum]; + BUILD_ASSERT(sizeof(struct bitcoin_txid) == sizeof(in->txhash)); + memcpy(in->txhash, txid, sizeof(struct bitcoin_txid)); + in->index = index; +} + void wally_tx_input_get_txid(const struct wally_tx_input *in, struct bitcoin_txid *txid) { diff --git a/bitcoin/tx.h b/bitcoin/tx.h index 713b777e3..3f941cee5 100644 --- a/bitcoin/tx.h +++ b/bitcoin/tx.h @@ -201,6 +201,13 @@ void bitcoin_tx_input_get_txid(const struct bitcoin_tx *tx, int innum, void wally_tx_input_get_txid(const struct wally_tx_input *in, struct bitcoin_txid *txid); +/** + * Overwrite the txhash and index in the wally_tx_input + */ +void bitcoin_tx_input_set_txid(struct bitcoin_tx *tx, int innum, + const struct bitcoin_txid *txid, + u32 index); + /** * Check a transaction for consistency. * diff --git a/closingd/closingd.c b/closingd/closingd.c index 4693ba936..569c3ed0c 100644 --- a/closingd/closingd.c +++ b/closingd/closingd.c @@ -43,7 +43,8 @@ static struct bitcoin_tx *close_tx(const tal_t *ctx, const struct amount_sat out[NUM_SIDES], enum side opener, struct amount_sat fee, - struct amount_sat dust_limit) + struct amount_sat dust_limit, + const struct bitcoin_outpoint *wrong_funding) { struct bitcoin_tx *tx; struct amount_sat out_minus_fee[NUM_SIDES]; @@ -88,6 +89,12 @@ static struct bitcoin_tx *close_tx(const tal_t *ctx, type_to_string(tmpctx, struct amount_sat, &dust_limit), type_to_string(tmpctx, struct amount_sat, &out[LOCAL]), type_to_string(tmpctx, struct amount_sat, &out[REMOTE])); + + if (wrong_funding) + bitcoin_tx_input_set_txid(tx, 0, + &wrong_funding->txid, + wrong_funding->n); + return tx; } @@ -148,13 +155,15 @@ static void do_reconnect(struct per_peer_state *pps, u64 revocations_received, const u8 *channel_reestablish, const u8 *final_scriptpubkey, - const struct secret *last_remote_per_commit_secret) + const struct secret *last_remote_per_commit_secret, + const struct bitcoin_outpoint *wrong_funding) { u8 *msg; struct channel_id their_channel_id; u64 next_local_commitment_number, next_remote_revocation_number; struct pubkey my_current_per_commitment_point, next_commitment_point; struct secret their_secret; + struct tlv_shutdown_tlvs *tlvs; my_current_per_commitment_point = get_per_commitment_point(next_index[LOCAL]-1); @@ -218,8 +227,16 @@ static void do_reconnect(struct per_peer_state *pps, * - if it has sent a previous `shutdown`: * - MUST retransmit `shutdown`. */ - /* FIXME: retransmit wrong_funding */ - msg = towire_shutdown(NULL, channel_id, final_scriptpubkey, NULL); + if (wrong_funding) { + tlvs = tlv_shutdown_tlvs_new(tmpctx); + tlvs->wrong_funding + = tal(tlvs, struct tlv_shutdown_tlvs_wrong_funding); + tlvs->wrong_funding->txid = wrong_funding->txid; + tlvs->wrong_funding->outnum = wrong_funding->n; + } else + tlvs = NULL; + + msg = towire_shutdown(NULL, channel_id, final_scriptpubkey, tlvs); sync_crypto_write(pps, take(msg)); /* BOLT #2: @@ -250,7 +267,8 @@ static void send_offer(struct per_peer_state *pps, const struct amount_sat out[NUM_SIDES], enum side opener, struct amount_sat our_dust_limit, - struct amount_sat fee_to_offer) + struct amount_sat fee_to_offer, + const struct bitcoin_outpoint *wrong_funding) { struct bitcoin_tx *tx; struct bitcoin_signature our_sig; @@ -269,7 +287,8 @@ static void send_offer(struct per_peer_state *pps, funding, funding_wscript, out, - opener, fee_to_offer, our_dust_limit); + opener, fee_to_offer, our_dust_limit, + wrong_funding); /* BOLT #3: * @@ -329,6 +348,7 @@ receive_offer(struct per_peer_state *pps, enum side opener, struct amount_sat our_dust_limit, struct amount_sat min_fee_to_accept, + const struct bitcoin_outpoint *wrong_funding, struct bitcoin_txid *closing_txid) { u8 *msg; @@ -379,7 +399,8 @@ receive_offer(struct per_peer_state *pps, funding_txout, funding, funding_wscript, - out, opener, received_fee, our_dust_limit); + out, opener, received_fee, our_dust_limit, + wrong_funding); if (!check_tx_sig(tx, 0, NULL, funding_wscript, &funding_pubkey[REMOTE], &their_sig)) { @@ -410,7 +431,8 @@ receive_offer(struct per_peer_state *pps, funding, funding_wscript, trimming_out, - opener, received_fee, our_dust_limit); + opener, received_fee, our_dust_limit, + wrong_funding); if (!trimmed || !check_tx_sig(trimmed, 0, NULL, funding_wscript, &funding_pubkey[REMOTE], &their_sig)) { @@ -619,6 +641,7 @@ int main(int argc, char *argv[]) enum side whose_turn; u8 *channel_reestablish; struct secret last_remote_per_commit_secret; + struct bitcoin_outpoint *wrong_funding; subdaemon_setup(argc, argv); @@ -626,30 +649,31 @@ int main(int argc, char *argv[]) msg = wire_sync_read(tmpctx, REQ_FD); if (!fromwire_closingd_init(ctx, msg, - &chainparams, - &pps, - &channel_id, - &funding_txid, &funding_txout, - &funding, - &funding_pubkey[LOCAL], - &funding_pubkey[REMOTE], - &opener, - &out[LOCAL], - &out[REMOTE], - &our_dust_limit, - &min_fee_to_accept, &commitment_fee, - &offer[LOCAL], - &scriptpubkey[LOCAL], - &scriptpubkey[REMOTE], - &fee_negotiation_step, - &fee_negotiation_step_unit, - &reconnected, - &next_index[LOCAL], - &next_index[REMOTE], - &revocations_received, - &channel_reestablish, - &last_remote_per_commit_secret, - &dev_fast_gossip)) + &chainparams, + &pps, + &channel_id, + &funding_txid, &funding_txout, + &funding, + &funding_pubkey[LOCAL], + &funding_pubkey[REMOTE], + &opener, + &out[LOCAL], + &out[REMOTE], + &our_dust_limit, + &min_fee_to_accept, &commitment_fee, + &offer[LOCAL], + &scriptpubkey[LOCAL], + &scriptpubkey[REMOTE], + &fee_negotiation_step, + &fee_negotiation_step_unit, + &reconnected, + &next_index[LOCAL], + &next_index[REMOTE], + &revocations_received, + &channel_reestablish, + &last_remote_per_commit_secret, + &dev_fast_gossip, + &wrong_funding)) master_badmsg(WIRE_CLOSINGD_INIT, msg); /* stdin == requests, 3 == peer, 4 = gossip, 5 = gossip_store, 6 = hsmd */ @@ -670,6 +694,11 @@ int main(int argc, char *argv[]) status_debug("fee = %s", type_to_string(tmpctx, struct amount_sat, &offer[LOCAL])); status_debug("fee negotiation step = %s", fee_negotiation_step_str); + if (wrong_funding) + status_unusual("Setting wrong_funding_txid to %s:%u", + type_to_string(tmpctx, struct bitcoin_txid, + &wrong_funding->txid), + wrong_funding->n); funding_wscript = bitcoin_redeem_2of2(ctx, &funding_pubkey[LOCAL], @@ -679,7 +708,8 @@ int main(int argc, char *argv[]) do_reconnect(pps, &channel_id, next_index, revocations_received, channel_reestablish, scriptpubkey[LOCAL], - &last_remote_per_commit_secret); + &last_remote_per_commit_secret, + wrong_funding); peer_billboard( true, @@ -705,7 +735,8 @@ int main(int argc, char *argv[]) scriptpubkey, &funding_txid, funding_txout, funding, out, opener, our_dust_limit, - offer[LOCAL]); + offer[LOCAL], + wrong_funding); } else { if (i == 0) peer_billboard(false, "Waiting for their initial" @@ -726,6 +757,7 @@ int main(int argc, char *argv[]) out, opener, our_dust_limit, min_fee_to_accept, + wrong_funding, &closing_txid); } } @@ -754,7 +786,8 @@ int main(int argc, char *argv[]) scriptpubkey, &funding_txid, funding_txout, funding, out, opener, our_dust_limit, - offer[LOCAL]); + offer[LOCAL], + wrong_funding); } else { peer_billboard(false, "Waiting for another" " closing fee offer:" @@ -770,6 +803,7 @@ int main(int argc, char *argv[]) out, opener, our_dust_limit, min_fee_to_accept, + wrong_funding, &closing_txid); } @@ -782,6 +816,7 @@ int main(int argc, char *argv[]) #if DEVELOPER /* We don't listen for master commands, so always check memleak here */ + tal_free(wrong_funding); closing_dev_memleak(ctx, scriptpubkey, funding_wscript); #endif diff --git a/closingd/closingd_wire.csv b/closingd/closingd_wire.csv index 5094119c8..c6f7ea07f 100644 --- a/closingd/closingd_wire.csv +++ b/closingd/closingd_wire.csv @@ -34,6 +34,7 @@ msgdata,closingd_init,channel_reestablish_len,u16, msgdata,closingd_init,channel_reestablish,u8,channel_reestablish_len msgdata,closingd_init,last_remote_secret,secret, msgdata,closingd_init,dev_fast_gossip,bool, +msgdata,closingd_init,shutdown_wrong_funding,?bitcoin_outpoint, # We received an offer, save signature. msgtype,closingd_received_signature,2002 diff --git a/closingd/closingd_wiregen.c b/closingd/closingd_wiregen.c index eabe04049..91f2693f8 100644 --- a/closingd/closingd_wiregen.c +++ b/closingd/closingd_wiregen.c @@ -48,7 +48,7 @@ bool closingd_wire_is_defined(u16 type) /* WIRE: CLOSINGD_INIT */ /* Begin! (passes peer fd */ -u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, struct amount_sat min_fee_satoshi, struct amount_sat fee_limit_satoshi, struct amount_sat initial_fee_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool reconnected, u64 next_index_local, u64 next_index_remote, u64 revocations_received, const u8 *channel_reestablish, const struct secret *last_remote_secret, bool dev_fast_gossip) +u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, struct amount_sat min_fee_satoshi, struct amount_sat fee_limit_satoshi, struct amount_sat initial_fee_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool reconnected, u64 next_index_local, u64 next_index_remote, u64 revocations_received, const u8 *channel_reestablish, const struct secret *last_remote_secret, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding) { u16 local_scriptpubkey_len = tal_count(local_scriptpubkey); u16 remote_scriptpubkey_len = tal_count(remote_scriptpubkey); @@ -85,10 +85,16 @@ u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams towire_u8_array(&p, channel_reestablish, channel_reestablish_len); towire_secret(&p, last_remote_secret); towire_bool(&p, dev_fast_gossip); + if (!shutdown_wrong_funding) + towire_bool(&p, false); + else { + towire_bool(&p, true); + towire_bitcoin_outpoint(&p, shutdown_wrong_funding); + } return memcheck(p, tal_count(p)); } -bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, struct amount_sat *min_fee_satoshi, struct amount_sat *fee_limit_satoshi, struct amount_sat *initial_fee_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *reconnected, u64 *next_index_local, u64 *next_index_remote, u64 *revocations_received, u8 **channel_reestablish, struct secret *last_remote_secret, bool *dev_fast_gossip) +bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, struct amount_sat *min_fee_satoshi, struct amount_sat *fee_limit_satoshi, struct amount_sat *initial_fee_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *reconnected, u64 *next_index_local, u64 *next_index_remote, u64 *revocations_received, u8 **channel_reestablish, struct secret *last_remote_secret, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding) { u16 local_scriptpubkey_len; u16 remote_scriptpubkey_len; @@ -134,6 +140,12 @@ bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainp fromwire_u8_array(&cursor, &plen, *channel_reestablish, channel_reestablish_len); fromwire_secret(&cursor, &plen, last_remote_secret); *dev_fast_gossip = fromwire_bool(&cursor, &plen); + if (!fromwire_bool(&cursor, &plen)) + *shutdown_wrong_funding = NULL; + else { + *shutdown_wrong_funding = tal(ctx, struct bitcoin_outpoint); + fromwire_bitcoin_outpoint(&cursor, &plen, *shutdown_wrong_funding); + } return cursor != NULL; } @@ -201,4 +213,4 @@ bool fromwire_closingd_complete(const void *p) return false; return cursor != NULL; } -// SHA256STAMP:196786d8f37f20c93162a33692b7caddc638a48d4ec15c1a9bc09bbec41da360 +// SHA256STAMP:95043321951ace6f7a5ee9f1dc0ae57c8a6427644b8b79d3e08e521dc9b3b49f diff --git a/closingd/closingd_wiregen.h b/closingd/closingd_wiregen.h index 7423051a8..ea2aa4f2e 100644 --- a/closingd/closingd_wiregen.h +++ b/closingd/closingd_wiregen.h @@ -37,8 +37,8 @@ bool closingd_wire_is_defined(u16 type); /* WIRE: CLOSINGD_INIT */ /* Begin! (passes peer fd */ -u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, struct amount_sat min_fee_satoshi, struct amount_sat fee_limit_satoshi, struct amount_sat initial_fee_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool reconnected, u64 next_index_local, u64 next_index_remote, u64 revocations_received, const u8 *channel_reestablish, const struct secret *last_remote_secret, bool dev_fast_gossip); -bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, struct amount_sat *min_fee_satoshi, struct amount_sat *fee_limit_satoshi, struct amount_sat *initial_fee_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *reconnected, u64 *next_index_local, u64 *next_index_remote, u64 *revocations_received, u8 **channel_reestablish, struct secret *last_remote_secret, bool *dev_fast_gossip); +u8 *towire_closingd_init(const tal_t *ctx, const struct chainparams *chainparams, const struct per_peer_state *pps, const struct channel_id *channel_id, const struct bitcoin_txid *funding_txid, u16 funding_txout, struct amount_sat funding_satoshi, const struct pubkey *local_fundingkey, const struct pubkey *remote_fundingkey, enum side opener, struct amount_sat local_sat, struct amount_sat remote_sat, struct amount_sat our_dust_limit, struct amount_sat min_fee_satoshi, struct amount_sat fee_limit_satoshi, struct amount_sat initial_fee_satoshi, const u8 *local_scriptpubkey, const u8 *remote_scriptpubkey, u64 fee_negotiation_step, u8 fee_negotiation_step_unit, bool reconnected, u64 next_index_local, u64 next_index_remote, u64 revocations_received, const u8 *channel_reestablish, const struct secret *last_remote_secret, bool dev_fast_gossip, const struct bitcoin_outpoint *shutdown_wrong_funding); +bool fromwire_closingd_init(const tal_t *ctx, const void *p, const struct chainparams **chainparams, struct per_peer_state **pps, struct channel_id *channel_id, struct bitcoin_txid *funding_txid, u16 *funding_txout, struct amount_sat *funding_satoshi, struct pubkey *local_fundingkey, struct pubkey *remote_fundingkey, enum side *opener, struct amount_sat *local_sat, struct amount_sat *remote_sat, struct amount_sat *our_dust_limit, struct amount_sat *min_fee_satoshi, struct amount_sat *fee_limit_satoshi, struct amount_sat *initial_fee_satoshi, u8 **local_scriptpubkey, u8 **remote_scriptpubkey, u64 *fee_negotiation_step, u8 *fee_negotiation_step_unit, bool *reconnected, u64 *next_index_local, u64 *next_index_remote, u64 *revocations_received, u8 **channel_reestablish, struct secret *last_remote_secret, bool *dev_fast_gossip, struct bitcoin_outpoint **shutdown_wrong_funding); /* WIRE: CLOSINGD_RECEIVED_SIGNATURE */ /* We received an offer */ @@ -56,4 +56,4 @@ bool fromwire_closingd_complete(const void *p); #endif /* LIGHTNING_CLOSINGD_CLOSINGD_WIREGEN_H */ -// SHA256STAMP:196786d8f37f20c93162a33692b7caddc638a48d4ec15c1a9bc09bbec41da360 +// SHA256STAMP:95043321951ace6f7a5ee9f1dc0ae57c8a6427644b8b79d3e08e521dc9b3b49f diff --git a/lightningd/closing_control.c b/lightningd/closing_control.c index 31b44c9ed..813d069fb 100644 --- a/lightningd/closing_control.c +++ b/lightningd/closing_control.c @@ -286,30 +286,31 @@ void peer_start_closingd(struct channel *channel, return; } initmsg = towire_closingd_init(tmpctx, - chainparams, - pps, - &channel->cid, - &channel->funding_txid, - channel->funding_outnum, - channel->funding, - &channel->local_funding_pubkey, - &channel->channel_info.remote_fundingkey, - channel->opener, - amount_msat_to_sat_round_down(channel->our_msat), - amount_msat_to_sat_round_down(their_msat), - channel->our_config.dust_limit, - minfee, feelimit, startfee, - channel->shutdown_scriptpubkey[LOCAL], - channel->shutdown_scriptpubkey[REMOTE], - channel->closing_fee_negotiation_step, - channel->closing_fee_negotiation_step_unit, - reconnected, - channel->next_index[LOCAL], - channel->next_index[REMOTE], - num_revocations, - channel_reestablish, - &last_remote_per_commit_secret, - IFDEV(ld->dev_fast_gossip, false)); + chainparams, + pps, + &channel->cid, + &channel->funding_txid, + channel->funding_outnum, + channel->funding, + &channel->local_funding_pubkey, + &channel->channel_info.remote_fundingkey, + channel->opener, + amount_msat_to_sat_round_down(channel->our_msat), + amount_msat_to_sat_round_down(their_msat), + channel->our_config.dust_limit, + minfee, feelimit, startfee, + channel->shutdown_scriptpubkey[LOCAL], + channel->shutdown_scriptpubkey[REMOTE], + channel->closing_fee_negotiation_step, + channel->closing_fee_negotiation_step_unit, + reconnected, + channel->next_index[LOCAL], + channel->next_index[REMOTE], + num_revocations, + channel_reestablish, + &last_remote_per_commit_secret, + IFDEV(ld->dev_fast_gossip, false), + channel->shutdown_wrong_funding); /* We don't expect a response: it will give us feedback on * signatures sent and received, then closing_complete. */