Skip to content

Commit 6c5b09a

Browse files
committed
rbf-wip: add ability to RBF from other side
Work in progress to allow acceptor to initiate an RBF Mostly works, except that the original funder isn't setup to re-add their original funds to the channel, so the init fails because it's missing any overlapping inputs. lightning/bolts#1236
1 parent c758672 commit 6c5b09a

File tree

3 files changed

+83
-66
lines changed

3 files changed

+83
-66
lines changed

lightningd/dual_open_control.c

Lines changed: 2 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -87,23 +87,6 @@ static void channel_saved_err_broken_reconn(struct channel *channel,
8787
channel_disconnect(channel, LOG_INFORM, true, errmsg);
8888
}
8989

90-
static void channel_err_broken(struct channel *channel,
91-
const char *fmt, ...)
92-
{
93-
va_list ap;
94-
const char *errmsg;
95-
96-
va_start(ap, fmt);
97-
errmsg = tal_vfmt(tmpctx, fmt, ap);
98-
va_end(ap);
99-
100-
if (channel_state_uncommitted(channel->state)) {
101-
log_broken(channel->log, "%s", errmsg);
102-
channel_unsaved_close_conn(channel, errmsg);
103-
} else
104-
channel_disconnect(channel, LOG_BROKEN, false, errmsg);
105-
}
106-
10790
void json_add_unsaved_channel(struct command *cmd,
10891
struct json_stream *response,
10992
const struct channel *channel,
@@ -2637,10 +2620,6 @@ json_openchannel_bump(struct command *cmd,
26372620
" Current state %s, expected state %s",
26382621
channel_state_name(channel),
26392622
channel_state_str(DUALOPEND_AWAITING_LOCKIN));
2640-
if (channel->opener != LOCAL)
2641-
return command_fail(cmd, FUNDING_STATE_INVALID,
2642-
"Only the channel opener can initiate an"
2643-
" RBF attempt");
26442623

26452624
inflight = channel_current_inflight(channel);
26462625
if (!inflight) {
@@ -3447,15 +3426,7 @@ static void handle_psbt_changed(struct subd *dualopend,
34473426
tal_free(channel->type);
34483427
channel->type = tal_steal(channel, channel_type);
34493428

3450-
switch (oa->role) {
3451-
case TX_INITIATOR:
3452-
if (!cmd) {
3453-
channel_err_broken(channel,
3454-
tal_fmt(tmpctx, "Unexpected"
3455-
" PSBT_CHANGED %s",
3456-
tal_hex(tmpctx, msg)));
3457-
return;
3458-
}
3429+
if (cmd) {
34593430
/* This might be the first time we learn the channel_id */
34603431
channel->cid = cid;
34613432
response = json_stream_success(cmd);
@@ -3470,8 +3441,7 @@ static void handle_psbt_changed(struct subd *dualopend,
34703441

34713442
oa->cmd = NULL;
34723443
was_pending(command_success(cmd, response));
3473-
return;
3474-
case TX_ACCEPTER:
3444+
} else {
34753445
payload = tal(dualopend, struct openchannel2_psbt_payload);
34763446
payload->dualopend = dualopend;
34773447
tal_add_destructor2(dualopend,
@@ -3480,9 +3450,7 @@ static void handle_psbt_changed(struct subd *dualopend,
34803450
payload->psbt = tal_steal(payload, psbt);
34813451
payload->channel = channel;
34823452
plugin_hook_call_openchannel2_changed(dualopend->ld, NULL, payload);
3483-
return;
34843453
}
3485-
abort();
34863454
}
34873455

34883456
static void handle_commit_ready(struct subd *dualopend,

openingd/dualopend.c

Lines changed: 28 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,9 @@ struct tx_state {
126126

127127
/* Lease's commited chan max ppt */
128128
u16 lease_chan_max_ppt;
129+
130+
/* What is our role for this tx */
131+
enum tx_role our_role;
129132
};
130133

131134
static struct tx_state *new_tx_state(const tal_t *ctx)
@@ -185,8 +188,6 @@ struct state {
185188
struct channel_id channel_id;
186189
u8 channel_flags;
187190

188-
enum tx_role our_role;
189-
190191
u32 feerate_per_kw_commitment;
191192

192193
/* If non-NULL, this is the scriptpubkey we/they *must* close with */
@@ -1054,7 +1055,7 @@ static u8 *psbt_to_tx_sigs_msg(const tal_t *ctx,
10541055
const struct wally_psbt *psbt)
10551056
{
10561057
const struct witness **ws =
1057-
psbt_to_witnesses(tmpctx, psbt, state->our_role, -1);
1058+
psbt_to_witnesses(tmpctx, psbt, state->tx_state->our_role, -1);
10581059

10591060
return towire_tx_signatures(ctx, &state->channel_id,
10601061
&state->tx_state->funding.txid,
@@ -1079,7 +1080,7 @@ static void report_channel_hsmd(const struct state *state,
10791080
"Overflow converting accepter_funding "
10801081
"to msats");
10811082

1082-
msg = towire_hsmd_setup_channel(NULL, state->our_role == TX_INITIATOR,
1083+
msg = towire_hsmd_setup_channel(NULL, state->tx_state->our_role == TX_INITIATOR,
10831084
total,
10841085
accepter_msats,
10851086
&tx_state->funding.txid,
@@ -1164,7 +1165,7 @@ static u8 *msg_for_remote_commit(const tal_t *ctx,
11641165

11651166
static enum tx_role their_role(const struct state *state)
11661167
{
1167-
return state->our_role == TX_INITIATOR ?
1168+
return state->tx_state->our_role == TX_INITIATOR ?
11681169
TX_ACCEPTER : TX_INITIATOR;
11691170
}
11701171

@@ -2116,7 +2117,7 @@ static void revert_channel_state(struct state *state)
21162117
struct tx_state *tx_state = state->tx_state;
21172118
struct amount_sat total;
21182119
struct amount_msat our_msats;
2119-
enum side opener = state->our_role == TX_INITIATOR ? LOCAL : REMOTE;
2120+
enum side opener = state->tx_state->our_role == TX_INITIATOR ? LOCAL : REMOTE;
21202121

21212122
/* We've already checked this */
21222123
if (!amount_sat_add(&total, tx_state->opener_funding,
@@ -2125,7 +2126,7 @@ static void revert_channel_state(struct state *state)
21252126

21262127
/* We've already checked this */
21272128
if (!amount_sat_to_msat(&our_msats,
2128-
state->our_role == TX_INITIATOR ?
2129+
state->tx_state->our_role == TX_INITIATOR ?
21292130
tx_state->opener_funding :
21302131
tx_state->accepter_funding))
21312132
abort();
@@ -2380,7 +2381,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
23802381
enum dualopend_wire msg_type;
23812382
struct tx_state *tx_state = state->tx_state;
23822383

2383-
state->our_role = TX_ACCEPTER;
2384+
tx_state->our_role = TX_ACCEPTER;
23842385

23852386
if (!fromwire_open_channel2(tmpctx, oc2_msg, &chain_hash,
23862387
&cid,
@@ -2655,7 +2656,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
26552656
init_changeset(tx_state, tx_state->psbt);
26562657

26572658
/* Now that we know the total of the channel, we can set the reserve */
2658-
set_reserve(tx_state, total, state->our_role);
2659+
set_reserve(tx_state, total, tx_state->our_role);
26592660

26602661
if (!check_config_bounds(tmpctx, total,
26612662
state->feerate_per_kw_commitment,
@@ -2745,7 +2746,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg)
27452746
* to an invalid number, 1 (initiator sets; valid is even) */
27462747
tx_state->funding_serial = 1;
27472748
/* Figure out what the funding transaction looks like! */
2748-
if (!run_tx_interactive(state, tx_state, &tx_state->psbt, TX_ACCEPTER))
2749+
if (!run_tx_interactive(state, tx_state, &tx_state->psbt, tx_state->our_role))
27492750
return;
27502751

27512752
if (state->require_confirmed_inputs[LOCAL]) {
@@ -2983,7 +2984,7 @@ static void opener_start(struct state *state, u8 *msg)
29832984
&expected_rates))
29842985
master_badmsg(WIRE_DUALOPEND_OPENER_INIT, msg);
29852986

2986-
state->our_role = TX_INITIATOR;
2987+
tx_state->our_role = TX_INITIATOR;
29872988
wally_psbt_get_locktime(tx_state->psbt, &locktime);
29882989
tx_state->tx_locktime = locktime;
29892990
open_tlv = tlv_opening_tlvs_new(tmpctx);
@@ -3299,7 +3300,7 @@ static void opener_start(struct state *state, u8 *msg)
32993300
/* We need to check that the inputs we've already provided
33003301
* via the API are confirmed :/ */
33013302
if (state->require_confirmed_inputs[REMOTE]) {
3302-
err_reason = validate_inputs(state, tx_state, state->our_role);
3303+
err_reason = validate_inputs(state, tx_state, tx_state->our_role);
33033304
if (err_reason) {
33043305
open_abort(state, "%s", err_reason);
33053306
return;
@@ -3319,7 +3320,7 @@ static void opener_start(struct state *state, u8 *msg)
33193320

33203321
/* Now that we know the total of the channel, we can
33213322
* set the reserve */
3322-
set_reserve(tx_state, total, state->our_role);
3323+
set_reserve(tx_state, total, tx_state->our_role);
33233324

33243325
if (!check_config_bounds(tmpctx, total,
33253326
state->feerate_per_kw_commitment,
@@ -3341,7 +3342,7 @@ static void opener_start(struct state *state, u8 *msg)
33413342
}
33423343

33433344
/* Figure out what the funding transaction looks like! */
3344-
if (!run_tx_interactive(state, tx_state, &tx_state->psbt, TX_INITIATOR))
3345+
if (!run_tx_interactive(state, tx_state, &tx_state->psbt, tx_state->our_role))
33453346
return;
33463347

33473348
if (state->require_confirmed_inputs[LOCAL]) {
@@ -3407,7 +3408,7 @@ static void rbf_wrap_up(struct state *state,
34073408
* - if is the *opener*:
34083409
* - MUST send at least one `tx_add_output`, which contains the
34093410
* channel's funding output */
3410-
if (state->our_role == TX_INITIATOR)
3411+
if (tx_state->our_role == TX_INITIATOR)
34113412
add_funding_output(tx_state, state, total);
34123413
else
34133414
/* if accepter, set to an invalid number, 1 (odd is invalid) */
@@ -3416,7 +3417,7 @@ static void rbf_wrap_up(struct state *state,
34163417
/* Add all of our inputs/outputs to the changeset */
34173418
init_changeset(tx_state, tx_state->psbt);
34183419

3419-
if (state->our_role == TX_INITIATOR) {
3420+
if (tx_state->our_role == TX_INITIATOR) {
34203421
/* Send our first message; opener initiates */
34213422
if (!send_next(state, tx_state, &tx_state->psbt, &aborted)) {
34223423
if (!aborted)
@@ -3427,13 +3428,13 @@ static void rbf_wrap_up(struct state *state,
34273428

34283429
if (!run_tx_interactive(state, tx_state,
34293430
&tx_state->psbt,
3430-
state->our_role)) {
3431+
tx_state->our_role)) {
34313432
return;
34323433
}
34333434

34343435
if (state->require_confirmed_inputs[LOCAL]) {
34353436
err_reason = validate_inputs(state, tx_state,
3436-
state->our_role == TX_INITIATOR ?
3437+
tx_state->our_role == TX_INITIATOR ?
34373438
TX_ACCEPTER : TX_INITIATOR);
34383439
if (err_reason) {
34393440
open_abort(state, "%s", err_reason);
@@ -3464,7 +3465,7 @@ static void rbf_wrap_up(struct state *state,
34643465
/* Find the funding transaction txid */
34653466
psbt_txid(NULL, tx_state->psbt, &tx_state->funding.txid, NULL);
34663467

3467-
if (state->our_role == TX_ACCEPTER)
3468+
if (tx_state->our_role == TX_ACCEPTER)
34683469
/* FIXME: lease fee rate !? */
34693470
msg = accepter_commits(state, tx_state, total, &err_reason);
34703471
else
@@ -3480,7 +3481,7 @@ static void rbf_wrap_up(struct state *state,
34803481
return;
34813482
}
34823483

3483-
if (state->our_role == TX_ACCEPTER)
3484+
if (tx_state->our_role == TX_ACCEPTER)
34843485
handle_send_tx_sigs(state, msg);
34853486
else
34863487
wire_sync_write(REQ_FD, take(msg));
@@ -3501,6 +3502,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
35013502

35023503
/* We need a new tx_state! */
35033504
tx_state = new_tx_state(rbf_ctx);
3505+
tx_state->our_role = TX_INITIATOR;
35043506
/* Copy over the channel config info -- everything except
35053507
* the reserve will be the same */
35063508
tx_state->localconf = state->tx_state->localconf;
@@ -3635,7 +3637,7 @@ static void rbf_local_start(struct state *state, u8 *msg)
36353637
}
36363638

36373639
/* Now that we know the total of the channel, we can set the reserve */
3638-
set_reserve(tx_state, total, state->our_role);
3640+
set_reserve(tx_state, total, tx_state->our_role);
36393641

36403642
if (!check_config_bounds(tmpctx, total,
36413643
state->feerate_per_kw_commitment,
@@ -3679,6 +3681,7 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
36793681

36803682
/* We need a new tx_state! */
36813683
tx_state = new_tx_state(rbf_ctx);
3684+
tx_state->our_role = TX_ACCEPTER;
36823685
ack_rbf_tlvs = tlv_tx_ack_rbf_tlvs_new(tmpctx);
36833686

36843687
if (!fromwire_tx_init_rbf(tmpctx, rbf_msg, &cid,
@@ -3698,13 +3701,6 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
36983701
"Last funding attempt not complete:"
36993702
" missing your funding tx_sigs");
37003703

3701-
if (state->our_role == TX_INITIATOR) {
3702-
open_abort(state, "%s",
3703-
"Only the channel initiator is allowed"
3704-
" to initiate RBF");
3705-
goto free_rbf_ctx;
3706-
}
3707-
37083704
/* Maybe they want a different funding amount! */
37093705
if (init_rbf_tlvs && init_rbf_tlvs->funding_output_contribution) {
37103706
tx_state->opener_funding =
@@ -3786,7 +3782,7 @@ static void rbf_remote_start(struct state *state, const u8 *rbf_msg)
37863782
}
37873783

37883784
/* Now that we know the total of the channel, we can set the reserve */
3789-
set_reserve(tx_state, total, state->our_role);
3785+
set_reserve(tx_state, total, tx_state->our_role);
37903786

37913787
if (!check_config_bounds(tmpctx, total,
37923788
state->feerate_per_kw_commitment,
@@ -4075,7 +4071,7 @@ static void do_reconnect_dance(struct state *state)
40754071
if (!tx_state->has_commitments)
40764072
send_our_sigs = false;
40774073
}
4078-
if (send_our_sigs && psbt_side_finalized(tx_state->psbt, state->our_role)) {
4074+
if (send_our_sigs && psbt_side_finalized(tx_state->psbt, tx_state->our_role)) {
40794075
msg = psbt_to_tx_sigs_msg(NULL, state, tx_state->psbt);
40804076
peer_write(state->pps, take(msg));
40814077

@@ -4470,13 +4466,13 @@ int main(int argc, char *argv[])
44704466
opener);
44714467

44724468
if (opener == LOCAL) {
4473-
state->our_role = TX_INITIATOR;
4469+
state->tx_state->our_role = TX_INITIATOR;
44744470
ok = amount_msat_to_sat(&state->tx_state->opener_funding, our_msat);
44754471
ok &= amount_sat_sub(&state->tx_state->accepter_funding,
44764472
total_funding,
44774473
state->tx_state->opener_funding);
44784474
} else {
4479-
state->our_role = TX_ACCEPTER;
4475+
state->tx_state->our_role = TX_ACCEPTER;
44804476
ok = amount_msat_to_sat(&state->tx_state->accepter_funding, our_msat);
44814477
ok &= amount_sat_sub(&state->tx_state->opener_funding,
44824478
total_funding,

tests/test_opening.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,59 @@ def test_v2_rbf_single(node_factory, bitcoind, chainparams):
429429
l1.daemon.wait_for_log('sendrawtx exit 0')
430430

431431

432+
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
433+
@pytest.mark.openchannel('v2')
434+
def test_v2_rbf_init_remote(node_factory, bitcoind, chainparams):
435+
l1, l2 = node_factory.get_nodes(2)
436+
437+
l1.rpc.connect(l2.info['id'], 'localhost', l2.port)
438+
amount = 2**24
439+
chan_amount = 100000
440+
bitcoind.rpc.sendtoaddress(l1.rpc.newaddr()['bech32'], amount / 10**8 + 0.01)
441+
bitcoind.rpc.sendtoaddress(l2.rpc.newaddr()['bech32'], amount / 10**8 + 0.01)
442+
bitcoind.generate_block(1)
443+
# Wait for it to arrive.
444+
wait_for(lambda: len(l1.rpc.listfunds()['outputs']) > 0)
445+
wait_for(lambda: len(l2.rpc.listfunds()['outputs']) > 0)
446+
447+
res = l1.rpc.fundchannel(l2.info['id'], chan_amount)
448+
chan_id = res['channel_id']
449+
vins = bitcoind.rpc.decoderawtransaction(res['tx'])['vin']
450+
assert(only_one(vins))
451+
prev_utxos = ["{}:{}".format(vins[0]['txid'], vins[0]['vout'])]
452+
453+
# Check that we're waiting for lockin
454+
l1.daemon.wait_for_log(' to DUALOPEND_AWAITING_LOCKIN')
455+
456+
next_feerate = find_next_feerate(l1, l2)
457+
458+
# Initiate an RBF
459+
startweight = 42 + 172 # base weight, funding output
460+
initpsbt = l2.rpc.fundpsbt(chan_amount, next_feerate, startweight)
461+
462+
# Do the bump from the remote
463+
bump = l2.rpc.openchannel_bump(chan_id, chan_amount, initpsbt['psbt'])
464+
465+
update = l2.rpc.openchannel_update(chan_id, bump['psbt'])
466+
assert update['commitments_secured']
467+
468+
# Sign our inputs, and continue
469+
signed_psbt = l2.rpc.signpsbt(update['psbt'])['signed_psbt']
470+
471+
l2.rpc.openchannel_signed(chan_id, signed_psbt)
472+
473+
bitcoind.generate_block(1)
474+
sync_blockheight(bitcoind, [l1])
475+
l1.daemon.wait_for_log(' to CHANNELD_NORMAL')
476+
l2.daemon.wait_for_log(' to CHANNELD_NORMAL')
477+
478+
# Check that feerate info is gone
479+
fee_info = only_one(l2.rpc.listpeerchannels(l1.info['id'])['channels'])
480+
assert 'initial_feerate' not in fee_info
481+
assert 'last_feerate' not in fee_info
482+
assert 'next_feerate' not in fee_info
483+
484+
432485
@unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need')
433486
@pytest.mark.openchannel('v2')
434487
def test_v2_rbf_abort_retry(node_factory, bitcoind, chainparams):

0 commit comments

Comments
 (0)