bookkeeper: fix restoration of derived wallet blockheights on restart.
What changed, and why it matters
This commit fixes a bookkeeping bug in Core Lightning's bookkeeper plugin. On restart, the plugin was reading the wrong part of a stored data key when trying to restore transaction block heights, causing it to log a 'BROKEN' error and set block heights to 0. The fix is a one-line change correcting an array index offset. It is a data-integrity/functional bug, not an exploitable security vulnerability.
Treat as a routine bug fix. Apply the patch to restore correct blockheight accounting on node restart. No emergency security response is warranted. Users relying on bookkeeper income reports should upgrade to avoid incorrect blockheight/time-based reporting.
Security signals we found
BROKEN log emitted due to malformed datastore parsing
Off-by-one index in JSON key parsing
Data integrity issue: derived blockheights reset to 0 on restart
No memory corruption, authentication bypass, or cryptographic weakness evident
Evidence from the diff
In plugins/bkpr/blockheights.c, init_blockheights() iterates over datastore entries with keys like [‘bookkeeper’,’blockheights’,
Changed components
plugins/bkpr/blockheights.cbookkeeper plugin datastore restore pathtests/test_bookkeeper.pyInspect captured patch +1 / −2
diff --git a/plugins/bkpr/blockheights.c b/plugins/bkpr/blockheights.c
index 094c8489..e483a066 100644
--- a/plugins/bkpr/blockheights.c
+++ b/plugins/bkpr/blockheights.c
@@ -140,7 +140,7 @@ struct blockheights *init_blockheights(const tal_t *ctx,
if (keytok->size != 3)
goto weird;
- if (!json_to_txid(buf, keytok + 2, &txid))
+ if (!json_to_txid(buf, keytok + 3, &txid))
goto weird;
if (!json_hex_to_be32(buf, hextok, &be_blockheight))
goto weird;
diff --git a/tests/test_bookkeeper.py b/tests/test_bookkeeper.py
index 26930898..4186d917 100644
--- a/tests/test_bookkeeper.py
+++ b/tests/test_bookkeeper.py
@@ -1164,7 +1164,6 @@ def test_migration_no_bkpr(node_factory, bitcoind):
'type': 'channel'}]
-@pytest.mark.xfail(strict=True)
@unittest.skipIf(TEST_NETWORK != 'regtest', "External wallet support doesn't work with elements yet.")
def test_listincome_timebox(node_factory, bitcoind):
l1 = node_factory.get_node()
Why this scored 21/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.