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:
niftynei 2021-01-25 12:37:42 -06:00 committed by Rusty Russell
parent 4dcd4ca155
commit d47358848f
5 changed files with 281 additions and 66 deletions

View File

@ -1744,7 +1744,16 @@ json_openchannel_bump(struct command *cmd,
oa->our_upfront_shutdown_script oa->our_upfront_shutdown_script
= channel->shutdown_scriptpubkey[LOCAL]; = 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); 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_INIT:
case WIRE_DUALOPEND_REINIT: case WIRE_DUALOPEND_REINIT:
case WIRE_DUALOPEND_OPENER_INIT: case WIRE_DUALOPEND_OPENER_INIT:
case WIRE_DUALOPEND_RBF_INIT:
case WIRE_DUALOPEND_GOT_OFFER_REPLY: case WIRE_DUALOPEND_GOT_OFFER_REPLY:
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY: case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
case WIRE_DUALOPEND_RBF_VALID: case WIRE_DUALOPEND_RBF_VALID:

View File

@ -2495,7 +2495,230 @@ static bool update_feerate(struct tx_state *tx_state,
return true; 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 channel_id cid;
struct tx_state *tx_state; 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); sync_crypto_write(state->pps, msg);
peer_billboard(false, "channel rbf: ack sent, waiting for reply"); peer_billboard(false, "channel rbf: ack sent, waiting for reply");
/* We merge with RBF's we've initiated now */
/* BOLT-78de9a79b491ae9fb84b1fdb4546bacf642dce87 #2: rbf_wrap_up(state, tx_state, total);
* 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;
} }
static u8 *handle_funding_locked(struct state *state, u8 *msg) 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: case WIRE_DUALOPEND_OPENER_INIT:
opener_start(state, msg); opener_start(state, msg);
return NULL; return NULL;
case WIRE_DUALOPEND_RBF_INIT:
rbf_local_start(state, msg);
return NULL;
case WIRE_DUALOPEND_SEND_TX_SIGS: case WIRE_DUALOPEND_SEND_TX_SIGS:
handle_send_tx_sigs(state, msg); handle_send_tx_sigs(state, msg);
return NULL; return NULL;
@ -3104,7 +3271,7 @@ static u8 *handle_peer_in(struct state *state)
handle_peer_shutdown(state, msg); handle_peer_shutdown(state, msg);
return NULL; return NULL;
case WIRE_INIT_RBF: case WIRE_INIT_RBF:
rbf_start(state, msg); rbf_remote_start(state, msg);
return NULL; return NULL;
/* Otherwise we fall through */ /* Otherwise we fall through */
case WIRE_INIT: case WIRE_INIT:

View File

@ -120,6 +120,11 @@ msgdata,dualopend_rbf_validate,proposed_funding_psbt,wally_psbt,
# master->dualopend: this is a valid RBF candidate transaction # master->dualopend: this is a valid RBF candidate transaction
msgtype,dualopend_rbf_valid,7507 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 # dualopend->master: ready to commit channel open to database and
# get some signatures for the funding_tx. # get some signatures for the funding_tx.
msgtype,dualopend_commit_rcvd,7007 msgtype,dualopend_commit_rcvd,7007

Can't render this file because it has a wrong number of fields in line 13.

View File

@ -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_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_VALIDATE: return "WIRE_DUALOPEND_RBF_VALIDATE";
case WIRE_DUALOPEND_RBF_VALID: return "WIRE_DUALOPEND_RBF_VALID"; 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_COMMIT_RCVD: return "WIRE_DUALOPEND_COMMIT_RCVD";
case WIRE_DUALOPEND_PSBT_CHANGED: return "WIRE_DUALOPEND_PSBT_CHANGED"; case WIRE_DUALOPEND_PSBT_CHANGED: return "WIRE_DUALOPEND_PSBT_CHANGED";
case WIRE_DUALOPEND_PSBT_UPDATED: return "WIRE_DUALOPEND_PSBT_UPDATED"; 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_GOT_RBF_OFFER_REPLY:;
case WIRE_DUALOPEND_RBF_VALIDATE:; case WIRE_DUALOPEND_RBF_VALIDATE:;
case WIRE_DUALOPEND_RBF_VALID:; case WIRE_DUALOPEND_RBF_VALID:;
case WIRE_DUALOPEND_RBF_INIT:;
case WIRE_DUALOPEND_COMMIT_RCVD:; case WIRE_DUALOPEND_COMMIT_RCVD:;
case WIRE_DUALOPEND_PSBT_CHANGED:; case WIRE_DUALOPEND_PSBT_CHANGED:;
case WIRE_DUALOPEND_PSBT_UPDATED:; case WIRE_DUALOPEND_PSBT_UPDATED:;
@ -461,6 +463,30 @@ bool fromwire_dualopend_rbf_valid(const void *p)
return cursor != NULL; 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 */ /* WIRE: DUALOPEND_COMMIT_RCVD */
/* dualopend->master: ready to commit channel open to database and */ /* dualopend->master: ready to commit channel open to database and */
/* get some signatures for the funding_tx. */ /* 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); *leak = fromwire_bool(&cursor, &plen);
return cursor != NULL; return cursor != NULL;
} }
// SHA256STAMP:16b6a5025dbdb4cd770749cf8557990d0a4ff2b85ad6fca17ce91769dd22fd68 // SHA256STAMP:ac2f996019c8461a99192330f4d2cc506fc8c6dcebf2f0ce56f7b53157ffffe4

View File

@ -35,6 +35,8 @@ enum dualopend_wire {
WIRE_DUALOPEND_RBF_VALIDATE = 7506, WIRE_DUALOPEND_RBF_VALIDATE = 7506,
/* master->dualopend: this is a valid RBF candidate transaction */ /* master->dualopend: this is a valid RBF candidate transaction */
WIRE_DUALOPEND_RBF_VALID = 7507, 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 */ /* dualopend->master: ready to commit channel open to database and */
/* get some signatures for the funding_tx. */ /* get some signatures for the funding_tx. */
WIRE_DUALOPEND_COMMIT_RCVD = 7007, 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); u8 *towire_dualopend_rbf_valid(const tal_t *ctx);
bool fromwire_dualopend_rbf_valid(const void *p); 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 */ /* WIRE: DUALOPEND_COMMIT_RCVD */
/* dualopend->master: ready to commit channel open to database and */ /* dualopend->master: ready to commit channel open to database and */
/* get some signatures for the funding_tx. */ /* 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 */ #endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */
// SHA256STAMP:16b6a5025dbdb4cd770749cf8557990d0a4ff2b85ad6fca17ce91769dd22fd68 // SHA256STAMP:ac2f996019c8461a99192330f4d2cc506fc8c6dcebf2f0ce56f7b53157ffffe4