diff --git a/plugins/bkpr/bookkeeper.c b/plugins/bkpr/bookkeeper.c index 93f44e5c2296..e5e2e82f8e87 100644 --- a/plugins/bkpr/bookkeeper.c +++ b/plugins/bkpr/bookkeeper.c @@ -1222,8 +1222,10 @@ parse_and_log_chain_move(struct command *cmd, if (e->origin_acct) find_or_create_account(cmd, bkpr, e->origin_acct); - /* Make this visible for queries (we expect increasing!) */ - assert(e->db_id > bkpr->chainmoves_index); + /* Make this visible for queries (we expect increasing!). If we raced, this is not true. */ + if (e->db_id <= bkpr->chainmoves_index) + return; + bkpr->chainmoves_index = e->db_id; /* This event *might* have implications for account; @@ -1336,8 +1338,9 @@ parse_and_log_channel_move(struct command *cmd, " but no account exists %s", acct_name); - /* Make this visible for queries (we expect increasing!) */ - assert(e->db_id > bkpr->channelmoves_index); + /* Make this visible for queries (we expect increasing!). If we raced, this is not true. */ + if (e->db_id <= bkpr->channelmoves_index) + return; bkpr->channelmoves_index = e->db_id; /* Check for invoice desc data, necessary */ diff --git a/tests/test_bookkeeper.py b/tests/test_bookkeeper.py index 4186d917f990..d22d924d3533 100644 --- a/tests/test_bookkeeper.py +++ b/tests/test_bookkeeper.py @@ -1194,6 +1194,21 @@ def test_listincome_timebox(node_factory, bitcoind): incomes = l1.rpc.bkpr_listincome(end_time=first_one)['income_events'] assert [i for i in incomes if i['timestamp'] > first_one] == [] + +@unittest.skipIf(TEST_NETWORK != 'regtest', "Snapshots are bitcoin regtest.") +@unittest.skipIf(os.getenv('TEST_DB_PROVIDER', 'sqlite3') != 'sqlite3', "uses snapshots") +def test_bkpr_parallel(node_factory, bitcoind, executor): + """Bookkeeper could crash with parallel requests""" + bitcoind.generate_block(1) + l1 = node_factory.get_node(dbfile="l1-before-moves-in-db.sqlite3.xz", + options={'database-upgrade': True}) + + fut1 = executor.submit(l1.rpc.bkpr_listincome) + fut2 = executor.submit(l1.rpc.bkpr_listincome) + + fut1.result() + fut2.result() + # We save blockheights in storage, so make sure we restore them on restart! acctevents_before = l1.rpc.bkpr_listaccountevents() l1.restart()