From b6463174d68bd8ad82511027d739fb79fc6303c0 Mon Sep 17 00:00:00 2001 From: niftynei Date: Mon, 6 Dec 2021 12:24:20 -0600 Subject: [PATCH] coin moves: turn 'tag' into 'tags' array, add OPENER tag Channels that the node has hopened will now be tagged with 'opener' in a list of tags. --- common/coin_mvt.c | 84 ++++++++---- common/coin_mvt.h | 24 ++-- doc/PLUGINS.md | 2 +- lightningd/channel_control.c | 3 +- lightningd/coin_mvts.c | 8 +- lightningd/notification.c | 6 +- lightningd/onchain_control.c | 2 + tests/test_closing.py | 246 +++++++++++++++++------------------ tests/test_connection.py | 4 +- tests/test_plugin.py | 20 +-- tests/utils.py | 22 ++-- 11 files changed, 234 insertions(+), 187 deletions(-) diff --git a/common/coin_mvt.c b/common/coin_mvt.c index a9bb5dee6..85f999057 100644 --- a/common/coin_mvt.c +++ b/common/coin_mvt.c @@ -40,18 +40,27 @@ static const char *mvt_tags[] = { "penalized", "stolen", "to_miner", + "opener", }; + const char *mvt_tag_str(enum mvt_tag tag) { return mvt_tags[tag]; } +enum mvt_tag *new_tag_arr(const tal_t *ctx, enum mvt_tag tag) +{ + enum mvt_tag *tags = tal_arr(ctx, enum mvt_tag, 1); + tags[0] = tag; + return tags; +} + struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, const struct channel_id *cid, struct sha256 payment_hash, u64 *part_id, struct amount_msat amount, - enum mvt_tag tag, + enum mvt_tag *tags STEALS, bool is_credit) { struct channel_coin_mvt *mvt = tal(ctx, struct channel_coin_mvt); @@ -59,7 +68,7 @@ struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, mvt->chan_id = *cid; mvt->payment_hash = tal_dup(mvt, struct sha256, &payment_hash); mvt->part_id = part_id; - mvt->tag = tag; + mvt->tags = tal_steal(mvt, tags); if (is_credit) { mvt->credit = amount; @@ -77,7 +86,8 @@ static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx, const struct bitcoin_txid *tx_txid, const struct bitcoin_outpoint *outpoint, const struct sha256 *payment_hash TAKES, - u32 blockheight, enum mvt_tag tag, + u32 blockheight, + enum mvt_tag *tags STEALS, struct amount_msat amount, bool is_credit, struct amount_sat output_val) @@ -101,7 +111,8 @@ static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx, mvt->payment_hash = NULL; mvt->blockheight = blockheight; - mvt->tag = tag; + mvt->tags = tal_steal(mvt, tags); + if (is_credit) { mvt->credit = amount; mvt->debit = AMOUNT_MSAT(0); @@ -119,7 +130,8 @@ static struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx, const struct bitcoin_txid *tx_txid, const struct bitcoin_outpoint *outpoint, const struct sha256 *payment_hash TAKES, - u32 blockheight, enum mvt_tag tag, + u32 blockheight, + enum mvt_tag *tags, struct amount_sat amt_sat, bool is_credit) { @@ -130,7 +142,7 @@ static struct chain_coin_mvt *new_chain_coin_mvt_sat(const tal_t *ctx, return new_chain_coin_mvt(ctx, account_name, tx_txid, outpoint, payment_hash, - blockheight, tag, amt_msat, is_credit, + blockheight, tags, amt_msat, is_credit, /* All amounts that are sat are * on-chain output values */ amt_sat); @@ -145,7 +157,7 @@ struct chain_coin_mvt *new_onchaind_withdraw(const tal_t *ctx, { return new_chain_coin_mvt_sat(ctx, NULL, spend_txid, outpoint, NULL, - blockheight, tag, + blockheight, new_tag_arr(ctx, tag), amount, false); } @@ -157,7 +169,7 @@ struct chain_coin_mvt *new_onchaind_deposit(const tal_t *ctx, { return new_chain_coin_mvt_sat(ctx, NULL, NULL, outpoint, NULL, - blockheight, tag, + blockheight, new_tag_arr(ctx, tag), amount, true); } @@ -170,7 +182,7 @@ struct chain_coin_mvt *new_coin_journal_entry(const tal_t *ctx, { return new_chain_coin_mvt(ctx, NULL, txid, outpoint, NULL, - blockheight, JOURNAL, + blockheight, new_tag_arr(ctx, JOURNAL), amount, is_credit, AMOUNT_SAT(0)); } @@ -183,7 +195,8 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, { return new_chain_coin_mvt(ctx, NULL, txid, out, NULL, blockheight, - CHANNEL_CLOSE, amount, false, + new_tag_arr(ctx, CHANNEL_CLOSE), + amount, false, output_val); } @@ -192,12 +205,20 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, const struct bitcoin_outpoint *out, u32 blockheight, const struct amount_msat amount, - const struct amount_sat output_val) + const struct amount_sat output_val, + bool is_opener) { struct chain_coin_mvt *mvt; + mvt = new_chain_coin_mvt(ctx, NULL, NULL, out, NULL, blockheight, - CHANNEL_OPEN, amount, true, output_val); + new_tag_arr(ctx, CHANNEL_OPEN), amount, + true, output_val); mvt->account_name = type_to_string(mvt, struct channel_id, chan_id); + + /* If we're the opener, add to the tag list */ + if (is_opener) + tal_arr_expand(&mvt->tags, OPENER); + return mvt; } @@ -209,7 +230,8 @@ struct chain_coin_mvt *new_onchain_htlc_deposit(const tal_t *ctx, { return new_chain_coin_mvt_sat(ctx, NULL, NULL, outpoint, payment_hash, - blockheight, HTLC_FULFILL, + blockheight, + new_tag_arr(ctx, HTLC_FULFILL), amount, true); } @@ -224,7 +246,8 @@ struct chain_coin_mvt *new_onchain_htlc_withdraw(const tal_t *ctx, * that output into their (external) account */ return new_chain_coin_mvt_sat(ctx, EXTERNAL, NULL, outpoint, payment_hash, - blockheight, HTLC_FULFILL, + blockheight, + new_tag_arr(ctx, HTLC_FULFILL), amount, false); } @@ -237,7 +260,8 @@ struct chain_coin_mvt *new_coin_external_spend(const tal_t *ctx, { return new_chain_coin_mvt(ctx, EXTERNAL, txid, outpoint, NULL, blockheight, - tag, AMOUNT_MSAT(0), true, amount); + new_tag_arr(ctx, tag), + AMOUNT_MSAT(0), true, amount); } struct chain_coin_mvt *new_coin_external_deposit(const tal_t *ctx, @@ -248,7 +272,8 @@ struct chain_coin_mvt *new_coin_external_deposit(const tal_t *ctx, { return new_chain_coin_mvt(ctx, EXTERNAL, NULL, outpoint, NULL, - blockheight, tag, + blockheight, + new_tag_arr(ctx, tag), AMOUNT_MSAT(0), true, amount); } @@ -260,7 +285,7 @@ struct chain_coin_mvt *new_coin_wallet_deposit(const tal_t *ctx, { return new_chain_coin_mvt_sat(ctx, WALLET, NULL, outpoint, NULL, - blockheight, tag, + blockheight, new_tag_arr(ctx, tag), amount, true); } @@ -273,7 +298,7 @@ struct chain_coin_mvt *new_coin_wallet_withdraw(const tal_t *ctx, { return new_chain_coin_mvt_sat(ctx, WALLET, spend_txid, outpoint, NULL, - blockheight, tag, + blockheight, new_tag_arr(ctx, tag), amount, false); } @@ -286,7 +311,8 @@ struct chain_coin_mvt *new_coin_penalty_sat(const tal_t *ctx, { return new_chain_coin_mvt_sat(ctx, account_name, txid, outpoint, NULL, - blockheight, PENALTY, + blockheight, + new_tag_arr(ctx, PENALTY), amount, false); } @@ -299,7 +325,8 @@ struct channel_coin_mvt *new_coin_pushed(const tal_t *ctx, memset(&empty_hash, 0, sizeof(empty_hash)); return new_channel_coin_mvt(ctx, cid, empty_hash, - NULL, amount, PUSHED, false); + NULL, amount, + new_tag_arr(ctx, PUSHED), false); } struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, @@ -318,7 +345,7 @@ struct coin_mvt *finalize_chain_mvt(const tal_t *ctx, mvt->id.tx_txid = chain_mvt->tx_txid; mvt->id.outpoint = chain_mvt->outpoint; mvt->id.payment_hash = chain_mvt->payment_hash; - mvt->tag = chain_mvt->tag; + mvt->tags = tal_steal(mvt, chain_mvt->tags); mvt->credit = chain_mvt->credit; mvt->debit = chain_mvt->debit; @@ -348,7 +375,7 @@ struct coin_mvt *finalize_channel_mvt(const tal_t *ctx, mvt->id.part_id = chan_mvt->part_id; mvt->id.tx_txid = NULL; mvt->id.outpoint = NULL; - mvt->tag = chan_mvt->tag; + mvt->tags = tal_steal(mvt, chan_mvt->tags); mvt->credit = chan_mvt->credit; mvt->debit = chan_mvt->debit; mvt->output_val = NULL; @@ -383,7 +410,11 @@ void towire_chain_coin_mvt(u8 **pptr, const struct chain_coin_mvt *mvt) } else towire_bool(pptr, false); towire_u32(pptr, mvt->blockheight); - towire_u8(pptr, mvt->tag); + + towire_u32(pptr, tal_count(mvt->tags)); + for (size_t i = 0; i < tal_count(mvt->tags); i++) + towire_u8(pptr, mvt->tags[i]); + towire_amount_msat(pptr, mvt->credit); towire_amount_msat(pptr, mvt->debit); towire_amount_sat(pptr, mvt->output_val); @@ -415,7 +446,12 @@ void fromwire_chain_coin_mvt(const u8 **cursor, size_t *max, struct chain_coin_m } else mvt->payment_hash = NULL; mvt->blockheight = fromwire_u32(cursor, max); - mvt->tag = fromwire_u8(cursor, max); + + u32 tags_len = fromwire_u32(cursor, max); + mvt->tags = tal_arr(mvt, enum mvt_tag, tags_len); + for (size_t i = 0; i < tags_len; i++) + mvt->tags[i] = fromwire_u8(cursor, max); + mvt->credit = fromwire_amount_msat(cursor, max); mvt->debit = fromwire_amount_msat(cursor, max); mvt->output_val = fromwire_amount_sat(cursor, max); diff --git a/common/coin_mvt.h b/common/coin_mvt.h index e76a6679b..e0f85df3a 100644 --- a/common/coin_mvt.h +++ b/common/coin_mvt.h @@ -4,11 +4,10 @@ #include #include +#include #define COIN_MVT_VERSION 2 -#define COIN_MVT_ACCT_WALLET "wallet" - enum mvt_type { CHAIN_MVT = 0, CHANNEL_MVT = 1, @@ -38,6 +37,7 @@ enum mvt_tag { PENALIZED = 20, STOLEN = 21, TO_MINER = 22, + OPENER = 23, }; struct channel_coin_mvt { @@ -51,8 +51,8 @@ struct channel_coin_mvt { * so we should also record a 'part-id' for them */ u64 *part_id; - /* label / tag */ - enum mvt_tag tag; + /* label / tag array */ + enum mvt_tag *tags; /* only one or the other */ struct amount_msat credit; @@ -69,8 +69,8 @@ struct chain_coin_mvt { /* some on-chain movements have a payment hash */ struct sha256 *payment_hash; - /* label / tag */ - enum mvt_tag tag; + /* label / tag array */ + enum mvt_tag *tags; /* block this transaction is confirmed in * zero means it's unknown/unconfirmed */ @@ -103,8 +103,8 @@ struct coin_mvt { /* identifier */ struct mvt_id id; - /* label / tag */ - enum mvt_tag tag; + /* label / tag array */ + enum mvt_tag *tags; /* only one or the other */ struct amount_msat credit; @@ -125,12 +125,14 @@ struct coin_mvt { struct node_id *node_id; }; +enum mvt_tag *new_tag_arr(const tal_t *ctx, enum mvt_tag tag); + struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx, const struct channel_id *cid, struct sha256 payment_hash, u64 *part_id, struct amount_msat amount, - enum mvt_tag tag, + enum mvt_tag *tags STEALS, bool is_credit); struct chain_coin_mvt *new_onchaind_withdraw(const tal_t *ctx, @@ -159,12 +161,14 @@ struct chain_coin_mvt *new_coin_channel_close(const tal_t *ctx, u32 blockheight, const struct amount_msat amount, const struct amount_sat output_val); + struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx, const struct channel_id *chan_id, const struct bitcoin_outpoint *out, u32 blockheight, const struct amount_msat amount, - const struct amount_sat output_val); + const struct amount_sat output_val, + bool is_opener); struct chain_coin_mvt *new_onchain_htlc_deposit(const tal_t *ctx, const struct bitcoin_outpoint *outpoint, diff --git a/doc/PLUGINS.md b/doc/PLUGINS.md index 07fe74007..79dfc358f 100644 --- a/doc/PLUGINS.md +++ b/doc/PLUGINS.md @@ -708,7 +708,7 @@ i.e. only definitively resolved HTLCs or confirmed bitcoin transactions. "part_id": 0, // (`channel_mvt` type only, mandatory) "credit":"2000000000msat", "debit":"0msat", - "tag":"deposit", + "tags": ["deposit"], "blockheight":102, // (May be null) "timestamp":1585948198, "coin_type":"bc" diff --git a/lightningd/channel_control.c b/lightningd/channel_control.c index 7262889b4..d44dd87e9 100644 --- a/lightningd/channel_control.c +++ b/lightningd/channel_control.c @@ -155,7 +155,8 @@ void channel_record_open(struct channel *channel) &channel->funding, blockheight, start_balance, - channel->funding_sats); + channel->funding_sats, + channel->opener == LOCAL); notify_chain_mvt(channel->peer->ld, mvt); diff --git a/lightningd/coin_mvts.c b/lightningd/coin_mvts.c index d83550327..968a014db 100644 --- a/lightningd/coin_mvts.c +++ b/lightningd/coin_mvts.c @@ -32,7 +32,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hin(const tal_t *ctx, { return new_channel_coin_mvt(ctx, &channel->cid, hin->payment_hash, NULL, - hin->msat, INVOICE, + hin->msat, new_tag_arr(ctx, INVOICE), true); } @@ -42,7 +42,7 @@ struct channel_coin_mvt *new_channel_mvt_routed_hin(const tal_t *ctx, { return new_channel_coin_mvt(ctx, &channel->cid, hin->payment_hash, NULL, - hin->msat, ROUTED, + hin->msat, new_tag_arr(ctx, ROUTED), true); } @@ -52,7 +52,7 @@ struct channel_coin_mvt *new_channel_mvt_invoice_hout(const tal_t *ctx, { return new_channel_coin_mvt(ctx, &channel->cid, hout->payment_hash, &hout->partid, - hout->msat, INVOICE, + hout->msat, new_tag_arr(ctx, INVOICE), false); } @@ -62,6 +62,6 @@ struct channel_coin_mvt *new_channel_mvt_routed_hout(const tal_t *ctx, { return new_channel_coin_mvt(ctx, &channel->cid, hout->payment_hash, NULL, - hout->msat, ROUTED, + hout->msat, new_tag_arr(ctx, ROUTED), false); } diff --git a/lightningd/notification.c b/lightningd/notification.c index 3ca5deec2..c5033eaf2 100644 --- a/lightningd/notification.c +++ b/lightningd/notification.c @@ -474,7 +474,11 @@ static void coin_movement_notification_serialize(struct json_stream *stream, if (mvt->output_val) json_add_amount_sat_only(stream, "output_value", *mvt->output_val); - json_add_string(stream, "tag", mvt_tag_str(mvt->tag)); + + json_array_start(stream, "tags"); + for (size_t i = 0; i < tal_count(mvt->tags); i++) + json_add_string(stream, NULL, mvt_tag_str(mvt->tags[i])); + json_array_end(stream); /* Only chain movements have blockheights. A blockheight * of 'zero' means we haven't seen this tx confirmed yet. */ diff --git a/lightningd/onchain_control.c b/lightningd/onchain_control.c index bd17246fb..6942162f7 100644 --- a/lightningd/onchain_control.c +++ b/lightningd/onchain_control.c @@ -428,6 +428,7 @@ static void handle_irrevocably_resolved(struct channel *channel, const u8 *msg U delete_channel(channel); } + /** * onchain_add_utxo -- onchaind is telling us about an UTXO we own */ @@ -466,6 +467,7 @@ static void onchain_add_utxo(struct channel *channel, const u8 *msg) mvt = new_coin_wallet_deposit(msg, &outpoint, blockheight, amount, CHANNEL_CLOSE); + notify_chain_mvt(channel->peer->ld, mvt); } diff --git a/tests/test_closing.py b/tests/test_closing.py index b1d871d5e..c5f420e9e 100644 --- a/tests/test_closing.py +++ b/tests/test_closing.py @@ -105,14 +105,14 @@ def test_closing_simple(node_factory, bitcoind, chainparams): assert account_balance(l2, channel_id) == 0 expected_1 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], - 'A': [('wallet', 'deposit', None, None), ('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'deposit', None, None)], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('wallet', ['deposit'], None, None)], } expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'deposit', None, None)], + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('wallet', ['deposit'], None, None)], } tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) @@ -628,24 +628,24 @@ def test_penalty_inhtlc(node_factory, bitcoind, executor, chainparams): # l1 loses all of their channel balance to the peer, as penalties expected_1 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], - 'A': [('wallet', 'deposit', None, None), ('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'penalty', None, None), ('external', 'penalty', None, None)], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('external', ['penalty'], None, None), ('external', ['penalty'], None, None)], } # l2 sweeps all of l1's closing outputs expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('cid1', 'penalty', 'to_wallet', 'C'), ('cid1', 'penalty', 'to_wallet', 'D')], - 'C': [('wallet', 'deposit', None, None)], - 'D': [('wallet', 'deposit', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('cid1', ['penalty'], ['to_wallet'], 'C'), ('cid1', ['penalty'], ['to_wallet'], 'D')], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('wallet', ['deposit'], None, None)] } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) # We use a subset of tags in expected_2 that are used in expected_1 tags = check_utxos_channel(l1, [channel_id], expected_1) @@ -755,24 +755,24 @@ def test_penalty_outhtlc(node_factory, bitcoind, executor, chainparams): # l1 loses all of their channel balance to the peer, as penalties expected_1 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], - 'A': [('wallet', 'deposit', None, None), ('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'penalty', None, None), ('external', 'penalty', None, None), ('external', 'penalty', None, None)], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('external', ['penalty'], None, None), ('external', ['penalty'], None, None), ('external', ['penalty'], None, None)], } # l2 sweeps all of l1's closing outputs expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'channel_close', None, None), ('cid1', 'penalty', 'to_wallet', 'C'), ('cid1', 'penalty', 'to_wallet', 'D')], - 'C': [('wallet', 'deposit', None, None)], - 'D': [('wallet', 'deposit', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('wallet', ['channel_close'], None, None), ('cid1', ['penalty'], ['to_wallet'], 'C'), ('cid1', ['penalty'], ['to_wallet'], 'D')], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('wallet', ['deposit'], None, None)] } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) # We use a subset of tags in expected_2 that are used in expected_1 tags = check_utxos_channel(l1, [channel_id], expected_1) @@ -1283,24 +1283,24 @@ def test_penalty_htlc_tx_fulfill(node_factory, bitcoind, chainparams): assert account_balance(l2, channel_id) == 0 expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('cid1', 'htlc_fulfill', 'htlc_fulfill', 'C'), ('external', 'penalized', None, None)], - 'C': [('external', 'penalized', None, None)], + 'A': [('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('cid1', ['htlc_fulfill'], ['htlc_fulfill'], 'C'), ('external', ['penalized'], None, None)], + 'C': [('external', ['penalized'], None, None)], } expected_3 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'channel_close', None, None), ('external', 'htlc_fulfill', 'htlc_fulfill', 'C'), ('cid1', 'penalty', 'to_wallet', 'E')], - 'C': [('cid1', 'penalty', 'to_wallet', 'D')], - 'D': [('wallet', 'deposit', None, None)], - 'E': [('wallet', 'deposit', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('wallet', ['channel_close'], None, None), ('external', ['htlc_fulfill'], ['htlc_fulfill'], 'C'), ('cid1', ['penalty'], ['to_wallet'], 'E')], + 'C': [('cid1', ['penalty'], ['to_wallet'], 'D')], + 'D': [('wallet', ['deposit'], None, None)], + 'E': [('wallet', ['deposit'], None, None)] } if anchor_expected(): - expected_2['B'].append(('external', 'anchor', None, None)) - expected_3['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) - expected_3['B'].append(('wallet', 'anchor', None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_3['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) + expected_3['B'].append(('wallet', ['anchor'], None, None)) tags = check_utxos_channel(l2, [channel_id], expected_2, filter_channel=channel_id) check_utxos_channel(l3, [channel_id], expected_3, tags, filter_channel=channel_id) @@ -1489,27 +1489,27 @@ def test_penalty_htlc_tx_timeout(node_factory, bitcoind, chainparams): assert account_balance(l2, channel_id) == 0 expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('cid1', 'htlc_fulfill', 'htlc_fulfill', 'E'), ('cid1', 'delayed_to_us', 'to_wallet', 'F'), ('cid1', 'htlc_timeout', 'htlc_timeout', 'C')], - 'C': [('external', 'penalized', None, None)], - 'E': [('cid1', 'htlc_tx', 'to_wallet', 'G')], - 'F': [('wallet', 'deposit', None, None)], - 'G': [('wallet', 'deposit', None, None)] + 'A': [('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('cid1', ['htlc_fulfill'], ['htlc_fulfill'], 'E'), ('cid1', ['delayed_to_us'], ['to_wallet'], 'F'), ('cid1', ['htlc_timeout'], ['htlc_timeout'], 'C')], + 'C': [('external', ['penalized'], None, None)], + 'E': [('cid1', ['htlc_tx'], ['to_wallet'], 'G')], + 'F': [('wallet', ['deposit'], None, None)], + 'G': [('wallet', ['deposit'], None, None)] } expected_3 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'channel_close', None, None), ('external', 'htlc_fulfill', 'htlc_fulfill', 'E'), ('external', 'stolen', None, None), ('external', 'htlc_timeout', 'htlc_timeout', 'C')], - 'C': [('cid1', 'penalty', 'to_wallet', 'D')], - 'D': [('wallet', 'deposit', None, None)], - 'E': [('external', 'stolen', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('wallet', ['channel_close'], None, None), ('external', ['htlc_fulfill'], ['htlc_fulfill'], 'E'), ('external', ['stolen'], None, None), ('external', ['htlc_timeout'], ['htlc_timeout'], 'C')], + 'C': [('cid1', ['penalty'], ['to_wallet'], 'D')], + 'D': [('wallet', ['deposit'], None, None)], + 'E': [('external', ['stolen'], None, None)] } if anchor_expected(): - expected_2['B'].append(('external', 'anchor', None, None)) - expected_3['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) - expected_3['B'].append(('wallet', 'anchor', None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_3['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) + expected_3['B'].append(('wallet', ['anchor'], None, None)) tags = check_utxos_channel(l2, [channel_id], expected_2, filter_channel=channel_id) check_utxos_channel(l3, [channel_id], expected_3, tags, filter_channel=channel_id) @@ -1626,15 +1626,15 @@ def test_penalty_rbf_normal(node_factory, bitcoind, executor, chainparams): assert account_balance(l2, channel_id) == 0 expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('cid1', 'penalty', 'to_wallet', 'C'), ('cid1', 'penalty', 'to_wallet', 'D')], - 'C': [('wallet', 'deposit', None, None)], - 'D': [('wallet', 'deposit', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('cid1', ['penalty'], ['to_wallet'], 'C'), ('cid1', ['penalty'], ['to_wallet'], 'D')], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('wallet', ['deposit'], None, None)] } if anchor_expected(): - expected_2['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) check_utxos_channel(l2, [channel_id], expected_2) @@ -1749,13 +1749,13 @@ def test_penalty_rbf_burn(node_factory, bitcoind, executor, chainparams): assert account_balance(l2, channel_id) == 0 expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('cid1', 'penalty', 'to_miner', 'C'), ('cid1', 'penalty', 'to_miner', 'D')], + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('cid1', ['penalty'], ['to_miner'], 'C'), ('cid1', ['penalty'], ['to_miner'], 'D')], } if anchor_expected(): - expected_2['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) check_utxos_channel(l2, [channel_id], expected_2) @@ -2067,24 +2067,24 @@ def test_onchain_timeout(node_factory, bitcoind, executor): # Graph of coin_move events we expect expected_1 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], - 'A': [('wallet', 'deposit', None, None), ('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('cid1', 'delayed_to_us', 'to_wallet', 'C'), ('cid1', 'htlc_timeout', 'htlc_timeout', 'D')], - 'C': [('wallet', 'deposit', None, None)], - 'D': [('cid1', 'htlc_tx', 'to_wallet', 'E')], - 'E': [('wallet', 'deposit', None, None)] + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('cid1', ['delayed_to_us'], ['to_wallet'], 'C'), ('cid1', ['htlc_timeout'], ['htlc_timeout'], 'D')], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('cid1', ['htlc_tx'], ['to_wallet'], 'E')], + 'E': [('wallet', ['deposit'], None, None)] } expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('external', 'htlc_timeout', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('external', ['htlc_timeout'], None, None)] } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) # We use a subset of tags in expected_2 that are used in expected_1 tags = check_utxos_channel(l1, [channel_id], expected_1) @@ -2182,28 +2182,28 @@ def test_onchain_middleman_simple(node_factory, bitcoind): # Graph of coin_move events we expect expected_2 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], # This is ugly, but this wallet deposit is either unspent or used # in the next channel open - 'A': [('wallet', 'deposit', [('withdrawal', 'F'), (None, None)]), ('cid1', 'channel_open', 'channel_close', 'B')], - '1': [('wallet', 'deposit', 'withdrawal', 'F')], - 'B': [('cid1', 'delayed_to_us', 'to_wallet', 'C'), ('cid1', 'htlc_fulfill', 'htlc_fulfill', 'D'), ('external', 'to_them', None, None)], - 'C': [('wallet', 'deposit', None, None)], - 'D': [('cid1', 'htlc_tx', 'to_wallet', 'E')], - 'E': [('wallet', 'deposit', None, None)], - 'F': [('wallet', 'deposit', None, None), ('cid2', 'channel_open', None, None)] + 'A': [('wallet', ['deposit'], ((['withdrawal'], 'F'), (None, None))), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + '1': [('wallet', ['deposit'], ['withdrawal'], 'F')], + 'B': [('cid1', ['delayed_to_us'], ['to_wallet'], 'C'), ('cid1', ['htlc_fulfill'], ['htlc_fulfill'], 'D'), ('external', ['to_them'], None, None)], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('cid1', ['htlc_tx'], ['to_wallet'], 'E')], + 'E': [('wallet', ['deposit'], None, None)], + 'F': [('wallet', ['deposit'], None, None), ('cid2', ['channel_open', 'opener'], None, None)] } expected_1 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('external', 'htlc_fulfill', 'htlc_fulfill', 'D'), ('wallet', 'channel_close', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('external', ['htlc_fulfill'], ['htlc_fulfill'], 'D'), ('wallet', ['channel_close'], None, None)] } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) chan2_id = first_channel_id(l2, l3) tags = check_utxos_channel(l2, [channel_id, chan2_id], expected_2) @@ -2303,27 +2303,27 @@ def test_onchain_middleman_their_unilateral_in(node_factory, bitcoind): # Graph of coin_move events we expect expected_2 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], # This is ugly, but this wallet deposit is either unspent or used # in the next channel open - 'A': [('wallet', 'deposit', [('withdrawal', 'D'), (None, None)]), ('cid1', 'channel_open', 'channel_close', 'B')], - '1': [('wallet', 'deposit', 'withdrawal', 'D')], - 'B': [('external', 'to_them', None, None), ('wallet', 'channel_close', None, None), ('cid1', 'htlc_fulfill', 'to_wallet', 'C')], - 'C': [('wallet', 'deposit', None, None)], - 'D': [('wallet', 'deposit', None, None), ('cid2', 'channel_open', None, None)] + 'A': [('wallet', ['deposit'], ((['withdrawal'], 'D'), (None, None))), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + '1': [('wallet', ['deposit'], ['withdrawal'], 'D')], + 'B': [('external', ['to_them'], None, None), ('wallet', ['channel_close'], None, None), ('cid1', ['htlc_fulfill'], ['to_wallet'], 'C')], + 'C': [('wallet', ['deposit'], None, None)], + 'D': [('wallet', ['deposit'], None, None), ('cid2', ['channel_open', 'opener'], None, None)] } expected_1 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('external', 'htlc_fulfill', 'htlc_fulfill', 'C'), ('cid1', 'delayed_to_us', 'to_wallet', 'E')], - 'E': [('wallet', 'deposit', None, None)] + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('external', ['htlc_fulfill'], ['htlc_fulfill'], 'C'), ('cid1', ['delayed_to_us'], ['to_wallet'], 'E')], + 'E': [('wallet', ['deposit'], None, None)] } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) chan2_id = first_channel_id(l2, l3) tags = check_utxos_channel(l2, [channel_id, chan2_id], expected_2) @@ -2396,24 +2396,24 @@ def test_onchain_their_unilateral_out(node_factory, bitcoind): # Graph of coin_move events we expect expected_1 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], # This is ugly, but this wallet deposit is either unspent or used # in the next channel open - 'A': [('wallet', 'deposit', None, None), ('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'channel_close', None, None), ('cid1', 'htlc_timeout', 'to_wallet', 'C')], - 'C': [('wallet', 'deposit', None, None)], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('wallet', ['channel_close'], None, None), ('cid1', ['htlc_timeout'], ['to_wallet'], 'C')], + 'C': [('wallet', ['deposit'], None, None)], } expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('external', 'htlc_timeout', None, None)], + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('external', ['htlc_timeout'], None, None)], } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) @@ -2600,22 +2600,22 @@ def test_onchain_all_dust(node_factory, bitcoind, executor): # Graph of coin_move events we expect expected_1 = { - '0': [('wallet', 'deposit', 'withdrawal', 'A')], - 'A': [('wallet', 'deposit', None, None), ('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('wallet', 'channel_close', None, None), ('cid1', 'htlc_timeout', 'ignored', 'C')], - 'C': [('wallet', 'deposit', None, None)], + '0': [('wallet', ['deposit'], ['withdrawal'], 'A')], + 'A': [('wallet', ['deposit'], None, None), ('cid1', ['channel_open', 'opener'], ['channel_close'], 'B')], + 'B': [('wallet', ['channel_close'], None, None), ('cid1', ['htlc_timeout'], ['ignored'], 'C')], + 'C': [('wallet', ['deposit'], None, None)], } expected_2 = { - 'A': [('cid1', 'channel_open', 'channel_close', 'B')], - 'B': [('external', 'to_them', None, None), ('external', 'htlc_timeout', None, None)], + 'A': [('cid1', ['channel_open'], ['channel_close'], 'B')], + 'B': [('external', ['to_them'], None, None), ('external', ['htlc_timeout'], None, None)], } if anchor_expected(): - expected_1['B'].append(('external', 'anchor', None, None)) - expected_2['B'].append(('external', 'anchor', None, None)) - expected_1['B'].append(('wallet', 'anchor', None, None)) - expected_2['B'].append(('wallet', 'anchor', None, None)) + expected_1['B'].append(('external', ['anchor'], None, None)) + expected_2['B'].append(('external', ['anchor'], None, None)) + expected_1['B'].append(('wallet', ['anchor'], None, None)) + expected_2['B'].append(('wallet', ['anchor'], None, None)) tags = check_utxos_channel(l1, [channel_id], expected_1) check_utxos_channel(l2, [channel_id], expected_2, tags) diff --git a/tests/test_connection.py b/tests/test_connection.py index dd30de9cc..738154b8f 100644 --- a/tests/test_connection.py +++ b/tests/test_connection.py @@ -1104,8 +1104,8 @@ def test_funding_push(node_factory, bitcoind, chainparams): # give the file write a second time.sleep(1) channel_mvts = [ - {'type': 'chain_mvt', 'credit': 16777215000, 'debit': 0, 'tag': 'channel_open'}, - {'type': 'channel_mvt', 'credit': 0, 'debit': 20000000, 'tag': 'pushed'}, + {'type': 'chain_mvt', 'credit': 16777215000, 'debit': 0, 'tags': ['channel_open', 'opener']}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 20000000, 'tags': ['pushed']}, ] check_coin_moves(l1, chanid, channel_mvts, chainparams) assert account_balance(l1, chanid) == (amount - push_sat) * 1000 diff --git a/tests/test_plugin.py b/tests/test_plugin.py index b4cbf7508..7de9d31b6 100644 --- a/tests/test_plugin.py +++ b/tests/test_plugin.py @@ -1887,19 +1887,19 @@ def test_coin_movement_notices(node_factory, bitcoind, chainparams): """Verify that channel coin movements are triggered correctly. """ l1_l2_mvts = [ - {'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tag': 'channel_open'}, - {'type': 'channel_mvt', 'credit': 100001001, 'debit': 0, 'tag': 'routed'}, - {'type': 'channel_mvt', 'credit': 0, 'debit': 50000000, 'tag': 'routed'}, - {'type': 'channel_mvt', 'credit': 100000000, 'debit': 0, 'tag': 'invoice'}, - {'type': 'channel_mvt', 'credit': 0, 'debit': 50000000, 'tag': 'invoice'}, - {'type': 'chain_mvt', 'credit': 0, 'debit': 100001001, 'tag': 'channel_close'}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 0, 'tags': ['channel_open']}, + {'type': 'channel_mvt', 'credit': 100001001, 'debit': 0, 'tags': ['routed']}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 50000000, 'tags': ['routed']}, + {'type': 'channel_mvt', 'credit': 100000000, 'debit': 0, 'tags': ['invoice']}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 50000000, 'tags': ['invoice']}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 100001001, 'tags': ['channel_close']}, ] l2_l3_mvts = [ - {'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tag': 'channel_open'}, - {'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tag': 'routed'}, - {'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tag': 'routed'}, - {'type': 'chain_mvt', 'credit': 0, 'debit': 950000501, 'tag': 'channel_close'}, + {'type': 'chain_mvt', 'credit': 1000000000, 'debit': 0, 'tags': ['channel_open', 'opener']}, + {'type': 'channel_mvt', 'credit': 0, 'debit': 100000000, 'tags': ['routed']}, + {'type': 'channel_mvt', 'credit': 50000501, 'debit': 0, 'tags': ['routed']}, + {'type': 'chain_mvt', 'credit': 0, 'debit': 950000501, 'tags': ['channel_close']}, ] l1, l2, l3 = node_factory.line_graph(3, opts=[ diff --git a/tests/utils.py b/tests/utils.py index 4c5c83464..def472b0e 100644 --- a/tests/utils.py +++ b/tests/utils.py @@ -77,7 +77,7 @@ def move_matches(exp, mv): return False if mv['debit'] != "{}msat".format(exp['debit']): return False - if mv['tag'] != exp['tag']: + if mv['tags'] != exp['tags']: return False return True @@ -94,11 +94,11 @@ def check_coin_moves(n, account_id, expected_moves, chainparams): node_id = n.info['id'] acct_moves = [m for m in moves if m['account_id'] == account_id] for mv in acct_moves: - print("{{'type': '{}', 'credit': {}, 'debit': {}, 'tag': '{}'}}," + print("{{'type': '{}', 'credit': {}, 'debit': {}, 'tags': '{}'}}," .format(mv['type'], Millisatoshi(mv['credit']).millisatoshis, Millisatoshi(mv['debit']).millisatoshis, - mv['tag'])) + mv['tags'])) assert mv['version'] == 2 assert mv['node_id'] == node_id assert mv['timestamp'] > 0 @@ -167,9 +167,9 @@ def print_utxos(utxos): print(k) for u in us: if u[1]: - print('\t', u[0]['account_id'], u[0]['tag'], u[1]['tag'], u[1]['txid']) + print('\t', u[0]['account_id'], u[0]['tags'], u[1]['tags'], u[1]['txid']) else: - print('\t', u[0]['account_id'], u[0]['tag'], None, None) + print('\t', u[0]['account_id'], u[0]['tags'], None, None) def utxos_for_channel(utxoset, channel_id): @@ -218,7 +218,7 @@ def matchup_events(u_set, evs, chans, tag_list): else: acct = ev[0] - if u[0]['account_id'] != acct or u[0]['tag'] != ev[1]: + if u[0]['account_id'] != acct or u[0]['tags'] != ev[1]: continue if ev[2] is None: @@ -228,21 +228,21 @@ def matchup_events(u_set, evs, chans, tag_list): break # ugly hack to annotate two possible futures for a utxo - if type(ev[2]) is list: - tag = u[1]['tag'] if u[1] else u[1] + if type(ev[2]) is tuple: + tag = u[1]['tags'] if u[1] else u[1] assert tag in [x[0] for x in ev[2]] if not u[1]: found = True u_set.remove(u) break for x in ev[2]: - if x[0] == u[1]['tag'] and u[1]['tag'] != 'to_miner': + if x[0] == u[1]['tags'] and 'to_miner' not in u[1]['tags']: # Save the 'spent to' txid in the tag-list tag_list[x[1]] = u[1]['txid'] else: - assert ev[2] == u[1]['tag'] + assert ev[2] == u[1]['tags'] # Save the 'spent to' txid in the tag-list - if u[1]['tag'] != 'to_miner': + if 'to_miner' not in u[1]['tags']: tag_list[ev[3]] = u[1]['txid'] found = True