mirror of
https://github.com/ElementsProject/lightning.git
synced 2025-01-17 19:03:42 +01:00
df-rbf: start of handling an incoming RBF attempt from peer
A peer init's an RBF, we start handling it
This commit is contained in:
parent
067f1f2eb7
commit
a489f92ee8
@ -1931,6 +1931,9 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||
case WIRE_DUALOPEND_GOT_OFFER:
|
||||
accepter_got_offer(dualopend, uc, msg);
|
||||
return 0;
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER:
|
||||
// FIXME: do this
|
||||
return 0;
|
||||
case WIRE_DUALOPEND_PSBT_CHANGED:
|
||||
if (uc->fc) {
|
||||
if (!uc->fc->cmd) {
|
||||
@ -1998,6 +2001,7 @@ static unsigned int dual_opend_msg(struct subd *dualopend,
|
||||
case WIRE_DUALOPEND_REINIT:
|
||||
case WIRE_DUALOPEND_OPENER_INIT:
|
||||
case WIRE_DUALOPEND_GOT_OFFER_REPLY:
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
|
||||
case WIRE_DUALOPEND_FAIL:
|
||||
case WIRE_DUALOPEND_PSBT_UPDATED:
|
||||
case WIRE_DUALOPEND_SEND_TX_SIGS:
|
||||
|
@ -332,10 +332,7 @@ static void negotiation_failed(struct state *state,
|
||||
open_error(state, "You gave bad parameters: %s", errmsg);
|
||||
}
|
||||
|
||||
/* FIXME: remove this once used */
|
||||
void rbf_failed(struct state *state, const char *fmt, ...);
|
||||
void rbf_failed(struct state *state,
|
||||
const char *fmt, ...)
|
||||
static void rbf_failed(struct state *state, const char *fmt, ...)
|
||||
{
|
||||
va_list ap;
|
||||
const char *errmsg;
|
||||
@ -2351,6 +2348,180 @@ static void opener_start(struct state *state, u8 *msg)
|
||||
wire_sync_write(REQ_FD, take(msg));
|
||||
}
|
||||
|
||||
static bool update_feerate(struct tx_state *tx_state,
|
||||
u32 feerate_funding,
|
||||
u32 last_feerate,
|
||||
u8 fee_step)
|
||||
{
|
||||
u32 feerate = feerate_funding;
|
||||
|
||||
/*
|
||||
* BOLT-487dd4b46aad9b59f7f3480b7bdf15862b52d2f9b #2:
|
||||
* Each `fee_step` adds 1/4 (rounded down) to the initial
|
||||
* transaction feerate, i.e. if the initial `feerate_per_kw_funding`
|
||||
* was 512 satoshis per kiloweight, `fee_step` 1 is
|
||||
* 512 + 512 / 4 or 640 sat/kw, `fee_step` 2
|
||||
* is 640 + 640 / 4 or 800 sat/kw.
|
||||
*/
|
||||
for (; fee_step > 0; fee_step--)
|
||||
feerate += feerate / 4;
|
||||
|
||||
/* It's possible they sent us a 'bad' feerate step,
|
||||
* i.e. less than the last one. */
|
||||
if (feerate <= last_feerate)
|
||||
return false;
|
||||
|
||||
tx_state->feerate_per_kw_funding = feerate;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rbf_start(struct state *state, const u8 *rbf_msg)
|
||||
{
|
||||
struct channel_id cid;
|
||||
struct tx_state *tx_state;
|
||||
char *err_reason;
|
||||
struct amount_sat total;
|
||||
enum dualopend_wire msg_type;
|
||||
u8 fee_step, *msg;
|
||||
|
||||
/* We need a new tx_state! */
|
||||
tx_state = new_tx_state(state);
|
||||
|
||||
if (!fromwire_init_rbf(rbf_msg, &cid,
|
||||
&tx_state->opener_funding,
|
||||
&tx_state->tx_locktime,
|
||||
&fee_step))
|
||||
peer_failed_err(state->pps, &state->channel_id,
|
||||
"Parsing init_rbf %s",
|
||||
tal_hex(tmpctx, rbf_msg));
|
||||
|
||||
/* Is this the correct channel? */
|
||||
check_channel_id(state, &cid, &state->channel_id);
|
||||
peer_billboard(false, "channel rbf: init received from peer");
|
||||
|
||||
/* Have you sent us everything we need yet ? */
|
||||
if (!state->tx_state->remote_funding_sigs_rcvd)
|
||||
rbf_failed(state, "Last funding attempt not complete:"
|
||||
" missing your funding tx_sigs");
|
||||
|
||||
/* FIXME: should we check for currently in progress? */
|
||||
|
||||
/* 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 (!update_feerate(tx_state,
|
||||
state->feerate_per_kw_funding,
|
||||
state->tx_state->feerate_per_kw_funding,
|
||||
fee_step)) {
|
||||
rbf_failed(state, "Fee step not greater than last."
|
||||
" Fee step %d, last feerate %d",
|
||||
fee_step,
|
||||
state->tx_state->feerate_per_kw_funding);
|
||||
return;
|
||||
}
|
||||
|
||||
/* We ask master if this is ok */
|
||||
msg = towire_dualopend_got_rbf_offer(NULL,
|
||||
&state->channel_id,
|
||||
tx_state->opener_funding,
|
||||
tx_state->feerate_per_kw_funding,
|
||||
tx_state->tx_locktime);
|
||||
|
||||
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_got_rbf_offer_reply(state, msg,
|
||||
&tx_state->accepter_funding,
|
||||
&tx_state->psbt))
|
||||
master_badmsg(WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY, msg);
|
||||
|
||||
if (!tx_state->psbt)
|
||||
tx_state->psbt = create_psbt(tx_state, 0, 0,
|
||||
tx_state->tx_locktime);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
/* Add all of our inputs/outputs to the changeset */
|
||||
init_changeset(tx_state, tx_state->psbt);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
msg = towire_ack_rbf(tmpctx, &state->channel_id,
|
||||
state->our_role == TX_INITIATOR ?
|
||||
tx_state->opener_funding :
|
||||
tx_state->accepter_funding);
|
||||
sync_crypto_write(state->pps, msg);
|
||||
peer_billboard(false, "channel rbf: ack sent, waiting for reply");
|
||||
|
||||
|
||||
/* This is unused in this flow. We re-use
|
||||
* the wire method between accepter + opener, so we set it
|
||||
* to an invalid number, 1 (initiator sets; valid is even) */
|
||||
tx_state->funding_serial = 1;
|
||||
/* Now we figure out what the proposed new open transaction is */
|
||||
if (!run_tx_interactive(state, tx_state,
|
||||
&tx_state->psbt, TX_ACCEPTER))
|
||||
return;
|
||||
|
||||
/* Find the funding transaction txid */
|
||||
psbt_txid(NULL, tx_state->psbt, &tx_state->funding_txid, NULL);
|
||||
|
||||
// FIXME: same as accepter run now?
|
||||
}
|
||||
|
||||
static u8 *handle_funding_locked(struct state *state, u8 *msg)
|
||||
{
|
||||
struct channel_id cid;
|
||||
@ -2697,9 +2868,11 @@ static u8 *handle_master_in(struct state *state)
|
||||
case WIRE_DUALOPEND_FAIL:
|
||||
case WIRE_DUALOPEND_PSBT_UPDATED:
|
||||
case WIRE_DUALOPEND_GOT_OFFER_REPLY:
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:
|
||||
|
||||
/* Messages we send */
|
||||
case WIRE_DUALOPEND_GOT_OFFER:
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER:
|
||||
case WIRE_DUALOPEND_PSBT_CHANGED:
|
||||
case WIRE_DUALOPEND_COMMIT_RCVD:
|
||||
case WIRE_DUALOPEND_FUNDING_SIGS:
|
||||
@ -2759,7 +2932,7 @@ static u8 *handle_peer_in(struct state *state)
|
||||
handle_peer_shutdown(state, msg);
|
||||
return NULL;
|
||||
case WIRE_INIT_RBF:
|
||||
// FIXME: rbf_start?
|
||||
rbf_start(state, msg);
|
||||
return NULL;
|
||||
/* Otherwise we fall through */
|
||||
case WIRE_INIT:
|
||||
|
@ -98,6 +98,18 @@ msgdata,dualopend_got_offer_reply,psbt,wally_psbt,
|
||||
msgdata,dualopend_got_offer_reply,shutdown_len,u16,
|
||||
msgdata,dualopend_got_offer_reply,our_shutdown_scriptpubkey,?u8,shutdown_len
|
||||
|
||||
# dualopend->master: they offered a RBF, should we continue?
|
||||
msgtype,dualopend_got_rbf_offer,7500
|
||||
msgdata,dualopend_got_rbf_offer,channel_id,channel_id,
|
||||
msgdata,dualopend_got_rbf_offer,opener_funding,amount_sat,
|
||||
msgdata,dualopend_got_rbf_offer,funding_feerate_per_kw,u32,
|
||||
msgdata,dualopend_got_rbf_offer,locktime,u32,
|
||||
|
||||
# master->dualopend: reply back with our funding info/contribs
|
||||
msgtype,dualopend_got_rbf_offer_reply,7505
|
||||
msgdata,dualopend_got_rbf_offer_reply,accepter_funding,amount_sat,
|
||||
msgdata,dualopend_got_rbf_offer_reply,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.
|
58
openingd/dualopend_wiregen.c
generated
58
openingd/dualopend_wiregen.c
generated
@ -24,6 +24,8 @@ const char *dualopend_wire_name(int e)
|
||||
case WIRE_DUALOPEND_REINIT: return "WIRE_DUALOPEND_REINIT";
|
||||
case WIRE_DUALOPEND_GOT_OFFER: return "WIRE_DUALOPEND_GOT_OFFER";
|
||||
case WIRE_DUALOPEND_GOT_OFFER_REPLY: return "WIRE_DUALOPEND_GOT_OFFER_REPLY";
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER: return "WIRE_DUALOPEND_GOT_RBF_OFFER";
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY: return "WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY";
|
||||
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";
|
||||
@ -56,6 +58,8 @@ bool dualopend_wire_is_defined(u16 type)
|
||||
case WIRE_DUALOPEND_REINIT:;
|
||||
case WIRE_DUALOPEND_GOT_OFFER:;
|
||||
case WIRE_DUALOPEND_GOT_OFFER_REPLY:;
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER:;
|
||||
case WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY:;
|
||||
case WIRE_DUALOPEND_COMMIT_RCVD:;
|
||||
case WIRE_DUALOPEND_PSBT_CHANGED:;
|
||||
case WIRE_DUALOPEND_PSBT_UPDATED:;
|
||||
@ -353,6 +357,58 @@ bool fromwire_dualopend_got_offer_reply(const tal_t *ctx, const void *p, struct
|
||||
return cursor != NULL;
|
||||
}
|
||||
|
||||
/* WIRE: DUALOPEND_GOT_RBF_OFFER */
|
||||
/* dualopend->master: they offered a RBF */
|
||||
u8 *towire_dualopend_got_rbf_offer(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat opener_funding, u32 funding_feerate_per_kw, u32 locktime)
|
||||
{
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
||||
towire_u16(&p, WIRE_DUALOPEND_GOT_RBF_OFFER);
|
||||
towire_channel_id(&p, channel_id);
|
||||
towire_amount_sat(&p, opener_funding);
|
||||
towire_u32(&p, funding_feerate_per_kw);
|
||||
towire_u32(&p, locktime);
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_dualopend_got_rbf_offer(const void *p, struct channel_id *channel_id, struct amount_sat *opener_funding, u32 *funding_feerate_per_kw, u32 *locktime)
|
||||
{
|
||||
const u8 *cursor = p;
|
||||
size_t plen = tal_count(p);
|
||||
|
||||
if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_GOT_RBF_OFFER)
|
||||
return false;
|
||||
fromwire_channel_id(&cursor, &plen, channel_id);
|
||||
*opener_funding = fromwire_amount_sat(&cursor, &plen);
|
||||
*funding_feerate_per_kw = fromwire_u32(&cursor, &plen);
|
||||
*locktime = fromwire_u32(&cursor, &plen);
|
||||
return cursor != NULL;
|
||||
}
|
||||
|
||||
/* WIRE: DUALOPEND_GOT_RBF_OFFER_REPLY */
|
||||
/* master->dualopend: reply back with our funding info/contribs */
|
||||
u8 *towire_dualopend_got_rbf_offer_reply(const tal_t *ctx, struct amount_sat accepter_funding, const struct wally_psbt *psbt)
|
||||
{
|
||||
u8 *p = tal_arr(ctx, u8, 0);
|
||||
|
||||
towire_u16(&p, WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY);
|
||||
towire_amount_sat(&p, accepter_funding);
|
||||
towire_wally_psbt(&p, psbt);
|
||||
|
||||
return memcheck(p, tal_count(p));
|
||||
}
|
||||
bool fromwire_dualopend_got_rbf_offer_reply(const tal_t *ctx, const void *p, struct amount_sat *accepter_funding, struct wally_psbt **psbt)
|
||||
{
|
||||
const u8 *cursor = p;
|
||||
size_t plen = tal_count(p);
|
||||
|
||||
if (fromwire_u16(&cursor, &plen) != WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY)
|
||||
return false;
|
||||
*accepter_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. */
|
||||
@ -862,4 +918,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak)
|
||||
*leak = fromwire_bool(&cursor, &plen);
|
||||
return cursor != NULL;
|
||||
}
|
||||
// SHA256STAMP:6e149f437eae7fde2f891bbb7f36903fa105179d9a97cd1b765d34641c0839ce
|
||||
// SHA256STAMP:d9a02c4575a71748388be74b56f3fe333147557aa715e6735b9a1c35a72c7cd5
|
||||
|
16
openingd/dualopend_wiregen.h
generated
16
openingd/dualopend_wiregen.h
generated
@ -27,6 +27,10 @@ enum dualopend_wire {
|
||||
WIRE_DUALOPEND_GOT_OFFER = 7005,
|
||||
/* master->dualopend: reply back with our first funding info/contribs */
|
||||
WIRE_DUALOPEND_GOT_OFFER_REPLY = 7105,
|
||||
/* dualopend->master: they offered a RBF */
|
||||
WIRE_DUALOPEND_GOT_RBF_OFFER = 7500,
|
||||
/* master->dualopend: reply back with our funding info/contribs */
|
||||
WIRE_DUALOPEND_GOT_RBF_OFFER_REPLY = 7505,
|
||||
/* dualopend->master: ready to commit channel open to database and */
|
||||
/* get some signatures for the funding_tx. */
|
||||
WIRE_DUALOPEND_COMMIT_RCVD = 7007,
|
||||
@ -98,6 +102,16 @@ bool fromwire_dualopend_got_offer(const tal_t *ctx, const void *p, struct channe
|
||||
u8 *towire_dualopend_got_offer_reply(const tal_t *ctx, struct amount_sat accepter_funding, u32 feerate_funding, const struct wally_psbt *psbt, const u8 *our_shutdown_scriptpubkey);
|
||||
bool fromwire_dualopend_got_offer_reply(const tal_t *ctx, const void *p, struct amount_sat *accepter_funding, u32 *feerate_funding, struct wally_psbt **psbt, u8 **our_shutdown_scriptpubkey);
|
||||
|
||||
/* WIRE: DUALOPEND_GOT_RBF_OFFER */
|
||||
/* dualopend->master: they offered a RBF */
|
||||
u8 *towire_dualopend_got_rbf_offer(const tal_t *ctx, const struct channel_id *channel_id, struct amount_sat opener_funding, u32 funding_feerate_per_kw, u32 locktime);
|
||||
bool fromwire_dualopend_got_rbf_offer(const void *p, struct channel_id *channel_id, struct amount_sat *opener_funding, u32 *funding_feerate_per_kw, u32 *locktime);
|
||||
|
||||
/* WIRE: DUALOPEND_GOT_RBF_OFFER_REPLY */
|
||||
/* master->dualopend: reply back with our funding info/contribs */
|
||||
u8 *towire_dualopend_got_rbf_offer_reply(const tal_t *ctx, struct amount_sat accepter_funding, const struct wally_psbt *psbt);
|
||||
bool fromwire_dualopend_got_rbf_offer_reply(const tal_t *ctx, const void *p, struct amount_sat *accepter_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. */
|
||||
@ -195,4 +209,4 @@ bool fromwire_dualopend_dev_memleak_reply(const void *p, bool *leak);
|
||||
|
||||
|
||||
#endif /* LIGHTNING_OPENINGD_DUALOPEND_WIREGEN_H */
|
||||
// SHA256STAMP:6e149f437eae7fde2f891bbb7f36903fa105179d9a97cd1b765d34641c0839ce
|
||||
// SHA256STAMP:d9a02c4575a71748388be74b56f3fe333147557aa715e6735b9a1c35a72c7cd5
|
||||
|
Loading…
Reference in New Issue
Block a user