mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-03-12 18:49:42 +01:00
dual-fund: add require_confirmed_inputs
to RBF flows
We now require peers to reaffirm their preference for `require_confirmed_inputs` when executing an RBF. Requested-By: @t-bast
This commit is contained in:
parent
e72be90606
commit
bc98cafe9e
8 changed files with 98 additions and 14 deletions
|
@ -543,6 +543,13 @@ static void rbf_channel_hook_cb(struct rbf_channel_payload *payload STEALS)
|
||||||
return subd_send_msg(dualopend, take(msg));
|
return subd_send_msg(dualopend, take(msg));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Update the remote's require confirmed preferences */
|
||||||
|
if (payload->req_confirmed_ins_remote != channel->req_confirmed_ins[REMOTE]) {
|
||||||
|
channel->req_confirmed_ins[REMOTE] =
|
||||||
|
payload->req_confirmed_ins_remote;
|
||||||
|
wallet_channel_save(dualopend->ld->wallet, channel);
|
||||||
|
}
|
||||||
|
|
||||||
/* Update channel with new open attempt. */
|
/* Update channel with new open attempt. */
|
||||||
channel->open_attempt = new_channel_open_attempt(channel);
|
channel->open_attempt = new_channel_open_attempt(channel);
|
||||||
msg = towire_dualopend_got_rbf_offer_reply(NULL,
|
msg = towire_dualopend_got_rbf_offer_reply(NULL,
|
||||||
|
@ -2002,7 +2009,8 @@ static void rbf_got_offer(struct subd *dualopend, const u8 *msg)
|
||||||
&payload->our_last_funding,
|
&payload->our_last_funding,
|
||||||
&payload->funding_feerate_per_kw,
|
&payload->funding_feerate_per_kw,
|
||||||
&payload->locktime,
|
&payload->locktime,
|
||||||
&payload->requested_lease_amt)) {
|
&payload->requested_lease_amt,
|
||||||
|
&payload->req_confirmed_ins_remote)) {
|
||||||
channel_internal_error(channel,
|
channel_internal_error(channel,
|
||||||
"Bad WIRE_DUALOPEND_GOT_RBF_OFFER: %s",
|
"Bad WIRE_DUALOPEND_GOT_RBF_OFFER: %s",
|
||||||
tal_hex(msg, msg));
|
tal_hex(msg, msg));
|
||||||
|
@ -2027,8 +2035,6 @@ static void rbf_got_offer(struct subd *dualopend, const u8 *msg)
|
||||||
payload->peer_id = channel->peer->id;
|
payload->peer_id = channel->peer->id;
|
||||||
payload->feerate_our_max = feerate_max(dualopend->ld, NULL);
|
payload->feerate_our_max = feerate_max(dualopend->ld, NULL);
|
||||||
payload->feerate_our_min = feerate_min(dualopend->ld, NULL);
|
payload->feerate_our_min = feerate_min(dualopend->ld, NULL);
|
||||||
payload->req_confirmed_ins_remote =
|
|
||||||
channel->req_confirmed_ins[REMOTE];
|
|
||||||
|
|
||||||
payload->psbt = NULL;
|
payload->psbt = NULL;
|
||||||
|
|
||||||
|
@ -3243,6 +3249,25 @@ done:
|
||||||
tal_free(pv);
|
tal_free(pv);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void handle_update_require_confirmed(struct subd *dualopend,
|
||||||
|
const u8 *msg)
|
||||||
|
{
|
||||||
|
bool require_confirmed;
|
||||||
|
struct channel *channel = dualopend->channel;
|
||||||
|
|
||||||
|
if (!fromwire_dualopend_update_require_confirmed(msg, &require_confirmed)) {
|
||||||
|
channel_internal_error(dualopend->channel,
|
||||||
|
"Bad DUALOPEND_UPDATE_REQUIRE_CONFIRMED: %s",
|
||||||
|
tal_hex(msg, msg));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (channel->req_confirmed_ins[REMOTE] != require_confirmed) {
|
||||||
|
channel->req_confirmed_ins[REMOTE] = require_confirmed;
|
||||||
|
wallet_channel_save(dualopend->ld->wallet, channel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void handle_validate_inputs(struct subd *dualopend,
|
static void handle_validate_inputs(struct subd *dualopend,
|
||||||
const u8 *msg)
|
const u8 *msg)
|
||||||
{
|
{
|
||||||
|
@ -3632,6 +3657,9 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||||
case WIRE_DUALOPEND_VALIDATE_INPUTS:
|
case WIRE_DUALOPEND_VALIDATE_INPUTS:
|
||||||
handle_validate_inputs(dualopend, msg);
|
handle_validate_inputs(dualopend, msg);
|
||||||
return 0;
|
return 0;
|
||||||
|
case WIRE_DUALOPEND_UPDATE_REQUIRE_CONFIRMED:
|
||||||
|
handle_update_require_confirmed(dualopend, msg);
|
||||||
|
return 0;
|
||||||
/* Messages we send */
|
/* Messages we send */
|
||||||
case WIRE_DUALOPEND_INIT:
|
case WIRE_DUALOPEND_INIT:
|
||||||
case WIRE_DUALOPEND_REINIT:
|
case WIRE_DUALOPEND_REINIT:
|
||||||
|
|
|
@ -3564,6 +3564,14 @@ static void rbf_local_start(struct state *state, u8 *msg)
|
||||||
*init_rbf_tlvs->funding_output_contribution
|
*init_rbf_tlvs->funding_output_contribution
|
||||||
= (s64)tx_state->opener_funding.satoshis; /* Raw: wire conversion */
|
= (s64)tx_state->opener_funding.satoshis; /* Raw: wire conversion */
|
||||||
|
|
||||||
|
|
||||||
|
/* We repeat whatever we used on initial open for requiring confirmed
|
||||||
|
* inputs */
|
||||||
|
if (state->require_confirmed_inputs[LOCAL])
|
||||||
|
init_rbf_tlvs->require_confirmed_inputs =
|
||||||
|
tal(init_rbf_tlvs, struct tlv_tx_init_rbf_tlvs_require_confirmed_inputs);
|
||||||
|
|
||||||
|
|
||||||
msg = towire_tx_init_rbf(tmpctx, &state->channel_id,
|
msg = towire_tx_init_rbf(tmpctx, &state->channel_id,
|
||||||
tx_state->tx_locktime,
|
tx_state->tx_locktime,
|
||||||
tx_state->feerate_per_kw_funding,
|
tx_state->feerate_per_kw_funding,
|
||||||
|
@ -3601,6 +3609,14 @@ static void rbf_local_start(struct state *state, u8 *msg)
|
||||||
} else
|
} else
|
||||||
tx_state->accepter_funding = state->tx_state->accepter_funding;
|
tx_state->accepter_funding = state->tx_state->accepter_funding;
|
||||||
|
|
||||||
|
/* Set the require_confirmed_inputs to whatever they set here */
|
||||||
|
if (ack_rbf_tlvs)
|
||||||
|
state->require_confirmed_inputs[REMOTE] =
|
||||||
|
ack_rbf_tlvs->require_confirmed_inputs != NULL;
|
||||||
|
else
|
||||||
|
/* They have to re-affirm to keep it! */
|
||||||
|
state->require_confirmed_inputs[REMOTE] = false;
|
||||||
|
|
||||||
/* Check that total funding doesn't overflow */
|
/* Check that total funding doesn't overflow */
|
||||||
if (!amount_sat_add(&total, tx_state->opener_funding,
|
if (!amount_sat_add(&total, tx_state->opener_funding,
|
||||||
tx_state->accepter_funding)) {
|
tx_state->accepter_funding)) {
|
||||||
|
@ -3672,6 +3688,11 @@ static void rbf_local_start(struct state *state, u8 *msg)
|
||||||
tal_free(state->tx_state);
|
tal_free(state->tx_state);
|
||||||
state->tx_state = tal_steal(state, tx_state);
|
state->tx_state = tal_steal(state, tx_state);
|
||||||
|
|
||||||
|
/* Notify lightningd about require_confirmed state */
|
||||||
|
msg = towire_dualopend_update_require_confirmed(NULL,
|
||||||
|
state->require_confirmed_inputs[REMOTE]);
|
||||||
|
wire_sync_write(REQ_FD, take(msg));
|
||||||
|
|
||||||
/* We merge with RBF's we've initiated now */
|
/* We merge with RBF's we've initiated now */
|
||||||
rbf_wrap_up(state, tx_state, total);
|
rbf_wrap_up(state, tx_state, total);
|
||||||
tal_free(rbf_ctx);
|
tal_free(rbf_ctx);
|
||||||
|
@ -3735,6 +3756,14 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
|
||||||
/* Otherwise we use the last known funding amount */
|
/* Otherwise we use the last known funding amount */
|
||||||
tx_state->opener_funding = state->tx_state->opener_funding;
|
tx_state->opener_funding = state->tx_state->opener_funding;
|
||||||
|
|
||||||
|
/* Set the require_confirmed_inputs to whatever they set here */
|
||||||
|
if (init_rbf_tlvs)
|
||||||
|
state->require_confirmed_inputs[REMOTE] =
|
||||||
|
init_rbf_tlvs->require_confirmed_inputs != NULL;
|
||||||
|
else
|
||||||
|
/* They have to re-affirm to keep it! */
|
||||||
|
state->require_confirmed_inputs[REMOTE] = false;
|
||||||
|
|
||||||
/* Copy over the channel config info -- everything except
|
/* Copy over the channel config info -- everything except
|
||||||
* the reserve will be the same */
|
* the reserve will be the same */
|
||||||
tx_state->localconf = state->tx_state->localconf;
|
tx_state->localconf = state->tx_state->localconf;
|
||||||
|
@ -3757,7 +3786,8 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
|
||||||
state->tx_state->accepter_funding,
|
state->tx_state->accepter_funding,
|
||||||
tx_state->feerate_per_kw_funding,
|
tx_state->feerate_per_kw_funding,
|
||||||
tx_state->tx_locktime,
|
tx_state->tx_locktime,
|
||||||
state->requested_lease);
|
state->requested_lease,
|
||||||
|
state->require_confirmed_inputs[REMOTE]);
|
||||||
|
|
||||||
wire_sync_write(REQ_FD, take(msg));
|
wire_sync_write(REQ_FD, take(msg));
|
||||||
msg = wire_sync_read(tmpctx, REQ_FD);
|
msg = wire_sync_read(tmpctx, REQ_FD);
|
||||||
|
@ -3833,6 +3863,11 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
|
||||||
*ack_rbf_tlvs->funding_output_contribution
|
*ack_rbf_tlvs->funding_output_contribution
|
||||||
= (s64)tx_state->accepter_funding.satoshis; /* Raw: wire conversion */
|
= (s64)tx_state->accepter_funding.satoshis; /* Raw: wire conversion */
|
||||||
|
|
||||||
|
/* We keep whatever we initially set at open for RBFs */
|
||||||
|
if (state->require_confirmed_inputs[LOCAL])
|
||||||
|
ack_rbf_tlvs->require_confirmed_inputs =
|
||||||
|
tal(ack_rbf_tlvs, struct tlv_tx_ack_rbf_tlvs_require_confirmed_inputs);
|
||||||
|
|
||||||
msg = towire_tx_ack_rbf(tmpctx, &state->channel_id, ack_rbf_tlvs);
|
msg = towire_tx_ack_rbf(tmpctx, &state->channel_id, ack_rbf_tlvs);
|
||||||
peer_write(state->pps, msg);
|
peer_write(state->pps, msg);
|
||||||
peer_billboard(false, "channel rbf: ack sent, waiting for reply");
|
peer_billboard(false, "channel rbf: ack sent, waiting for reply");
|
||||||
|
@ -4177,6 +4212,7 @@ static u8 *handle_master_in(struct state *state)
|
||||||
case WIRE_DUALOPEND_DRY_RUN:
|
case WIRE_DUALOPEND_DRY_RUN:
|
||||||
case WIRE_DUALOPEND_VALIDATE_LEASE:
|
case WIRE_DUALOPEND_VALIDATE_LEASE:
|
||||||
case WIRE_DUALOPEND_VALIDATE_INPUTS:
|
case WIRE_DUALOPEND_VALIDATE_INPUTS:
|
||||||
|
case WIRE_DUALOPEND_UPDATE_REQUIRE_CONFIRMED:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
status_failed(STATUS_FAIL_MASTER_IO,
|
status_failed(STATUS_FAIL_MASTER_IO,
|
||||||
|
|
|
@ -118,12 +118,17 @@ msgdata,dualopend_got_rbf_offer,our_last_funding,amount_sat,
|
||||||
msgdata,dualopend_got_rbf_offer,funding_feerate_per_kw,u32,
|
msgdata,dualopend_got_rbf_offer,funding_feerate_per_kw,u32,
|
||||||
msgdata,dualopend_got_rbf_offer,locktime,u32,
|
msgdata,dualopend_got_rbf_offer,locktime,u32,
|
||||||
msgdata,dualopend_got_rbf_offer,requested_lease,?amount_sat,
|
msgdata,dualopend_got_rbf_offer,requested_lease,?amount_sat,
|
||||||
|
msgdata,dualopend_got_rbf_offer,require_confirmed_inputs,bool,
|
||||||
|
|
||||||
# master->dualopend: reply back with our funding info/contribs
|
# master->dualopend: reply back with our funding info/contribs
|
||||||
msgtype,dualopend_got_rbf_offer_reply,7505
|
msgtype,dualopend_got_rbf_offer_reply,7505
|
||||||
msgdata,dualopend_got_rbf_offer_reply,our_funding,amount_sat,
|
msgdata,dualopend_got_rbf_offer_reply,our_funding,amount_sat,
|
||||||
msgdata,dualopend_got_rbf_offer_reply,psbt,wally_psbt,
|
msgdata,dualopend_got_rbf_offer_reply,psbt,wally_psbt,
|
||||||
|
|
||||||
|
# dualopend->master: update to require_confirmed_inputs preference
|
||||||
|
msgtype,dualopend_update_require_confirmed,7511
|
||||||
|
msgdata,dualopend_update_require_confirmed,require_confirmed_inputs,bool,
|
||||||
|
|
||||||
# dualopend->master: is this a valid RBF candidate transaction?
|
# dualopend->master: is this a valid RBF candidate transaction?
|
||||||
msgtype,dualopend_rbf_validate,7506
|
msgtype,dualopend_rbf_validate,7506
|
||||||
msgdata,dualopend_rbf_validate,proposed_funding_psbt,wally_psbt,
|
msgdata,dualopend_rbf_validate,proposed_funding_psbt,wally_psbt,
|
||||||
|
|
Can't render this file because it has a wrong number of fields in line 16.
|
|
@ -31,10 +31,14 @@ static bool equal(const struct tx_ack_rbf *x, const struct tx_ack_rbf *y)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert(x->tlvs && y->tlvs);
|
assert(x->tlvs && y->tlvs);
|
||||||
return memeq(x->tlvs->funding_output_contribution,
|
if (!memeq(x->tlvs->funding_output_contribution,
|
||||||
tal_bytelen(x->tlvs->funding_output_contribution),
|
tal_bytelen(x->tlvs->funding_output_contribution),
|
||||||
y->tlvs->funding_output_contribution,
|
y->tlvs->funding_output_contribution,
|
||||||
tal_bytelen(y->tlvs->funding_output_contribution));
|
tal_bytelen(y->tlvs->funding_output_contribution)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !!x->tlvs->require_confirmed_inputs ==
|
||||||
|
!!y->tlvs->require_confirmed_inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(const u8 *data, size_t size)
|
void run(const u8 *data, size_t size)
|
||||||
|
|
|
@ -36,10 +36,14 @@ static bool equal(const struct tx_init_rbf *x, const struct tx_init_rbf *y)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
assert(x->tlvs && y->tlvs);
|
assert(x->tlvs && y->tlvs);
|
||||||
return memeq(x->tlvs->funding_output_contribution,
|
if (!memeq(x->tlvs->funding_output_contribution,
|
||||||
tal_bytelen(x->tlvs->funding_output_contribution),
|
tal_bytelen(x->tlvs->funding_output_contribution),
|
||||||
y->tlvs->funding_output_contribution,
|
y->tlvs->funding_output_contribution,
|
||||||
tal_bytelen(y->tlvs->funding_output_contribution));
|
tal_bytelen(y->tlvs->funding_output_contribution)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return !!x->tlvs->require_confirmed_inputs ==
|
||||||
|
!!y->tlvs->require_confirmed_inputs;
|
||||||
}
|
}
|
||||||
|
|
||||||
void run(const u8 *data, size_t size)
|
void run(const u8 *data, size_t size)
|
||||||
|
|
|
@ -2286,9 +2286,10 @@ void wallet_channel_save(struct wallet *w, struct channel *chan)
|
||||||
" remote_feerate_ppm=?," // 48
|
" remote_feerate_ppm=?," // 48
|
||||||
" remote_cltv_expiry_delta=?," // 49
|
" remote_cltv_expiry_delta=?," // 49
|
||||||
" remote_htlc_minimum_msat=?," // 50
|
" remote_htlc_minimum_msat=?," // 50
|
||||||
" remote_htlc_maximum_msat=?,"
|
" remote_htlc_maximum_msat=?," // 51
|
||||||
" last_stable_connection=?"
|
" last_stable_connection=?" // 52
|
||||||
" WHERE id=?"));
|
" require_confirm_inputs_remote=?" // 53
|
||||||
|
" WHERE id=?")); // 54
|
||||||
db_bind_u64(stmt, chan->their_shachain.id);
|
db_bind_u64(stmt, chan->their_shachain.id);
|
||||||
if (chan->scid)
|
if (chan->scid)
|
||||||
db_bind_short_channel_id(stmt, chan->scid);
|
db_bind_short_channel_id(stmt, chan->scid);
|
||||||
|
@ -2385,6 +2386,8 @@ void wallet_channel_save(struct wallet *w, struct channel *chan)
|
||||||
db_bind_null(stmt);
|
db_bind_null(stmt);
|
||||||
}
|
}
|
||||||
db_bind_u64(stmt, chan->last_stable_connection);
|
db_bind_u64(stmt, chan->last_stable_connection);
|
||||||
|
|
||||||
|
db_bind_int(stmt, chan->req_confirmed_ins[REMOTE]);
|
||||||
db_bind_u64(stmt, chan->dbid);
|
db_bind_u64(stmt, chan->dbid);
|
||||||
db_exec_prepared_v2(take(stmt));
|
db_exec_prepared_v2(take(stmt));
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
--- wire/peer_wire.csv.raw 2023-09-11 13:32:30.677617251 +0930
|
--- wire/peer_wire.csv.raw 2023-09-11 13:32:30.677617251 +0930
|
||||||
+++ wire/peer_wire.csv.openchannel2 2023-09-11 13:31:47.906308397 +0930
|
+++ wire/peer_wire.csv.openchannel2 2023-09-11 13:31:47.906308397 +0930
|
||||||
@@ -37,6 +37,51 @@
|
@@ -37,6 +37,53 @@
|
||||||
tlvdata,n2,tlv1,amount_msat,tu64,
|
tlvdata,n2,tlv1,amount_msat,tu64,
|
||||||
tlvtype,n2,tlv2,11
|
tlvtype,n2,tlv2,11
|
||||||
tlvdata,n2,tlv2,cltv_expiry,tu32,
|
tlvdata,n2,tlv2,cltv_expiry,tu32,
|
||||||
|
@ -40,11 +40,13 @@
|
||||||
+msgdata,tx_init_rbf,tlvs,tx_init_rbf_tlvs,
|
+msgdata,tx_init_rbf,tlvs,tx_init_rbf_tlvs,
|
||||||
+tlvtype,tx_init_rbf_tlvs,funding_output_contribution,0
|
+tlvtype,tx_init_rbf_tlvs,funding_output_contribution,0
|
||||||
+tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
+tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
||||||
|
+tlvtype,tx_init_rbf_tlvs,require_confirmed_inputs,2
|
||||||
+msgtype,tx_ack_rbf,73
|
+msgtype,tx_ack_rbf,73
|
||||||
+msgdata,tx_ack_rbf,channel_id,channel_id,
|
+msgdata,tx_ack_rbf,channel_id,channel_id,
|
||||||
+msgdata,tx_ack_rbf,tlvs,tx_ack_rbf_tlvs,
|
+msgdata,tx_ack_rbf,tlvs,tx_ack_rbf_tlvs,
|
||||||
+tlvtype,tx_ack_rbf_tlvs,funding_output_contribution,0
|
+tlvtype,tx_ack_rbf_tlvs,funding_output_contribution,0
|
||||||
+tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
+tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
||||||
|
+tlvtype,tx_ack_rbf_tlvs,require_confirmed_inputs,2
|
||||||
+msgtype,tx_abort,74
|
+msgtype,tx_abort,74
|
||||||
+msgdata,tx_abort,channel_id,channel_id,
|
+msgdata,tx_abort,channel_id,channel_id,
|
||||||
+msgdata,tx_abort,len,u16,
|
+msgdata,tx_abort,len,u16,
|
||||||
|
|
|
@ -76,11 +76,13 @@ msgdata,tx_init_rbf,feerate,u32,
|
||||||
msgdata,tx_init_rbf,tlvs,tx_init_rbf_tlvs,
|
msgdata,tx_init_rbf,tlvs,tx_init_rbf_tlvs,
|
||||||
tlvtype,tx_init_rbf_tlvs,funding_output_contribution,0
|
tlvtype,tx_init_rbf_tlvs,funding_output_contribution,0
|
||||||
tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
tlvdata,tx_init_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
||||||
|
tlvtype,tx_init_rbf_tlvs,require_confirmed_inputs,2
|
||||||
msgtype,tx_ack_rbf,73
|
msgtype,tx_ack_rbf,73
|
||||||
msgdata,tx_ack_rbf,channel_id,channel_id,
|
msgdata,tx_ack_rbf,channel_id,channel_id,
|
||||||
msgdata,tx_ack_rbf,tlvs,tx_ack_rbf_tlvs,
|
msgdata,tx_ack_rbf,tlvs,tx_ack_rbf_tlvs,
|
||||||
tlvtype,tx_ack_rbf_tlvs,funding_output_contribution,0
|
tlvtype,tx_ack_rbf_tlvs,funding_output_contribution,0
|
||||||
tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
tlvdata,tx_ack_rbf_tlvs,funding_output_contribution,satoshis,s64,
|
||||||
|
tlvtype,tx_ack_rbf_tlvs,require_confirmed_inputs,2
|
||||||
msgtype,tx_abort,74
|
msgtype,tx_abort,74
|
||||||
msgdata,tx_abort,channel_id,channel_id,
|
msgdata,tx_abort,channel_id,channel_id,
|
||||||
msgdata,tx_abort,len,u16,
|
msgdata,tx_abort,len,u16,
|
||||||
|
|
|
Loading…
Add table
Reference in a new issue