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.
This commit is contained in:
niftynei 2021-01-25 12:32:02 -06:00 committed by neil saitug
parent cf170c3909
commit fe688ab718

View File

@ -1467,6 +1467,48 @@ static bool run_tx_interactive(struct state *state,
return true; 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 /* Returns NULL on negotation failure; reason given as *err_reason
* In case that negotiation_aborted called, *err_reason set NULL */ * In case that negotiation_aborted called, *err_reason set NULL */
static u8 *accepter_commits(struct state *state, static u8 *accepter_commits(struct state *state,
@ -1544,6 +1586,9 @@ static u8 *accepter_commits(struct state *state,
"Overflow converting accepter_funding " "Overflow converting accepter_funding "
"to msats"); "to msats");
if (state->channel)
state->channel = tal_free(state->channel);
state->channel = new_initial_channel(state, state->channel = new_initial_channel(state,
&state->channel_id, &state->channel_id,
&tx_state->funding_txid, &tx_state->funding_txid,
@ -1571,6 +1616,7 @@ static u8 *accepter_commits(struct state *state,
if (!local_commit) { if (!local_commit) {
*err_reason = tal_fmt(tmpctx, "Could not meet our fees" *err_reason = tal_fmt(tmpctx, "Could not meet our fees"
" and reserve: %s", error); " and reserve: %s", error);
revert_channel_state(state);
return NULL; return NULL;
} }
@ -1596,21 +1642,27 @@ static u8 *accepter_commits(struct state *state,
* a courtesy to other implementaters whose brains may be so * a courtesy to other implementaters whose brains may be so
* twisted by coding in Go, Scala and Rust that they can no * twisted by coding in Go, Scala and Rust that they can no
* longer read C code. */ * longer read C code. */
peer_failed_err(state->pps, &state->channel_id, *err_reason = tal_fmt(tmpctx,
"Bad signature %s on tx %s using key %s" "Bad signature %s on tx %s using key %s"
" (funding txid %s, psbt %s)", " (funding txid %s, psbt %s)",
type_to_string(tmpctx, struct bitcoin_signature, type_to_string(tmpctx,
&remote_sig), struct bitcoin_signature,
type_to_string(tmpctx, struct bitcoin_tx, &remote_sig),
local_commit), type_to_string(tmpctx,
type_to_string(tmpctx, struct pubkey, struct bitcoin_tx,
&state->their_funding_pubkey), local_commit),
/* This is the first place we'd discover type_to_string(tmpctx, struct pubkey,
* * the funding tx doesn't match up */ &state->their_funding_pubkey),
type_to_string(tmpctx, struct bitcoin_txid, /* This is the first place we'd discover
&tx_state->funding_txid), * the funding tx doesn't match up */
type_to_string(tmpctx, struct wally_psbt, type_to_string(tmpctx,
tx_state->psbt)); 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 */ /* Create commitment tx signatures for remote */
@ -1621,6 +1673,7 @@ static u8 *accepter_commits(struct state *state,
if (!remote_commit) { if (!remote_commit) {
*err_reason = tal_fmt(tmpctx, "Could not meet their fees" *err_reason = tal_fmt(tmpctx, "Could not meet their fees"
" and reserve: %s", error); " and reserve: %s", error);
revert_channel_state(state);
return NULL; return NULL;
} }
@ -2021,6 +2074,7 @@ static u8 *opener_commits(struct state *state,
if (!remote_commit) { if (!remote_commit) {
*err_reason = tal_fmt(tmpctx, "Could not meet their fees" *err_reason = tal_fmt(tmpctx, "Could not meet their fees"
" and reserve: %s", error); " and reserve: %s", error);
revert_channel_state(state);
return NULL; return NULL;
} }
@ -2060,6 +2114,7 @@ static u8 *opener_commits(struct state *state,
msg = opening_negotiate_msg(tmpctx, state); msg = opening_negotiate_msg(tmpctx, state);
if (!msg) { if (!msg) {
*err_reason = NULL; *err_reason = NULL;
revert_channel_state(state);
return NULL; return NULL;
} }
@ -2071,11 +2126,12 @@ static u8 *opener_commits(struct state *state,
"Parsing commitment signed %s", "Parsing commitment signed %s",
tal_hex(tmpctx, msg)); tal_hex(tmpctx, msg));
if (htlc_sigs != NULL) if (htlc_sigs != NULL) {
peer_failed_warn(state->pps, &state->channel_id, *err_reason = tal_fmt(tmpctx, "Must not send HTLCs with first"
"Must not send HTLCs with first" " commitment. %s", tal_hex(tmpctx, msg));
" commitment. %s", revert_channel_state(state);
tal_hex(tmpctx, msg)); return NULL;
}
local_commit = initial_channel_tx(state, &wscript, state->channel, local_commit = initial_channel_tx(state, &wscript, state->channel,
&state->first_per_commitment_point[LOCAL], &state->first_per_commitment_point[LOCAL],
@ -2086,6 +2142,7 @@ static u8 *opener_commits(struct state *state,
if (!local_commit) { if (!local_commit) {
*err_reason = tal_fmt(tmpctx, "Could not meet our fees" *err_reason = tal_fmt(tmpctx, "Could not meet our fees"
" and reserve: %s", error); " and reserve: %s", error);
revert_channel_state(state);
return NULL; return NULL;
} }
@ -2112,21 +2169,27 @@ static u8 *opener_commits(struct state *state,
* a courtesy to other implementaters whose brains may be so * a courtesy to other implementaters whose brains may be so
* twisted by coding in Go, Scala and Rust that they can no * twisted by coding in Go, Scala and Rust that they can no
* longer read C code. */ * longer read C code. */
peer_failed_err(state->pps, &state->channel_id, *err_reason = tal_fmt(tmpctx,
"Bad signature %s on tx %s using key %s " "Bad signature %s on tx %s using key %s "
"(funding txid %s, psbt %s)", "(funding txid %s, psbt %s)",
type_to_string(tmpctx, struct bitcoin_signature, type_to_string(tmpctx,
&remote_sig), struct bitcoin_signature,
type_to_string(tmpctx, struct bitcoin_tx, &remote_sig),
local_commit), type_to_string(tmpctx,
type_to_string(tmpctx, struct pubkey, struct bitcoin_tx,
&state->their_funding_pubkey), local_commit),
/* This is the first place we'd discover the type_to_string(tmpctx, struct pubkey,
* * funding tx doesn't match up */ &state->their_funding_pubkey),
type_to_string(tmpctx, struct bitcoin_txid, /* This is the first place we'd discover the
&tx_state->funding_txid), * funding tx doesn't match up */
type_to_string(tmpctx, struct wally_psbt, type_to_string(tmpctx,
tx_state->psbt)); 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]) if (direct_outputs[LOCAL])