diff --git a/plugins/bkpr/account.c b/plugins/bkpr/account.c index b734078ea..61739462c 100644 --- a/plugins/bkpr/account.c +++ b/plugins/bkpr/account.c @@ -19,6 +19,7 @@ struct account *new_account(const tal_t *ctx, a->onchain_resolved_block = 0; a->open_event_db_id = NULL; a->closed_event_db_id = NULL; + a->closed_count = 0; return a; } diff --git a/plugins/bkpr/account.h b/plugins/bkpr/account.h index 5f83090c8..afce6e5f1 100644 --- a/plugins/bkpr/account.h +++ b/plugins/bkpr/account.h @@ -34,6 +34,9 @@ struct account { /* db_id of chain event that closed this account */ u64 *closed_event_db_id; + + /* Number of outputs to expect on close */ + u32 closed_count; }; /* Get a new account */ diff --git a/plugins/bkpr/bookkeeper.c b/plugins/bkpr/bookkeeper.c index 1e5fa6962..6d74c2b7a 100644 --- a/plugins/bkpr/bookkeeper.c +++ b/plugins/bkpr/bookkeeper.c @@ -493,7 +493,7 @@ static bool new_missed_channel_account(struct command *cmd, chain_ev->credit = amt; db_begin_transaction(db); log_chain_event(db, acct, chain_ev); - maybe_update_account(db, acct, chain_ev, tags); + maybe_update_account(db, acct, chain_ev, tags, 0); maybe_update_onchain_fees(cmd, db, &opt.txid); /* We won't count the close's fees if we're @@ -958,6 +958,7 @@ parse_and_log_chain_move(struct command *cmd, struct sha256 *payment_hash = tal(cmd, struct sha256); struct bitcoin_txid *spending_txid = tal(cmd, struct bitcoin_txid); struct account *acct; + u32 closed_count; const char *err; /* Fields we expect on *every* chain movement */ @@ -1011,8 +1012,20 @@ parse_and_log_chain_move(struct command *cmd, "{originating_account:%}}", JSON_SCAN_TAL(e, json_strdup, &e->origin_acct)); - if (err) + if (err) { e->origin_acct = NULL; + err = tal_free(err); + } + + err = json_scan(tmpctx, buf, params, + "{coin_movement:" + "{output_count:%}}", + JSON_SCAN(json_to_number, &closed_count)); + + if (err) { + closed_count = 0; + err = tal_free(err); + } e->payment_id = tal_steal(e, payment_hash); @@ -1039,7 +1052,7 @@ parse_and_log_chain_move(struct command *cmd, /* This event *might* have implications for account; * update as necessary */ - maybe_update_account(db, acct, e, tags); + maybe_update_account(db, acct, e, tags, closed_count); /* Can we calculate any onchain fees now? */ err = maybe_update_onchain_fees(cmd, db, diff --git a/plugins/bkpr/db.c b/plugins/bkpr/db.c index 8edda43c8..7a7f2aca2 100644 --- a/plugins/bkpr/db.c +++ b/plugins/bkpr/db.c @@ -93,6 +93,7 @@ static struct migration db_migrations[] = { ");"), NULL}, {SQL("ALTER TABLE chain_events ADD origin TEXT;"), NULL}, + {SQL("ALTER TABLE accounts ADD closed_count INTEGER DEFAULT 0;"), NULL}, }; static bool db_migrate(struct plugin *p, struct db *db) diff --git a/plugins/bkpr/recorder.c b/plugins/bkpr/recorder.c index dab6d477a..2c5172184 100644 --- a/plugins/bkpr/recorder.c +++ b/plugins/bkpr/recorder.c @@ -836,6 +836,8 @@ static struct account *stmt2account(const tal_t *ctx, struct db_stmt *stmt) } else a->closed_event_db_id = NULL; + a->closed_count = db_col_int(stmt, "closed_count"); + return a; } @@ -856,6 +858,7 @@ struct account *find_account(const tal_t *ctx, ", is_wallet" ", we_opened" ", leased" + ", closed_count" " FROM accounts" " WHERE name = ?")); @@ -921,6 +924,7 @@ struct account **list_accounts(const tal_t *ctx, struct db *db) ", is_wallet" ", we_opened" ", leased" + ", closed_count" " FROM accounts;")); db_query_prepared(stmt); @@ -966,7 +970,8 @@ void account_add(struct db *db, struct account *acct) void maybe_update_account(struct db *db, struct account *acct, struct chain_event *e, - const enum mvt_tag *tags) + const enum mvt_tag *tags, + u32 closed_count) { struct db_stmt *stmt; bool updated = false; @@ -1014,6 +1019,11 @@ void maybe_update_account(struct db *db, } } + if (closed_count > 0) { + updated = true; + acct->closed_count = closed_count; + } + /* Nothing new here */ if (!updated) return; @@ -1024,6 +1034,7 @@ void maybe_update_account(struct db *db, ", closed_event_id = ?" ", we_opened = ?" ", leased = ?" + ", closed_count = ?" " WHERE" " name = ?")); @@ -1039,8 +1050,9 @@ void maybe_update_account(struct db *db, db_bind_int(stmt, 2, acct->we_opened ? 1 : 0); db_bind_int(stmt, 3, acct->leased ? 1 : 0); + db_bind_int(stmt, 4, acct->closed_count); - db_bind_text(stmt, 4, acct->name); + db_bind_text(stmt, 5, acct->name); db_exec_prepared_v2(take(stmt)); } diff --git a/plugins/bkpr/recorder.h b/plugins/bkpr/recorder.h index 0375ae6d7..4989d5f12 100644 --- a/plugins/bkpr/recorder.h +++ b/plugins/bkpr/recorder.h @@ -110,7 +110,8 @@ struct account *find_account(const tal_t *ctx, void maybe_update_account(struct db *db, struct account *acct, struct chain_event *e, - const enum mvt_tag *tags); + const enum mvt_tag *tags, + u32 closed_count); /* Update our onchain fees now? */ char *maybe_update_onchain_fees(const tal_t *ctx, diff --git a/plugins/bkpr/test/run-recorder.c b/plugins/bkpr/test/run-recorder.c index 8033d0507..1693f089e 100644 --- a/plugins/bkpr/test/run-recorder.c +++ b/plugins/bkpr/test/run-recorder.c @@ -247,6 +247,8 @@ static bool accountseq(struct account *a1, struct account *a2) if (a1->closed_event_db_id) CHECK(*a1->closed_event_db_id == *a2->closed_event_db_id); + CHECK(a1->closed_count == a2->closed_count); + return true; } @@ -1080,7 +1082,8 @@ static bool test_account_crud(const tal_t *ctx, struct plugin *p) /* should not update the account info */ tags[0] = PUSHED; tags[1] = PENALTY; - maybe_update_account(db, acct, ev1, tags); + maybe_update_account(db, acct, ev1, tags, 0); + acct2 = find_account(ctx, db, "wallet"); accountseq(acct, acct2); /* channel_open -> open event db updated */ @@ -1088,17 +1091,18 @@ static bool test_account_crud(const tal_t *ctx, struct plugin *p) CHECK(acct->open_event_db_id == NULL); tags[0] = CHANNEL_OPEN; tags[1] = LEASED; - maybe_update_account(db, acct, ev1, tags); + maybe_update_account(db, acct, ev1, tags, 2); acct2 = find_account(ctx, db, "wallet"); accountseq(acct, acct2); CHECK(acct->leased); CHECK(acct->open_event_db_id != NULL); + CHECK(acct->closed_count == 2); tags[0] = CHANNEL_CLOSE; tags[1] = OPENER; CHECK(acct->closed_event_db_id == NULL); CHECK(!acct->we_opened); - maybe_update_account(db, acct, ev1, tags); + maybe_update_account(db, acct, ev1, tags, 0); acct2 = find_account(ctx, db, "wallet"); accountseq(acct, acct2); CHECK(acct->closed_event_db_id != NULL);