From fe688ab7188b3b22f972f08d9d9346a24cb9b53f Mon Sep 17 00:00:00 2001 From: niftynei Date: Mon, 25 Jan 2021 12:32:02 -0600 Subject: [PATCH] df: revert channel state in dualopend Now that RBF's are possible, we revert the channel's state after a failure to the previous channel info. --- openingd/dualopend.c | 133 +++++++++++++++++++++++++++++++------------ 1 file changed, 98 insertions(+), 35 deletions(-) diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 831d06c35..9daa4b09e 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -1467,6 +1467,48 @@ static bool run_tx_interactive(struct state *state, return true; } +/* If there's a failure, we reset the state to the last + * valid channel */ +static void revert_channel_state(struct state *state) +{ + struct tx_state *tx_state = state->tx_state; + struct amount_sat total; + struct amount_msat our_msats; + enum side opener = state->our_role == TX_INITIATOR ? LOCAL : REMOTE; + + /* We've already checked this */ + if (!amount_sat_add(&total, tx_state->opener_funding, + tx_state->accepter_funding)) + abort(); + + /* We've already checked this */ + if (!amount_sat_to_msat(&our_msats, + state->our_role == TX_INITIATOR ? + tx_state->opener_funding : + tx_state->accepter_funding)) + abort(); + + tal_free(state->channel); + state->channel = new_initial_channel(state, + &state->channel_id, + &tx_state->funding_txid, + tx_state->funding_txout, + state->minimum_depth, + total, + our_msats, + take(new_fee_states( + NULL, opener, + &state->feerate_per_kw_commitment)), + &tx_state->localconf, + &tx_state->remoteconf, + &state->our_points, + &state->their_points, + &state->our_funding_pubkey, + &state->their_funding_pubkey, + true, true, + opener); +} + /* Returns NULL on negotation failure; reason given as *err_reason * In case that negotiation_aborted called, *err_reason set NULL */ static u8 *accepter_commits(struct state *state, @@ -1544,6 +1586,9 @@ static u8 *accepter_commits(struct state *state, "Overflow converting accepter_funding " "to msats"); + if (state->channel) + state->channel = tal_free(state->channel); + state->channel = new_initial_channel(state, &state->channel_id, &tx_state->funding_txid, @@ -1571,6 +1616,7 @@ static u8 *accepter_commits(struct state *state, if (!local_commit) { *err_reason = tal_fmt(tmpctx, "Could not meet our fees" " and reserve: %s", error); + revert_channel_state(state); return NULL; } @@ -1596,21 +1642,27 @@ static u8 *accepter_commits(struct state *state, * a courtesy to other implementaters whose brains may be so * twisted by coding in Go, Scala and Rust that they can no * longer read C code. */ - peer_failed_err(state->pps, &state->channel_id, - "Bad signature %s on tx %s using key %s" - " (funding txid %s, psbt %s)", - type_to_string(tmpctx, struct bitcoin_signature, - &remote_sig), - type_to_string(tmpctx, struct bitcoin_tx, - local_commit), - type_to_string(tmpctx, struct pubkey, - &state->their_funding_pubkey), - /* This is the first place we'd discover - * * the funding tx doesn't match up */ - type_to_string(tmpctx, struct bitcoin_txid, - &tx_state->funding_txid), - type_to_string(tmpctx, struct wally_psbt, - tx_state->psbt)); + *err_reason = tal_fmt(tmpctx, + "Bad signature %s on tx %s using key %s" + " (funding txid %s, psbt %s)", + type_to_string(tmpctx, + struct bitcoin_signature, + &remote_sig), + type_to_string(tmpctx, + struct bitcoin_tx, + local_commit), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + /* This is the first place we'd discover + * the funding tx doesn't match up */ + type_to_string(tmpctx, + struct bitcoin_txid, + &tx_state->funding_txid), + type_to_string(tmpctx, + struct wally_psbt, + tx_state->psbt)); + revert_channel_state(state); + return NULL; } /* Create commitment tx signatures for remote */ @@ -1621,6 +1673,7 @@ static u8 *accepter_commits(struct state *state, if (!remote_commit) { *err_reason = tal_fmt(tmpctx, "Could not meet their fees" " and reserve: %s", error); + revert_channel_state(state); return NULL; } @@ -2021,6 +2074,7 @@ static u8 *opener_commits(struct state *state, if (!remote_commit) { *err_reason = tal_fmt(tmpctx, "Could not meet their fees" " and reserve: %s", error); + revert_channel_state(state); return NULL; } @@ -2060,6 +2114,7 @@ static u8 *opener_commits(struct state *state, msg = opening_negotiate_msg(tmpctx, state); if (!msg) { *err_reason = NULL; + revert_channel_state(state); return NULL; } @@ -2071,11 +2126,12 @@ static u8 *opener_commits(struct state *state, "Parsing commitment signed %s", tal_hex(tmpctx, msg)); - if (htlc_sigs != NULL) - peer_failed_warn(state->pps, &state->channel_id, - "Must not send HTLCs with first" - " commitment. %s", - tal_hex(tmpctx, msg)); + if (htlc_sigs != NULL) { + *err_reason = tal_fmt(tmpctx, "Must not send HTLCs with first" + " commitment. %s", tal_hex(tmpctx, msg)); + revert_channel_state(state); + return NULL; + } local_commit = initial_channel_tx(state, &wscript, state->channel, &state->first_per_commitment_point[LOCAL], @@ -2086,6 +2142,7 @@ static u8 *opener_commits(struct state *state, if (!local_commit) { *err_reason = tal_fmt(tmpctx, "Could not meet our fees" " and reserve: %s", error); + revert_channel_state(state); return NULL; } @@ -2112,21 +2169,27 @@ static u8 *opener_commits(struct state *state, * a courtesy to other implementaters whose brains may be so * twisted by coding in Go, Scala and Rust that they can no * longer read C code. */ - peer_failed_err(state->pps, &state->channel_id, - "Bad signature %s on tx %s using key %s " - "(funding txid %s, psbt %s)", - type_to_string(tmpctx, struct bitcoin_signature, - &remote_sig), - type_to_string(tmpctx, struct bitcoin_tx, - local_commit), - type_to_string(tmpctx, struct pubkey, - &state->their_funding_pubkey), - /* This is the first place we'd discover the - * * funding tx doesn't match up */ - type_to_string(tmpctx, struct bitcoin_txid, - &tx_state->funding_txid), - type_to_string(tmpctx, struct wally_psbt, - tx_state->psbt)); + *err_reason = tal_fmt(tmpctx, + "Bad signature %s on tx %s using key %s " + "(funding txid %s, psbt %s)", + type_to_string(tmpctx, + struct bitcoin_signature, + &remote_sig), + type_to_string(tmpctx, + struct bitcoin_tx, + local_commit), + type_to_string(tmpctx, struct pubkey, + &state->their_funding_pubkey), + /* This is the first place we'd discover the + * funding tx doesn't match up */ + type_to_string(tmpctx, + struct bitcoin_txid, + &tx_state->funding_txid), + type_to_string(tmpctx, + struct wally_psbt, + tx_state->psbt)); + revert_channel_state(state); + return NULL; } if (direct_outputs[LOCAL])