Skip to content

Commit 83c3f27

Browse files
committed
wallet: generate fixup chainmoves and channelmoves when first starting.
If we don't have an accountdb from bookkeeper: 1. Generate a deposit chain event for every confirmed UTXO. 2. Generate an open chain event for every open, confirmed channel. 3. Generate a push/lease event if necessary. 4. Generate a fixup "journal" entry if balance is different from initial. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
1 parent c8bb117 commit 83c3f27

File tree

10 files changed

+608
-93
lines changed

10 files changed

+608
-93
lines changed

common/coin_mvt.c

Lines changed: 73 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -207,21 +207,22 @@ struct mvt_account_id *new_mvt_account_id(const tal_t *ctx,
207207
return acct;
208208
}
209209

210-
struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
211-
const struct channel *channel,
212-
u64 timestamp,
213-
const struct sha256 *payment_hash TAKES,
214-
const u64 *part_id,
215-
const u64 *group_id,
216-
enum coin_mvt_dir direction,
217-
struct amount_msat amount,
218-
struct mvt_tags tags,
219-
struct amount_msat fees)
210+
struct channel_coin_mvt *new_channel_coin_mvt_general(const tal_t *ctx,
211+
const struct channel *channel,
212+
const struct channel_id *cid,
213+
u64 timestamp,
214+
const struct sha256 *payment_hash TAKES,
215+
const u64 *part_id,
216+
const u64 *group_id,
217+
enum coin_mvt_dir direction,
218+
struct amount_msat amount,
219+
struct mvt_tags tags,
220+
struct amount_msat fees)
220221
{
221222
struct channel_coin_mvt *mvt = tal(ctx, struct channel_coin_mvt);
222223

223224
assert(mvt_tags_valid(tags));
224-
set_mvt_account_id(&mvt->account, channel, NULL);
225+
set_mvt_account_id(&mvt->account, channel, cid ? take(fmt_channel_id(NULL, cid)) : NULL);
225226
mvt->timestamp = timestamp;
226227
mvt->payment_hash = tal_dup_or_null(mvt, struct sha256, payment_hash);
227228
if (!part_id) {
@@ -251,6 +252,21 @@ struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
251252
abort();
252253
}
253254

255+
struct channel_coin_mvt *new_channel_coin_mvt(const tal_t *ctx,
256+
const struct channel *channel,
257+
u64 timestamp,
258+
const struct sha256 *payment_hash TAKES,
259+
const u64 *part_id,
260+
const u64 *group_id,
261+
enum coin_mvt_dir direction,
262+
struct amount_msat amount,
263+
struct mvt_tags tags,
264+
struct amount_msat fees)
265+
{
266+
return new_channel_coin_mvt_general(ctx, channel, NULL, timestamp, payment_hash,
267+
part_id, group_id, direction, amount, tags, fees);
268+
}
269+
254270
static struct chain_coin_mvt *new_chain_coin_mvt(const tal_t *ctx,
255271
const struct channel *channel,
256272
const char *account_name TAKES,
@@ -408,15 +424,17 @@ struct chain_coin_mvt *new_coin_channel_open_proposed(const tal_t *ctx,
408424
return mvt;
409425
}
410426

411-
struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx,
412-
const struct channel *channel,
413-
const struct bitcoin_outpoint *out,
414-
const struct node_id *peer_id,
415-
u32 blockheight,
416-
const struct amount_msat amount,
417-
const struct amount_sat output_val,
418-
bool is_opener,
419-
bool is_leased)
427+
struct chain_coin_mvt *new_coin_channel_open_general(const tal_t *ctx,
428+
const struct channel *channel,
429+
const struct channel_id *cid,
430+
u64 timestamp,
431+
const struct bitcoin_outpoint *out,
432+
const struct node_id *peer_id,
433+
u32 blockheight,
434+
const struct amount_msat amount,
435+
const struct amount_sat output_val,
436+
bool is_opener,
437+
bool is_leased)
420438
{
421439
struct chain_coin_mvt *mvt;
422440
struct mvt_tags tags = tag_to_mvt_tags(MVT_CHANNEL_OPEN);
@@ -428,7 +446,8 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx,
428446
if (is_leased)
429447
mvt_tag_set(&tags, MVT_LEASED);
430448

431-
mvt = new_chain_coin_mvt(ctx, channel, NULL, time_now().ts.tv_sec,
449+
mvt = new_chain_coin_mvt(ctx, channel, cid ? take(fmt_channel_id(NULL, cid)) : NULL,
450+
timestamp,
432451
NULL, out, NULL, blockheight,
433452
tags,
434453
COIN_CREDIT, amount,
@@ -438,6 +457,22 @@ struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx,
438457
return mvt;
439458
}
440459

460+
struct chain_coin_mvt *new_coin_channel_open(const tal_t *ctx,
461+
const struct channel *channel,
462+
const struct bitcoin_outpoint *out,
463+
const struct node_id *peer_id,
464+
u32 blockheight,
465+
const struct amount_msat amount,
466+
const struct amount_sat output_val,
467+
bool is_opener,
468+
bool is_leased)
469+
{
470+
return new_coin_channel_open_general(ctx, channel, NULL,
471+
time_now().ts.tv_sec,
472+
out, peer_id, blockheight,
473+
amount, output_val, is_opener, is_leased);
474+
}
475+
441476
struct chain_coin_mvt *new_onchain_htlc_deposit(const tal_t *ctx,
442477
const struct bitcoin_outpoint *outpoint,
443478
u32 blockheight,
@@ -522,16 +557,29 @@ struct chain_coin_mvt *new_coin_wallet_withdraw(const tal_t *ctx,
522557
COIN_DEBIT, amount);
523558
}
524559

560+
struct channel_coin_mvt *new_coin_channel_push_general(const tal_t *ctx,
561+
const struct channel *channel,
562+
const struct channel_id *cid,
563+
u64 timestamp,
564+
enum coin_mvt_dir direction,
565+
struct amount_msat amount,
566+
struct mvt_tags tags)
567+
{
568+
return new_channel_coin_mvt_general(ctx, channel, cid, timestamp, NULL,
569+
NULL, NULL, direction, amount,
570+
tags,
571+
AMOUNT_MSAT(0));
572+
}
573+
525574
struct channel_coin_mvt *new_coin_channel_push(const tal_t *ctx,
526575
const struct channel *channel,
527576
enum coin_mvt_dir direction,
528577
struct amount_msat amount,
529578
struct mvt_tags tags)
530579
{
531-
return new_channel_coin_mvt(ctx, channel, time_now().ts.tv_sec, NULL,
532-
NULL, NULL, direction, amount,
533-
tags,
534-
AMOUNT_MSAT(0));
580+
return new_coin_channel_push_general(ctx, channel, NULL,
581+
time_now().ts.tv_sec,
582+
direction, amount, tags);
535583
}
536584

537585
struct chain_coin_mvt *new_foreign_deposit(const tal_t *ctx,

common/coin_mvt.h

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,39 @@ struct chain_coin_mvt *new_foreign_withdrawal(const tal_t *ctx,
280280
u64 timestamp)
281281
NON_NULL_ARGS(2, 3, 6);
282282

283+
/* Generic versions (prefer the above ones: these are for migrations) */
284+
struct channel_coin_mvt *new_channel_coin_mvt_general(const tal_t *ctx,
285+
const struct channel *channel,
286+
const struct channel_id *cid,
287+
u64 timestamp,
288+
const struct sha256 *payment_hash TAKES,
289+
const u64 *part_id,
290+
const u64 *group_id,
291+
enum coin_mvt_dir direction,
292+
struct amount_msat amount,
293+
struct mvt_tags tags,
294+
struct amount_msat fees);
295+
296+
struct chain_coin_mvt *new_coin_channel_open_general(const tal_t *ctx,
297+
const struct channel *channel,
298+
const struct channel_id *cid,
299+
u64 timestamp,
300+
const struct bitcoin_outpoint *out,
301+
const struct node_id *peer_id,
302+
u32 blockheight,
303+
const struct amount_msat amount,
304+
const struct amount_sat output_val,
305+
bool is_opener,
306+
bool is_leased);
307+
308+
struct channel_coin_mvt *new_coin_channel_push_general(const tal_t *ctx,
309+
const struct channel *channel,
310+
const struct channel_id *cid,
311+
u64 timestamp,
312+
enum coin_mvt_dir direction,
313+
struct amount_msat amount,
314+
struct mvt_tags tags);
315+
283316
/* There are three standard accounts:
284317
* "wallet" for our internal wallet,
285318
* "external" for other bitcoin sources,

common/test/run-coin_mvt.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ struct amount_asset amount_sat_to_asset(struct amount_sat *sat UNNEEDED, const u
4343
/* Generated stub for amount_tx_fee */
4444
struct amount_sat amount_tx_fee(u32 fee_per_kw UNNEEDED, size_t weight UNNEEDED)
4545
{ fprintf(stderr, "amount_tx_fee called!\n"); abort(); }
46+
/* Generated stub for fmt_channel_id */
47+
char *fmt_channel_id(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED)
48+
{ fprintf(stderr, "fmt_channel_id called!\n"); abort(); }
4649
/* Generated stub for fromwire */
4750
const u8 *fromwire(const u8 **cursor UNNEEDED, size_t *max UNNEEDED, void *copy UNNEEDED, size_t n UNNEEDED)
4851
{ fprintf(stderr, "fromwire called!\n"); abort(); }

common/test/run-route_blinding_test.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@
1717
#include <stdio.h>
1818

1919
/* AUTOGENERATED MOCKS START */
20+
/* Generated stub for fmt_channel_id */
21+
char *fmt_channel_id(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED)
22+
{ fprintf(stderr, "fmt_channel_id called!\n"); abort(); }
2023
/* Generated stub for fromwire_channel_id */
2124
bool fromwire_channel_id(const u8 **cursor UNNEEDED, size_t *max UNNEEDED,
2225
struct channel_id *channel_id UNNEEDED)

plugins/bkpr/test/run-sql.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ u32 find_blockheight(const struct bkpr *bkpr UNNEEDED, const struct bitcoin_txid
3535
/* Generated stub for first_fee_state */
3636
enum htlc_state first_fee_state(enum side opener UNNEEDED)
3737
{ fprintf(stderr, "first_fee_state called!\n"); abort(); }
38+
/* Generated stub for fmt_channel_id */
39+
char *fmt_channel_id(const tal_t *ctx UNNEEDED, const struct channel_id *channel_id UNNEEDED)
40+
{ fprintf(stderr, "fmt_channel_id called!\n"); abort(); }
3841
/* Generated stub for fmt_wireaddr_without_port */
3942
char *fmt_wireaddr_without_port(const tal_t *ctx UNNEEDED, const struct wireaddr *a UNNEEDED)
4043
{ fprintf(stderr, "fmt_wireaddr_without_port called!\n"); abort(); }

tests/test_bookkeeper.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1083,3 +1083,64 @@ def test_migration(node_factory, bitcoind):
10831083
'payment_id': '7ccef7e9fabbf4a841af44b1fc7319bc70ce98697b77ce6dacffa84bebcd4350',
10841084
'tag': 'invoice',
10851085
'type': 'channel'}]
1086+
1087+
1088+
@unittest.skipIf(TEST_NETWORK != 'regtest', "Snapshots are bitcoin regtest.")
1089+
@unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "uses snapshots")
1090+
def test_migration_no_bkpr(node_factory, bitcoind):
1091+
"""These nodes need to invent coinmoves to make the balances work"""
1092+
bitcoind.generate_block(1)
1093+
l1 = node_factory.get_node(dbfile="l1-before-moves-in-db.sqlite3.xz",
1094+
options={'database-upgrade': True})
1095+
l2 = node_factory.get_node(dbfile="l2-before-moves-in-db.sqlite3.xz",
1096+
options={'database-upgrade': True})
1097+
1098+
chan = only_one(l1.rpc.listpeerchannels()['channels'])
1099+
1100+
l1_events = l1.rpc.bkpr_listaccountevents()['events']
1101+
for e in l1_events:
1102+
del e['timestamp']
1103+
1104+
l2_events = l2.rpc.bkpr_listaccountevents()['events']
1105+
for e in l2_events:
1106+
del e['timestamp']
1107+
1108+
assert l1_events == [{'account': chan['channel_id'],
1109+
'blockheight': 103,
1110+
'credit_msat': 1000000000,
1111+
'currency': 'bcrt',
1112+
'debit_msat': 0,
1113+
'outpoint': f"{chan['funding_txid']}:{chan['funding_outnum']}",
1114+
'tag': 'channel_open',
1115+
'type': 'chain'},
1116+
{'account': 'wallet',
1117+
'blockheight': 103,
1118+
'credit_msat': 995073000,
1119+
'currency': 'bcrt',
1120+
'debit_msat': 0,
1121+
'outpoint': f"{chan['funding_txid']}:{chan['funding_outnum'] ^ 1}",
1122+
'tag': 'deposit',
1123+
'type': 'chain'},
1124+
{'account': chan['channel_id'],
1125+
'credit_msat': 0,
1126+
'currency': 'bcrt',
1127+
'debit_msat': 12345678,
1128+
'is_rebalance': False,
1129+
'tag': 'journal',
1130+
'type': 'channel'}]
1131+
1132+
assert l2_events == [{'account': chan['channel_id'],
1133+
'blockheight': 103,
1134+
'credit_msat': 0,
1135+
'currency': 'bcrt',
1136+
'debit_msat': 0,
1137+
'outpoint': f"{chan['funding_txid']}:{chan['funding_outnum']}",
1138+
'tag': 'channel_open',
1139+
'type': 'chain'},
1140+
{'account': chan['channel_id'],
1141+
'credit_msat': 12345678,
1142+
'currency': 'bcrt',
1143+
'debit_msat': 0,
1144+
'is_rebalance': False,
1145+
'tag': 'journal',
1146+
'type': 'channel'}]

0 commit comments

Comments
 (0)