mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-18 05:12:45 +01:00
df-rbf: init an rbf for real, using openchannel_bumpfee
Reorg a bit of the RBF code so we use the same codepaths for we-init vs they-init starts.
This commit is contained in:
parent
4dcd4ca155
commit
d47358848f
@ -1744,7 +1744,16 @@ json_openchannel_bump(struct command *cmd,
|
||||
oa->our_upfront_shutdown_script
|
||||
= channel->shutdown_scriptpubkey[LOCAL];
|
||||
|
||||
/* FIXME: call dualopend with psbt + amount!! */
|
||||
/* Add serials to any input that's missing them */
|
||||
psbt_add_serials(psbt, TX_INITIATOR);
|
||||
if (!psbt_has_required_fields(psbt))
|
||||
return command_fail(cmd, FUNDING_PSBT_INVALID,
|
||||
"PSBT is missing required fields %s",
|
||||
type_to_string(tmpctx, struct wally_psbt,
|
||||
psbt));
|
||||
|
||||
subd_send_msg(channel->owner,
|
||||
take(towire_dualopend_rbf_init(NULL, *amount, psbt)));
|
||||
return command_still_pending(cmd);
|
||||
}
|
||||
|
||||
@ -2350,6 +2359,7 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||
case WIRE_DUALOPEND_INIT:
|
||||
case WIRE_DUALOPEND_REINIT:
|
||||
case WIRE_DUALOPEND_OPENER_INIT:
|
||||
case WIRE_DUALOPEND_RBF_INIT:
|
||||
case WIRE_DUALOPEND_GOT_OFFER_REPLY:
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
|
||||
case WIRE_DUALOPEND_RBF_VALID:
|
||||
|
@ -2495,7 +2495,230 @@ static bool update_feerate(struct tx_state *tx_state,
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rbf_start(struct state *state, const u8 *rbf_msg)
|
||||
static u8 find_next_feestep(u32 last_feerate, u32 feerate_funding,
|
||||
u32 *next_feerate)
|
||||
{
|
||||
u8 feestep;
|
||||
u32 feerate = feerate_funding;
|
||||
assert(last_feerate != 0 && feerate != 0);
|
||||
|
||||
for (feestep = 0; feerate <= last_feerate; feestep++)
|
||||
feerate = feerate + feerate / 4;
|
||||
|
||||
if (next_feerate)
|
||||
*next_feerate = feerate;
|
||||
return feestep;
|
||||
}
|
||||
|
||||
static void rbf_wrap_up(struct state *state,
|
||||
struct tx_state *tx_state,
|
||||
struct amount_sat total)
|
||||
{
|
||||
enum dualopend_wire msg_type;
|
||||
char *err_reason;
|
||||
u8 *msg;
|
||||
|
||||
/* BOLT-78de9a79b491ae9fb84b1fdb4546bacf642dce87 #2:
|
||||
* The sending node:
|
||||
* - if is the `opener`:
|
||||
* - MUST send at least one `tx_add_output`, the channel
|
||||
* funding output.
|
||||
*/
|
||||
if (state->our_role == TX_INITIATOR)
|
||||
add_funding_output(tx_state, state, total);
|
||||
else
|
||||
/* if accepter, set to an invalid number, 1 (odd is invalid) */
|
||||
tx_state->funding_serial = 1;
|
||||
|
||||
/* Add all of our inputs/outputs to the changeset */
|
||||
init_changeset(tx_state, tx_state->psbt);
|
||||
|
||||
if (state->our_role == TX_INITIATOR) {
|
||||
/* Send our first message; opener initiates */
|
||||
if (!send_next(state, tx_state, &tx_state->psbt)) {
|
||||
rbf_failed(state, "Peer error, has no tx updates.");
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: use rbf_failed !! */
|
||||
if (!run_tx_interactive(state, tx_state,
|
||||
&tx_state->psbt,
|
||||
state->our_role)) {
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is this an eligible RBF (at least one overlapping input) */
|
||||
msg = towire_dualopend_rbf_validate(NULL, tx_state->psbt);
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
msg = wire_sync_read(tmpctx, REQ_FD);
|
||||
|
||||
if ((msg_type = fromwire_peektype(msg)) == WIRE_DUALOPEND_FAIL) {
|
||||
if (!fromwire_dualopend_fail(msg, msg, &err_reason))
|
||||
master_badmsg(msg_type, msg);
|
||||
rbf_failed(state, "%s", err_reason);
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fromwire_dualopend_rbf_valid(msg))
|
||||
master_badmsg(WIRE_DUALOPEND_RBF_VALID, msg);
|
||||
|
||||
/* Find the funding transaction txid */
|
||||
psbt_txid(NULL, tx_state->psbt, &tx_state->funding_txid, NULL);
|
||||
|
||||
if (state->our_role == TX_ACCEPTER)
|
||||
msg = accepter_commits(state, tx_state, total, &err_reason);
|
||||
else
|
||||
msg = opener_commits(state, tx_state, total, &err_reason);
|
||||
|
||||
if (!msg) {
|
||||
if (err_reason)
|
||||
rbf_failed(state, "%s", err_reason);
|
||||
else
|
||||
rbf_failed(state, "%s", "Unable to commit");
|
||||
/* We need to 'reset' the channel to what it
|
||||
* was before we did this. */
|
||||
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Promote tx_state */
|
||||
tal_free(state->tx_state);
|
||||
state->tx_state = tx_state;
|
||||
|
||||
if (state->our_role == TX_ACCEPTER)
|
||||
handle_send_tx_sigs(state, msg);
|
||||
else
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
}
|
||||
|
||||
static void rbf_local_start(struct state *state, u8 *msg)
|
||||
{
|
||||
struct tx_state *tx_state;
|
||||
const char *errmsg;
|
||||
struct channel_id cid;
|
||||
struct amount_sat total;
|
||||
char *err_reason;
|
||||
u8 fee_step;
|
||||
|
||||
/* We need a new tx_state! */
|
||||
tx_state = new_tx_state(state);
|
||||
/* Copy over the channel config info -- everything except
|
||||
* the reserve will be the same */
|
||||
tx_state->localconf = state->tx_state->localconf;
|
||||
tx_state->remoteconf = state->tx_state->remoteconf;
|
||||
|
||||
if (!fromwire_dualopend_rbf_init(state, msg,
|
||||
state->our_role == TX_INITIATOR ?
|
||||
&tx_state->opener_funding :
|
||||
&tx_state->accepter_funding,
|
||||
&tx_state->psbt))
|
||||
master_badmsg(WIRE_DUALOPEND_RBF_INIT, msg);
|
||||
|
||||
peer_billboard(false, "channel rbf: init received from master");
|
||||
|
||||
fee_step = find_next_feestep(state->tx_state->feerate_per_kw_funding,
|
||||
state->feerate_per_kw_funding,
|
||||
&tx_state->feerate_per_kw_funding);
|
||||
|
||||
/* Have you sent us everything we need yet ? */
|
||||
if (!state->tx_state->remote_funding_sigs_rcvd) {
|
||||
/* we're still waiting for the last sigs, master
|
||||
* should know better. Tell them no! */
|
||||
errmsg = "Still waiting for remote funding sigs"
|
||||
" for last open attempt";
|
||||
msg = towire_dualopend_rbf_failed(NULL, errmsg);
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
tx_state->tx_locktime = tx_state->psbt->tx->locktime;
|
||||
msg = towire_init_rbf(tmpctx, &state->channel_id,
|
||||
state->our_role == TX_INITIATOR ?
|
||||
tx_state->opener_funding :
|
||||
tx_state->accepter_funding,
|
||||
tx_state->tx_locktime,
|
||||
fee_step);
|
||||
|
||||
sync_crypto_write(state->pps, take(msg));
|
||||
|
||||
/* ... since their reply should be immediate. */
|
||||
msg = opening_negotiate_msg(tmpctx, state);
|
||||
if (!msg) {
|
||||
errmsg = "Unable to init rbf";
|
||||
msg = towire_dualopend_rbf_failed(NULL, errmsg);
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!fromwire_ack_rbf(msg, &cid,
|
||||
state->our_role == TX_INITIATOR ?
|
||||
&tx_state->accepter_funding :
|
||||
&tx_state->opener_funding))
|
||||
peer_failed_err(state->pps, &state->channel_id,
|
||||
"Parsing ack_rbf %s",
|
||||
tal_hex(tmpctx, msg));
|
||||
|
||||
peer_billboard(false, "channel rbf: ack received");
|
||||
check_channel_id(state, &cid, &state->channel_id);
|
||||
|
||||
/* Check that total funding doesn't overflow */
|
||||
if (!amount_sat_add(&total, tx_state->opener_funding,
|
||||
tx_state->accepter_funding)) {
|
||||
rbf_failed(state, "Amount overflow. Local sats %s. "
|
||||
"Remote sats %s",
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&tx_state->accepter_funding),
|
||||
type_to_string(tmpctx, struct amount_sat,
|
||||
&tx_state->opener_funding));
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
/* Check that total funding doesn't exceed allowed channel capacity */
|
||||
/* BOLT #2:
|
||||
*
|
||||
* The receiving node MUST fail the channel if:
|
||||
*...
|
||||
* - `funding_satoshis` is greater than or equal to 2^24 and the receiver does not support
|
||||
* `option_support_large_channel`. */
|
||||
/* We choose to require *negotiation*, not just support! */
|
||||
if (!feature_negotiated(state->our_features, state->their_features,
|
||||
OPT_LARGE_CHANNELS)
|
||||
&& amount_sat_greater(total, chainparams->max_funding)) {
|
||||
rbf_failed(state, "total funding_satoshis %s too large",
|
||||
type_to_string(tmpctx, struct amount_sat, &total));
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Now that we know the total of the channel, we can set the reserve */
|
||||
set_reserve(tx_state, total);
|
||||
|
||||
if (!check_config_bounds(tmpctx, total,
|
||||
state->feerate_per_kw_commitment,
|
||||
state->max_to_self_delay,
|
||||
state->min_effective_htlc_capacity,
|
||||
&tx_state->remoteconf,
|
||||
&tx_state->localconf,
|
||||
false,
|
||||
true, /* v2 means we use anchor outputs */
|
||||
&err_reason)) {
|
||||
rbf_failed(state, "%s", err_reason);
|
||||
tal_free(tx_state);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We merge with RBF's we've initiated now */
|
||||
rbf_wrap_up(state, tx_state, total);
|
||||
}
|
||||
|
||||
static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
|
||||
{
|
||||
struct channel_id cid;
|
||||
struct tx_state *tx_state;
|
||||
@ -2629,67 +2852,8 @@ static void rbf_start(struct state *state, const u8 *rbf_msg)
|
||||
sync_crypto_write(state->pps, msg);
|
||||
peer_billboard(false, "channel rbf: ack sent, waiting for reply");
|
||||
|
||||
|
||||
/* BOLT-78de9a79b491ae9fb84b1fdb4546bacf642dce87 #2:
|
||||
* The sending node:
|
||||
* - if is the `opener`:
|
||||
* - MUST send at least one `tx_add_output`, the channel
|
||||
* funding output.
|
||||
*/
|
||||
if (state->our_role == TX_INITIATOR)
|
||||
add_funding_output(tx_state, state, total);
|
||||
else
|
||||
/* if accepter, set to an invalid number, 1 (odd is invalid) */
|
||||
tx_state->funding_serial = 1;
|
||||
|
||||
/* Add all of our inputs/outputs to the changeset */
|
||||
init_changeset(tx_state, tx_state->psbt);
|
||||
|
||||
if (state->our_role == TX_INITIATOR)
|
||||
/* Send our first message; opener initiates */
|
||||
if (!send_next(state, tx_state, &tx_state->psbt))
|
||||
rbf_failed(state, "Peer error, has no tx updates.");
|
||||
|
||||
/* FIXME: use rbf_failed !! */
|
||||
if (!run_tx_interactive(state, tx_state,
|
||||
&tx_state->psbt, state->our_role))
|
||||
return;
|
||||
|
||||
/* Is this an eligible RBF (at least one overlapping input) */
|
||||
msg = towire_dualopend_rbf_validate(NULL, tx_state->psbt);
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
msg = wire_sync_read(tmpctx, REQ_FD);
|
||||
|
||||
if ((msg_type = fromwire_peektype(msg)) == WIRE_DUALOPEND_FAIL) {
|
||||
if (!fromwire_dualopend_fail(msg, msg, &err_reason))
|
||||
master_badmsg(msg_type, msg);
|
||||
rbf_failed(state, "%s", err_reason);
|
||||
}
|
||||
|
||||
if (!fromwire_dualopend_rbf_valid(msg))
|
||||
master_badmsg(WIRE_DUALOPEND_RBF_VALID, msg);
|
||||
|
||||
/* Find the funding transaction txid */
|
||||
psbt_txid(NULL, tx_state->psbt, &tx_state->funding_txid, NULL);
|
||||
|
||||
if (state->our_role == TX_ACCEPTER)
|
||||
msg = accepter_commits(state, tx_state, total, &err_reason);
|
||||
else
|
||||
msg = opener_commits(state, tx_state, total, &err_reason);
|
||||
|
||||
if (!msg) {
|
||||
if (err_reason)
|
||||
rbf_failed(state, "%s", err_reason);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state->our_role == TX_ACCEPTER)
|
||||
handle_send_tx_sigs(state, msg);
|
||||
else
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
|
||||
tal_free(state->tx_state);
|
||||
state->tx_state = tx_state;
|
||||
/* We merge with RBF's we've initiated now */
|
||||
rbf_wrap_up(state, tx_state, total);
|
||||
}
|
||||
|
||||
static u8 *handle_funding_locked(struct state *state, u8 *msg)
|
||||
@ -3022,6 +3186,9 @@ static u8 *handle_master_in(struct state *state)
|
||||
case WIRE_DUALOPEND_OPENER_INIT:
|
||||
opener_start(state, msg);
|
||||
return NULL;
|
||||
case WIRE_DUALOPEND_RBF_INIT:
|
||||
rbf_local_start(state, msg);
|
||||
return NULL;
|
||||
case WIRE_DUALOPEND_SEND_TX_SIGS:
|
||||
handle_send_tx_sigs(state, msg);
|
||||
return NULL;
|
||||
@ -3104,7 +3271,7 @@ static u8 *handle_peer_in(struct state *state)
|
||||
handle_peer_shutdown(state, msg);
|
||||
return NULL;
|
||||
case WIRE_INIT_RBF:
|
||||
rbf_start(state, msg);
|
||||
rbf_remote_start(state, msg);
|
||||
return NULL;
|
||||
/* Otherwise we fall through */
|
||||
case WIRE_INIT:
|
||||
|
@ -120,6 +120,11 @@ msgdata,dualopend_rbf_validate,proposed_funding_psbt,wally_psbt,
|
||||
# master->dualopend: this is a valid RBF candidate transaction
|
||||
msgtype,dualopend_rbf_valid,7507
|
||||
|
||||
# master->dualopend: attempt an RBF
|
||||
msgtype,dualopend_rbf_init,7509
|
||||
msgdata,dualopend_rbf_init,our_funding,amount_sat,
|
||||
msgdata,dualopend_rbf_init,psbt,wally_psbt,
|
||||
|
||||
# dualopend->master: ready to commit channel open to database and
|
||||
# get some signatures for the funding_tx.
|
||||
msgtype,dualopend_commit_rcvd,7007
|
||||
|
Can't render this file because it has a wrong number of fields in line 13.
|
28
openingd/dualopend_wiregen.c
generated
28
openingd/dualopend_wiregen.c
generated
@ -28,6 +28,7 @@ const char *dualopend_wire_name(int e)
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY: return "WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY";
|
||||
case WIRE_DUALOPEND_RBF_VALIDATE: return "WIRE_DUALOPEND_RBF_VALIDATE";
|
||||
case WIRE_DUALOPEND_RBF_VALID: return "WIRE_DUALOPEND_RBF_VALID";
|
||||
case WIRE_DUALOPEND_RBF_INIT: return "WIRE_DUALOPEND_RBF_INIT";
|
||||
case WIRE_DUALOPEND_COMMIT_RCVD: return "WIRE_DUALOPEND_COMMIT_RCVD";
|
||||
case WIRE_DUALOPEND_PSBT_CHANGED: return "WIRE_DUALOPEND_PSBT_CHANGED";
|
||||
case WIRE_DUALOPEND_PSBT_UPDATED: return "WIRE_DUALOPEND_PSBT_UPDATED";
|
||||
@ -64,6 +65,7 @@ bool dualopend_wire_is_defined(u16 type)
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:;
|
||||
case WIRE_DUALOPEND_RBF_VALIDATE:;
|
||||
case WIRE_DUALOPEND_RBF_VALID:;
|
||||
case WIRE_DUALOPEND_RBF_INIT:;
|
||||
case WIRE_DUALOPEND_COMMIT_RCVD:;
|
||||
case WIRE_DUALOPEND_PSBT_CHANGED:;
|
||||
case WIRE_DUALOPEND_PSBT_UPDATED:;
|
||||
@ -461,6 +463,30 @@ bool fromwire_dualopend_rbf_valid(const void *p)
|
||||
return cursor != NULL;
|
||||
}
|
||||
|
||||
/* WIRE: DUALOPEND_RBF_INIT */
|
||||
/* master->dualopend: attempt an RBF */
|
||||
u8 *towire_dualopend_rbf_init(const tal_t *ctx, struct amount_sat our_funding, const struct wally_psbt *psbt)
|
||||
{
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
||||
towire_u16(&p, WIRE_DUALOPEND_RBF_INIT);
|
||||
towire_amount_sat(&p, our_funding);
|
||||
towire_wally_psbt(&p, psbt);
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_sat *our_funding, struct wally_psbt **psbt)
|
||||
{
|
||||
const u8 *cursor = p;
|
||||
size_t plen = tal_count(p);
|
||||
|
||||
if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_RBF_INIT)
|
||||
return false;
|
||||
*our_funding = fromwire_amount_sat(&cursor, &plen);
|
||||
*psbt = fromwire_wally_psbt(ctx, &cursor, &plen);
|
||||
return cursor != NULL;
|
||||
}
|
||||
|
||||
/* WIRE: DUALOPEND_COMMIT_RCVD */
|
||||
/* dualopend->master: ready to commit channel open to database and */
|
||||
/* get some signatures for the funding_tx. */
|
||||
@ -970,4 +996,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak)
|
||||
*leak = fromwire_bool(&cursor, &plen);
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:16b6a5025dbdb4cd770749cf8557990d0a4ff2b85ad6fca17ce91769dd22fd68
|
||||
// SHA256STAMP:ac2f996019c8461a99192330f4d2cc506fc8c6dcebf2f0ce56f7b53157ffffe4
|
||||
|
9
openingd/dualopend_wiregen.h
generated
9
openingd/dualopend_wiregen.h
generated
@ -35,6 +35,8 @@ enum dualopend_wire {
|
||||
WIRE_DUALOPEND_RBF_VALIDATE = 7506,
|
||||
/* master->dualopend: this is a valid RBF candidate transaction */
|
||||
WIRE_DUALOPEND_RBF_VALID = 7507,
|
||||
/* master->dualopend: attempt an RBF */
|
||||
WIRE_DUALOPEND_RBF_INIT = 7509,
|
||||
/* dualopend->master: ready to commit channel open to database and */
|
||||
/* get some signatures for the funding_tx. */
|
||||
WIRE_DUALOPEND_COMMIT_RCVD = 7007,
|
||||
@ -126,6 +128,11 @@ bool fromwire_dualopend_rbf_validate(const tal_t *ctx, const void *p, struct wal
|
||||
u8 *towire_dualopend_rbf_valid(const tal_t *ctx);
|
||||
bool fromwire_dualopend_rbf_valid(const void *p);
|
||||
|
||||
/* WIRE: DUALOPEND_RBF_INIT */
|
||||
/* master->dualopend: attempt an RBF */
|
||||
u8 *towire_dualopend_rbf_init(const tal_t *ctx, struct amount_sat our_funding, const struct wally_psbt *psbt);
|
||||
bool fromwire_dualopend_rbf_init(const tal_t *ctx, const void *p, struct amount_sat *our_funding, struct wally_psbt **psbt);
|
||||
|
||||
/* WIRE: DUALOPEND_COMMIT_RCVD */
|
||||
/* dualopend->master: ready to commit channel open to database and */
|
||||
/* get some signatures for the funding_tx. */
|
||||
@ -223,4 +230,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak);
|
||||
|
||||
|
||||
#endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */
|
||||
// SHA256STAMP:16b6a5025dbdb4cd770749cf8557990d0a4ff2b85ad6fca17ce91769dd22fd68
|
||||
// SHA256STAMP:ac2f996019c8461a99192330f4d2cc506fc8c6dcebf2f0ce56f7b53157ffffe4
|
||||
|
Loading…
Reference in New Issue
Block a user