diff --git a/common/coin_mvt.c b/common/coin_mvt.c index 5949f1342..37ae80093 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -41,6 +41,8 @@ static const char *mvt_tags[] = { "stolen", "to_miner", "opener", + "lease_fee", + "leased", }; const char *mvt_tag_str(enum mvt_tag tag) @@ -209,7 +211,8 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, u32 blockheight, const struct amount_msat amount, const struct amount_sat output_val, - bool is_opener) + bool is_opener, + bool is_leased) { struct chain_coin_mvt *mvt; @@ -222,6 +225,9 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, if (is_opener) tal_arr_expand(&mvt->tags, OPENER); + if (is_leased) + tal_arr_expand(&mvt->tags, LEASED); + return mvt; } @@ -319,9 +325,11 @@ struct chain_coin_mvt *new_coin_penalty_sat(const tal_t *ctx, amount, false); } -struct channel_coin_mvt *new_coin_pushed(const tal_t *ctx, - const struct channel_id *cid, - struct amount_msat amount) +struct channel_coin_mvt *new_coin_channel_push(const tal_t *ctx, + const struct channel_id *cid, + struct amount_msat amount, + enum mvt_tag tag, + bool is_credit) { struct sha256 empty_hash; /* Use a 0'd out payment hash */ @@ -329,7 +337,7 @@ struct channel_coin_mvt *new_coin_pushed(const tal_t *ctx, return new_channel_coin_mvt(ctx, cid, empty_hash, NULL, amount, - new_tag_arr(ctx, PUSHED), false, + new_tag_arr(ctx, tag), is_credit, AMOUNT_MSAT(0)); } diff --git a/common/coin_mvt.h b/common/coin_mvt.h index 9dfcc80c1..bac404974 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -38,6 +38,8 @@ enum mvt_tag { STOLEN = 21, TO_MINER = 22, OPENER = 23, + LEASE_FEE = 24, + LEASED = 25, }; struct channel_coin_mvt { @@ -174,7 +176,8 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, u32 blockheight, const struct amount_msat amount, const struct amount_sat output_val, - bool is_opener); + bool is_opener, + bool is_leased); struct chain_coin_mvt *new_onchain_htlc_deposit(const tal_t *ctx, const struct bitcoin_outpoint *outpoint, @@ -221,9 +224,11 @@ struct chain_coin_mvt *new_coin_penalty_sat(const tal_t *ctx, u32 blockheight, struct amount_sat amount); -struct channel_coin_mvt *new_coin_pushed(const tal_t *ctx, - const struct channel_id *cid, - struct amount_msat amount); +struct channel_coin_mvt *new_coin_channel_push(const tal_t *ctx, + const struct channel_id *cid, + struct amount_msat amount, + enum mvt_tag tag, + bool is_credit); struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, const struct chain_coin_mvt *chain_mvt, diff --git a/lightningd/channel.c b/lightningd/channel.c index 617b89ad9..e0c1f8779 100644 --- a/lightningd/channel.c +++ b/lightningd/channel.c @@ -155,7 +155,8 @@ new_inflight(struct channel *channel, const u32 lease_expiry, const secp256k1_ecdsa_signature *lease_commit_sig, const u32 lease_chan_max_msat, const u16 lease_chan_max_ppt, - const u32 lease_blockheight_start) + const u32 lease_blockheight_start, + const struct amount_msat lease_fee) { struct wally_psbt *last_tx_psbt_clone; struct channel_inflight *inflight @@ -191,6 +192,7 @@ new_inflight(struct channel *channel, inflight->lease_chan_max_msat = lease_chan_max_msat; inflight->lease_chan_max_ppt = lease_chan_max_ppt; + inflight->lease_fee = lease_fee; list_add_tail(&channel->inflights, &inflight->list); tal_add_destructor(inflight, destroy_inflight); diff --git a/lightningd/channel.h b/lightningd/channel.h index 76a73d5b4..4f3fb1d28 100644 --- a/lightningd/channel.h +++ b/lightningd/channel.h @@ -50,6 +50,10 @@ struct channel_inflight { u32 lease_chan_max_msat; u16 lease_chan_max_ppt; u32 lease_blockheight_start; + + /* We save this data so we can do nice accounting; + * on the channel we slot it into the 'push' field */ + struct amount_msat lease_fee; }; struct open_attempt { @@ -318,7 +322,8 @@ new_inflight(struct channel *channel, const secp256k1_ecdsa_signature *lease_commit_sig, const u32 lease_chan_max_msat, const u16 lease_chan_max_ppt, - const u32 lease_blockheight_start); + const u32 lease_blockheight_start, + const struct amount_msat lease_fee); /* Given a txid, find an inflight channel stub. Returns NULL if none found */ struct channel_inflight *channel_inflight_find(struct channel *channel, diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index d44dd87e9..49940eff4 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -132,21 +132,30 @@ void channel_record_open(struct channel *channel) struct chain_coin_mvt *mvt; u32 blockheight; struct amount_msat start_balance; - bool we_pushed = channel->opener == LOCAL - && !amount_msat_zero(channel->push); + bool is_pushed = !amount_msat_zero(channel->push); + bool is_leased = channel->lease_expiry > 0; blockheight = short_channel_id_blocknum(channel->scid); - /* If we pushed funds, add them back into the starting balance */ - if (we_pushed) { - if (!amount_msat_add(&start_balance, - channel->push, channel->our_msat)) - fatal("Unable to add push_msat (%s) + our_msat (%s)", - type_to_string(tmpctx, struct amount_msat, - &channel->push), - type_to_string(tmpctx, struct amount_msat, - &channel->our_msat)); - + /* If funds were pushed, add/sub them from the starting balance */ + if (is_pushed) { + if (channel->opener == LOCAL) { + if (!amount_msat_add(&start_balance, + channel->our_msat, channel->push)) + fatal("Unable to add push_msat (%s) + our_msat (%s)", + type_to_string(tmpctx, struct amount_msat, + &channel->push), + type_to_string(tmpctx, struct amount_msat, + &channel->our_msat)); + } else { + if (!amount_msat_sub(&start_balance, + channel->our_msat, channel->push)) + fatal("Unable to sub our_msat (%s) - push (%s)", + type_to_string(tmpctx, struct amount_msat, + &channel->our_msat), + type_to_string(tmpctx, struct amount_msat, + &channel->push)); + } } else start_balance = channel->our_msat; @@ -156,15 +165,18 @@ void channel_record_open(struct channel *channel) blockheight, start_balance, channel->funding_sats, - channel->opener == LOCAL); + channel->opener == LOCAL, + is_leased); notify_chain_mvt(channel->peer->ld, mvt); - /* If we pushed sats, *now* record them as a withdrawal */ - if (we_pushed) + /* If we pushed sats, *now* record them */ + if (is_pushed) notify_channel_mvt(channel->peer->ld, - new_coin_pushed(tmpctx, &channel->cid, - channel->push)); + new_coin_channel_push(tmpctx, &channel->cid, + channel->push, + is_leased ? LEASE_FEE : PUSHED, + channel->opener == REMOTE)); } static void lockin_complete(struct channel *channel) diff --git a/lightningd/dual_open_control.c b/lightningd/dual_open_control.c index a53c38be9..badaaf6f8 100644 --- a/lightningd/dual_open_control.c +++ b/lightningd/dual_open_control.c @@ -1079,12 +1079,13 @@ wallet_update_channel(struct lightningd *ld, u32 funding_feerate, struct wally_psbt *psbt STEALS, const u32 lease_expiry, + struct amount_sat lease_fee, secp256k1_ecdsa_signature *lease_commit_sig STEALS, const u32 lease_chan_max_msat, const u16 lease_chan_max_ppt, const u32 lease_blockheight_start) { - struct amount_msat our_msat; + struct amount_msat our_msat, lease_fee_msat; struct channel_inflight *inflight; if (!amount_sat_to_msat(&our_msat, our_funding)) { @@ -1092,6 +1093,11 @@ wallet_update_channel(struct lightningd *ld, return NULL; } + if (!amount_sat_to_msat(&lease_fee_msat, lease_fee)) { + log_broken(channel->log, "Unable to convert 'lease_fee'"); + return NULL; + } + assert(channel->unsaved_dbid == 0); assert(channel->dbid != 0); @@ -1099,6 +1105,7 @@ wallet_update_channel(struct lightningd *ld, channel->funding_sats = total_funding; channel->our_funds = our_funding; channel->our_msat = our_msat; + channel->push = lease_fee_msat; channel->msat_to_us_min = our_msat; channel->msat_to_us_max = our_msat; channel->lease_expiry = lease_expiry; @@ -1134,7 +1141,8 @@ wallet_update_channel(struct lightningd *ld, channel->lease_commit_sig, channel->lease_chan_max_msat, channel->lease_chan_max_ppt, - lease_blockheight_start); + lease_blockheight_start, + channel->push); wallet_inflight_add(ld->wallet, inflight); return inflight; @@ -1157,11 +1165,12 @@ wallet_commit_channel(struct lightningd *ld, struct wally_psbt *psbt STEALS, const u32 lease_blockheight_start, const u32 lease_expiry, + const struct amount_sat lease_fee, secp256k1_ecdsa_signature *lease_commit_sig STEALS, const u32 lease_chan_max_msat, const u16 lease_chan_max_ppt) { - struct amount_msat our_msat; + struct amount_msat our_msat, lease_fee_msat; struct channel_inflight *inflight; if (!amount_sat_to_msat(&our_msat, our_funding)) { @@ -1169,6 +1178,11 @@ wallet_commit_channel(struct lightningd *ld, return NULL; } + if (!amount_sat_to_msat(&lease_fee_msat, lease_fee)) { + log_broken(channel->log, "Unable to convert lease fee"); + return NULL; + } + /* Get a key to use for closing outputs from this tx */ channel->final_key_idx = wallet_get_newindex(ld); if (channel->final_key_idx == -1) { @@ -1190,6 +1204,7 @@ wallet_commit_channel(struct lightningd *ld, channel->funding_sats = total_funding; channel->our_funds = our_funding; channel->our_msat = our_msat; + channel->push = lease_fee_msat; channel->msat_to_us_min = our_msat; channel->msat_to_us_max = our_msat; @@ -1253,7 +1268,8 @@ wallet_commit_channel(struct lightningd *ld, channel->lease_commit_sig, channel->lease_chan_max_msat, channel->lease_chan_max_ppt, - lease_blockheight_start); + lease_blockheight_start, + channel->push); wallet_inflight_add(ld->wallet, inflight); return inflight; @@ -2739,7 +2755,7 @@ static void handle_commit_received(struct subd *dualopend, u16 lease_chan_max_ppt; u32 feerate_funding, feerate_commitment, lease_expiry, lease_chan_max_msat, lease_blockheight_start; - struct amount_sat total_funding, funding_ours; + struct amount_sat total_funding, funding_ours, lease_fee; u8 *remote_upfront_shutdown_script, *local_upfront_shutdown_script; struct penalty_base *pbase; @@ -2772,6 +2788,7 @@ static void handle_commit_received(struct subd *dualopend, &remote_upfront_shutdown_script, &lease_blockheight_start, &lease_expiry, + &lease_fee, &lease_commit_sig, &lease_chan_max_msat, &lease_chan_max_ppt)) { @@ -2817,6 +2834,7 @@ static void handle_commit_received(struct subd *dualopend, psbt, lease_blockheight_start, lease_expiry, + lease_fee, lease_commit_sig, lease_chan_max_msat, lease_chan_max_ppt))) { @@ -2849,6 +2867,7 @@ static void handle_commit_received(struct subd *dualopend, feerate_funding, psbt, lease_expiry, + lease_fee, lease_commit_sig, lease_chan_max_msat, lease_chan_max_ppt, diff --git a/lightningd/peer_control.c b/lightningd/peer_control.c index 4fc9279fe..fc81ee52b 100644 --- a/lightningd/peer_control.c +++ b/lightningd/peer_control.c @@ -1230,6 +1230,7 @@ static void update_channel_from_inflight(struct lightningd *ld, /* Lease infos ! */ channel->lease_expiry = inflight->lease_expiry; + channel->push = inflight->lease_fee; tal_free(channel->lease_commit_sig); channel->lease_commit_sig = tal_steal(channel, inflight->lease_commit_sig); diff --git a/openingd/dualopend.c b/openingd/dualopend.c index 7711f6224..78c87e651 100644 --- a/openingd/dualopend.c +++ b/openingd/dualopend.c @@ -113,6 +113,9 @@ struct tx_state { /* If delay til the channel funds lease expires */ u32 lease_expiry; + /* Total fee for lease */ + struct amount_sat lease_fee; + /* Lease's commit sig */ secp256k1_ecdsa_signature *lease_commit_sig; @@ -130,6 +133,7 @@ static struct tx_state *new_tx_state(const tal_t *ctx) tx_state->remote_funding_sigs_rcvd = false; tx_state->lease_expiry = 0; + tx_state->lease_fee = AMOUNT_SAT(0); tx_state->blockheight = 0; tx_state->lease_commit_sig = NULL; tx_state->lease_chan_max_msat = 0; @@ -567,7 +571,6 @@ static char *check_balances(const tal_t *ctx, struct state *state, struct tx_state *tx_state, struct wally_psbt *psbt, - struct amount_sat lease_fee, u32 feerate_per_kw_funding) { struct amount_sat initiator_inputs, initiator_outs, @@ -721,9 +724,11 @@ static char *check_balances(const tal_t *ctx, /* The lease_fee has been added to the accepter_funding, * but the opener_funding is responsible for covering it, * so we do a little switcheroo here */ - if (!amount_sat_add(&initiator_outs, initiator_outs, lease_fee)) + if (!amount_sat_add(&initiator_outs, initiator_outs, + tx_state->lease_fee)) return "overflow adding lease_fee to initiator's funding"; - if (!amount_sat_sub(&accepter_outs, accepter_outs, lease_fee)) + if (!amount_sat_sub(&accepter_outs, accepter_outs, + tx_state->lease_fee)) return "unable to subtract lease_fee from accepter's funding"; for (size_t i = 0; i < psbt->num_outputs; i++) { @@ -787,7 +792,7 @@ static char *check_balances(const tal_t *ctx, type_to_string(tmpctx, struct amount_sat, &initiator_outs), type_to_string(tmpctx, struct amount_sat, - &lease_fee)); + &tx_state->lease_fee)); } @@ -806,7 +811,8 @@ static char *check_balances(const tal_t *ctx, return tal_fmt(tmpctx, "accepter inputs %s less than outputs %s (lease fee %s)", type_to_string(tmpctx, struct amount_sat, &accepter_inputs), type_to_string(tmpctx, struct amount_sat, &accepter_outs), - type_to_string(tmpctx, struct amount_sat, &lease_fee)); + type_to_string(tmpctx, struct amount_sat, + &tx_state->lease_fee)); } if (!amount_sat_sub(&initiator_diff, initiator_inputs, @@ -1726,7 +1732,6 @@ static void revert_channel_state(struct state *state) static u8 *accepter_commits(struct state *state, struct tx_state *tx_state, struct amount_sat total, - struct amount_sat lease_fee, char **err_reason) { struct wally_tx_output *direct_outputs[NUM_SIDES]; @@ -1762,7 +1767,6 @@ static u8 *accepter_commits(struct state *state, /* Check tx funds are sane */ error = check_balances(tmpctx, state, tx_state, tx_state->psbt, - lease_fee, tx_state->feerate_per_kw_funding); if (error) { *err_reason = tal_fmt(tmpctx, "Insufficiently funded" @@ -1960,6 +1964,7 @@ static u8 *accepter_commits(struct state *state, state->upfront_shutdown_script[REMOTE], tx_state->blockheight, tx_state->lease_expiry, + tx_state->lease_fee, tx_state->lease_commit_sig, tx_state->lease_chan_max_msat, tx_state->lease_chan_max_ppt); @@ -2039,7 +2044,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg) struct channel_id cid, full_cid; char *err_reason; u8 *msg; - struct amount_sat total, requested_amt, lease_fee, our_accept; + struct amount_sat total, requested_amt, our_accept; enum dualopend_wire msg_type; struct tx_state *tx_state = state->tx_state; @@ -2209,13 +2214,14 @@ static void accepter_start(struct state *state, const u8 *oc2_msg) tx_state->accepter_funding, requested_amt, tx_state->feerate_per_kw_funding, - &lease_fee)) + &tx_state->lease_fee)) negotiation_failed(state, "Unable to calculate lease fee"); /* Add it to the accepter's total */ if (!amount_sat_add(&tx_state->accepter_funding, - tx_state->accepter_funding, lease_fee)) + tx_state->accepter_funding, + tx_state->lease_fee)) negotiation_failed(state, "Unable to add accepter's funding" @@ -2225,11 +2231,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg) &tx_state->accepter_funding), type_to_string(tmpctx, struct amount_sat, - &lease_fee)); - - } else { - tx_state->lease_expiry = 0; - lease_fee = AMOUNT_SAT(0); + &tx_state->lease_fee)); } /* Check that total funding doesn't overflow */ @@ -2342,8 +2344,7 @@ static void accepter_start(struct state *state, const u8 *oc2_msg) if (!run_tx_interactive(state, tx_state, &tx_state->psbt, TX_ACCEPTER)) return; - msg = accepter_commits(state, tx_state, total, - lease_fee, &err_reason); + msg = accepter_commits(state, tx_state, total, &err_reason); if (!msg) { if (err_reason) negotiation_failed(state, "%s", err_reason); @@ -2380,7 +2381,6 @@ static void add_funding_output(struct tx_state *tx_state, static u8 *opener_commits(struct state *state, struct tx_state *tx_state, struct amount_sat total, - struct amount_sat lease_fee, char **err_reason) { struct channel_id cid; @@ -2416,7 +2416,6 @@ static u8 *opener_commits(struct state *state, error = check_balances(tmpctx, state, tx_state, tx_state->psbt, - lease_fee, tx_state->feerate_per_kw_funding); if (error) { *err_reason = tal_fmt(tmpctx, "Insufficiently funded funding " @@ -2649,6 +2648,7 @@ static u8 *opener_commits(struct state *state, state->upfront_shutdown_script[REMOTE], tx_state->blockheight, tx_state->lease_expiry, + tx_state->lease_fee, tx_state->lease_commit_sig, tx_state->lease_chan_max_msat, tx_state->lease_chan_max_ppt); @@ -2661,7 +2661,7 @@ static void opener_start(struct state *state, u8 *msg) struct tlv_accept_tlvs *a_tlv; struct channel_id cid; char *err_reason; - struct amount_sat total, requested_sats, lease_fee; + struct amount_sat total, requested_sats; bool dry_run; struct lease_rates *expected_rates; struct tx_state *tx_state = state->tx_state; @@ -2882,13 +2882,14 @@ static void opener_start(struct state *state, u8 *msg) if (!lease_rates_calc_fee(rates, tx_state->accepter_funding, requested_sats, tx_state->feerate_per_kw_funding, - &lease_fee)) + &tx_state->lease_fee)) negotiation_failed(state, "Unable to calculate lease fee"); /* Add it to the accepter's total */ if (!amount_sat_add(&tx_state->accepter_funding, - tx_state->accepter_funding, lease_fee)) { + tx_state->accepter_funding, + tx_state->lease_fee)) { negotiation_failed(state, "Unable to add accepter's funding" @@ -2898,7 +2899,7 @@ static void opener_start(struct state *state, u8 *msg) &tx_state->accepter_funding), type_to_string(tmpctx, struct amount_sat, - &lease_fee)); + &tx_state->lease_fee)); return; } @@ -2909,8 +2910,7 @@ static void opener_start(struct state *state, u8 *msg) = rates->channel_fee_max_base_msat; tx_state->lease_chan_max_ppt = rates->channel_fee_max_proportional_thousandths; - } else - lease_fee = AMOUNT_SAT(0); + } /* Check that total funding doesn't overflow */ if (!amount_sat_add(&total, tx_state->opener_funding, @@ -2975,7 +2975,7 @@ static void opener_start(struct state *state, u8 *msg) if (!run_tx_interactive(state, tx_state, &tx_state->psbt, TX_INITIATOR)) return; - msg = opener_commits(state, tx_state, total, lease_fee, &err_reason); + msg = opener_commits(state, tx_state, total, &err_reason); if (!msg) { if (err_reason) open_err_warn(state, "%s", err_reason); @@ -3075,11 +3075,9 @@ static void rbf_wrap_up(struct state *state, if (state->our_role == TX_ACCEPTER) /* FIXME: lease fee rate !? */ - msg = accepter_commits(state, tx_state, total, - AMOUNT_SAT(0), &err_reason); + msg = accepter_commits(state, tx_state, total, &err_reason); else - msg = opener_commits(state, tx_state, total, - AMOUNT_SAT(0), &err_reason); + msg = opener_commits(state, tx_state, total, &err_reason); if (!msg) { if (err_reason) diff --git a/openingd/dualopend_wire.csv b/openingd/dualopend_wire.csv index 3b3620c74..48177925b 100644 --- a/openingd/dualopend_wire.csv +++ b/openingd/dualopend_wire.csv @@ -150,6 +150,7 @@ msgdata,dualopend_commit_rcvd,remote_shutdown_len,u16, msgdata,dualopend_commit_rcvd,remote_shutdown_scriptpubkey,u8,remote_shutdown_len msgdata,dualopend_commit_rcvd,lease_start_blockheight,u32, msgdata,dualopend_commit_rcvd,lease_expiry,u32, +msgdata,dualopend_commit_rcvd,lease_fee,amount_sat, msgdata,dualopend_commit_rcvd,lease_commit_sig,?secp256k1_ecdsa_signature, msgdata,dualopend_commit_rcvd,lease_chan_max_msat,u32, msgdata,dualopend_commit_rcvd,lease_chan_max_ppt,u16, diff --git a/tests/test_closing.py b/tests/test_closing.py index c5f420e9e..ea3fda115 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -7,7 +7,7 @@ from utils import ( only_one, sync_blockheight, wait_for, TIMEOUT, account_balance, first_channel_id, closing_fee, TEST_NETWORK, scriptpubkey_addr, calc_lease_fee, EXPERIMENTAL_FEATURES, - check_utxos_channel, anchor_expected + check_utxos_channel, anchor_expected, check_coin_moves ) import os @@ -824,11 +824,12 @@ def test_channel_lease_falls_behind(node_factory, bitcoind): @pytest.mark.openchannel('v2') @pytest.mark.developer("requres 'dev-queryrates'") @pytest.mark.slow_test -def test_channel_lease_post_expiry(node_factory, bitcoind): +def test_channel_lease_post_expiry(node_factory, bitcoind, chainparams): + coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') opts = {'funder-policy': 'match', 'funder-policy-mod': 100, 'lease-fee-base-msat': '100sat', 'lease-fee-basis': 100, - 'may_reconnect': True} + 'may_reconnect': True, 'plugin': coin_mvt_plugin} l1, l2, = node_factory.get_nodes(2, opts=opts) @@ -854,6 +855,7 @@ def test_channel_lease_post_expiry(node_factory, bitcoind): bitcoind.generate_block(6) l1.daemon.wait_for_log('to CHANNELD_NORMAL') + channel_id = first_channel_id(l1, l2) wait_for(lambda: [c['active'] for c in l1.rpc.listchannels(l1.get_channel_scid(l2))['channels']] == [True, True]) @@ -897,6 +899,30 @@ def test_channel_lease_post_expiry(node_factory, bitcoind): l1.rpc.close(chan) l2.daemon.wait_for_log('State changed from CLOSINGD_SIGEXCHANGE to CLOSINGD_COMPLETE') + bitcoind.generate_block(2) + sync_blockheight(bitcoind, [l1, l2]) + l1.daemon.wait_for_log('Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by MUTUAL_CLOSE') + l2.daemon.wait_for_log('Resolved FUNDING_TRANSACTION/FUNDING_OUTPUT by MUTUAL_CLOSE') + + channel_mvts_1 = [ + {'type': 'chain_mvt', 'credit': 506432000, 'debit': 0, 'tags': ['channel_open', 'opener', 'leased']}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 6432000, 'tags': ['lease_fee'], 'fees': '0msat'}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 10000, 'tags': ['invoice'], 'fees': '0msat'}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 499990000, 'tags': ['channel_close']}, + ] + + channel_mvts_2 = [ + {'type': 'chain_mvt', 'credit': 500000000, 'debit': 0, 'tags': ['channel_open', 'leased']}, + {'type': 'channel_mvt', 'credit': 6432000, 'debit': 0, 'tags': ['lease_fee'], 'fees': '0msat'}, + {'type': 'channel_mvt', 'credit': 10000, 'debit': 0, 'tags': ['invoice'], 'fees': '0msat'}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 506442000, 'tags': ['channel_close']}, + ] + + check_coin_moves(l1, channel_id, channel_mvts_1, chainparams) + check_coin_moves(l2, channel_id, channel_mvts_2, chainparams) + assert account_balance(l1, channel_id) == 0 + assert account_balance(l2, channel_id) == 0 + @unittest.skipIf(TEST_NETWORK != 'regtest', 'elementsd doesnt yet support PSBT features we need') @pytest.mark.openchannel('v2') diff --git a/tests/test_connection.py b/tests/test_connection.py index 738154b8f..1e717ebed 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1074,7 +1074,7 @@ def test_funding_push(node_factory, bitcoind, chainparams): coin_mvt_plugin = os.path.join(os.getcwd(), 'tests/plugins/coin_movements.py') l1 = node_factory.get_node(options={'plugin': coin_mvt_plugin}) - l2 = node_factory.get_node() + l2 = node_factory.get_node(options={'plugin': coin_mvt_plugin}) l1.rpc.connect(l2.info['id'], 'localhost', l2.port) @@ -1103,11 +1103,17 @@ def test_funding_push(node_factory, bitcoind, chainparams): chanid = first_channel_id(l2, l1) # give the file write a second time.sleep(1) - channel_mvts = [ + channel_mvts_1 = [ {'type': 'chain_mvt', 'credit': 16777215000, 'debit': 0, 'tags': ['channel_open', 'opener']}, - {'type': 'channel_mvt', 'credit': 0, 'debit': 20000000, 'tags': ['pushed']}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 20000000, 'tags': ['pushed'], 'fees': '0msat'}, ] - check_coin_moves(l1, chanid, channel_mvts, chainparams) + channel_mvts_2 = [ + {'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tags': ['channel_open']}, + {'type': 'channel_mvt', 'credit': 20000000, 'debit': 0, 'tags': ['pushed'], 'fees': '0msat'}, + ] + check_coin_moves(l1, chanid, channel_mvts_1, chainparams) + check_coin_moves(l2, chanid, channel_mvts_2, chainparams) + assert account_balance(l1, chanid) == (amount - push_sat) * 1000 diff --git a/wallet/db.c b/wallet/db.c index 21806c2c2..23fa2866c 100644 --- a/wallet/db.c +++ b/wallet/db.c @@ -869,6 +869,7 @@ static struct migration dbmigrations[] = { BUILD_ASSERT_OR_ZERO(19 == SENT_REMOVE_ACK_REVOCATION)], NULL}, {SQL("ALTER TABLE channel_htlcs ADD fees_msat BIGINT DEFAULT 0"), NULL}, + {SQL("ALTER TABLE channel_funding_inflights ADD lease_fee BIGINT DEFAULT 0"), NULL}, }; /* Leak tracking. */ diff --git a/wallet/test/run-wallet.c b/wallet/test/run-wallet.c index 3eed52759..01348b60c 100644 --- a/wallet/test/run-wallet.c +++ b/wallet/test/run-wallet.c @@ -1614,7 +1614,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) funding_psbt, last_tx, sig, - 1, lease_commit_sig, 2, 4, 22); + 1, lease_commit_sig, 2, 4, 22, + AMOUNT_MSAT(10)); /* do inflights get correctly added to the channel? */ wallet_inflight_add(w, inflight); @@ -1636,7 +1637,8 @@ static bool test_channel_inflight_crud(struct lightningd *ld, const tal_t *ctx) funding_psbt, last_tx, sig, - 0, NULL, 0, 0, 0); + 0, NULL, 0, 0, 0, + AMOUNT_MSAT(0)); wallet_inflight_add(w, inflight); CHECK_MSG(c2 = wallet_channel_load(w, chan->dbid), tal_fmt(w, "Load from DB")); diff --git a/wallet/wallet.c b/wallet/wallet.c index 62bae46bb..a08056d7b 100644 --- a/wallet/wallet.c +++ b/wallet/wallet.c @@ -1003,8 +1003,9 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight) ", lease_chan_max_ppt" ", lease_expiry" ", lease_blockheight_start" + ", lease_fee" ") VALUES (" - "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); + "?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?);")); db_bind_u64(stmt, 0, inflight->channel->dbid); db_bind_txid(stmt, 1, &inflight->funding->outpoint.txid); @@ -1022,12 +1023,14 @@ void wallet_inflight_add(struct wallet *w, struct channel_inflight *inflight) db_bind_int(stmt, 11, inflight->lease_chan_max_ppt); db_bind_int(stmt, 12, inflight->lease_expiry); db_bind_int(stmt, 13, inflight->lease_blockheight_start); + db_bind_amount_msat(stmt, 14, &inflight->lease_fee); } else { db_bind_null(stmt, 9); db_bind_null(stmt, 10); db_bind_null(stmt, 11); db_bind_int(stmt, 12, 0); db_bind_null(stmt, 13); + db_bind_null(stmt, 14); } db_exec_prepared_v2(stmt); @@ -1083,6 +1086,7 @@ wallet_stmt2inflight(struct wallet *w, struct db_stmt *stmt, struct channel *chan) { struct amount_sat funding_sat, our_funding_sat; + struct amount_msat lease_fee; struct bitcoin_outpoint funding; struct bitcoin_signature last_sig; struct channel_inflight *inflight; @@ -1106,14 +1110,18 @@ wallet_stmt2inflight(struct wallet *w, struct db_stmt *stmt, lease_chan_max_msat = db_col_int(stmt, "lease_chan_max_msat"); lease_chan_max_ppt = db_col_int(stmt, "lease_chan_max_ppt"); lease_blockheight_start = db_col_int(stmt, "lease_blockheight_start"); + db_col_amount_msat(stmt, "lease_fee", &lease_fee); } else { lease_commit_sig = NULL; lease_chan_max_msat = 0; lease_chan_max_ppt = 0; lease_blockheight_start = 0; + lease_fee = AMOUNT_MSAT(0); + db_col_ignore(stmt, "lease_chan_max_msat"); db_col_ignore(stmt, "lease_chan_max_ppt"); db_col_ignore(stmt, "lease_blockheight_start"); + db_col_ignore(stmt, "lease_fee"); } inflight = new_inflight(chan, &funding, @@ -1127,7 +1135,8 @@ wallet_stmt2inflight(struct wallet *w, struct db_stmt *stmt, lease_commit_sig, lease_chan_max_msat, lease_chan_max_ppt, - lease_blockheight_start); + lease_blockheight_start, + lease_fee); /* Pull out the serialized tx-sigs-received-ness */ inflight->remote_tx_sigs = db_col_int(stmt, "funding_tx_remote_sigs_received"); @@ -1155,6 +1164,7 @@ static bool wallet_channel_load_inflights(struct wallet *w, ", lease_chan_max_msat" ", lease_chan_max_ppt" ", lease_blockheight_start" + ", lease_fee" " FROM channel_funding_inflights" " WHERE channel_id = ?" " ORDER BY funding_feerate"));