upleb.uk

Public git repos — served from a NIP-34 GRASP relay at git.upleb.uk

summaryrefslogtreecommitdiff
path: root/src/db.h
diff options
context:
space:
mode:
authorbitflash <dev@bitflash.network>2026-08-18 14:33:40 -0300
committerbitflash <dev@bitflash.network>2026-08-18 14:33:40 -0300
commit440d7f393d74f309d29e1d10ba1f11c41c869226 (patch)
tree40c881b79ba7a2571cfd2bcfbb274031a5739071 /src/db.h
parente58c4022e0ddd137b93cdb3464753bef5df1d456 (diff)
wallet: bracket WriteHDMaster in a SQLite runtime transaction
The SQLite runtime wrote each record as its own autocommit, so a group that must land together -- hdmaster and hdchaincode, the two halves of an HD seed -- could be left half-written by a failure or crash between them, the incomplete-seed state -walletstoragecheck exists to catch. Berkeley DB was no worse (it is not transactional here either) but no better. Add WalletSQLiteRuntimeBeginTxn/CommitTxn/RollbackTxn -- no-ops that succeed when the SQLite backend is not active, so Berkeley DB keeps its existing per-write behaviour -- and wrap WriteHDMaster in them so the seed lands all-or-nothing under SQLite. The one BDB-atomic wallet rewrite, the encrypt path, is already matched by its own transaction in the SQLite encrypt branch; every other wallet multi-write is ordering-based on both backends by design. wallet-sqlite self-test now proves the bracket: a rolled-back runtime write leaves no record, a committed one persists, and WriteHDMaster lands both halves of the seed.
Diffstat (limited to 'src/db.h')
-rw-r--r--src/db.h20
1 files changed, 18 insertions, 2 deletions
diff --git a/src/db.h b/src/db.h
index fee5a82..1a272b9 100644
--- a/src/db.h
+++ b/src/db.h
@@ -365,6 +365,9 @@ bool WalletSQLiteRuntimeWriteRecord(const vector<unsigned char>& vchKey,
365 const vector<unsigned char>& vchValue, 365 const vector<unsigned char>& vchValue,
366 bool fOverwrite); 366 bool fOverwrite);
367bool WalletSQLiteRuntimeEraseRecord(const vector<unsigned char>& vchKey); 367bool WalletSQLiteRuntimeEraseRecord(const vector<unsigned char>& vchKey);
368bool WalletSQLiteRuntimeBeginTxn();
369bool WalletSQLiteRuntimeCommitTxn();
370void WalletSQLiteRuntimeRollbackTxn();
368 371
369 372
370 373
@@ -531,8 +534,21 @@ public:
531 534
532 bool WriteHDMaster(const vector<unsigned char>& vchMaster, const vector<unsigned char>& vchChainCode) 535 bool WriteHDMaster(const vector<unsigned char>& vchMaster, const vector<unsigned char>& vchChainCode)
533 { 536 {
534 return WriteWalletRecord(string("hdmaster"), vchMaster) 537 // hdmaster and hdchaincode are halves of one seed: a wallet with one but
535 && WriteWalletRecord(string("hdchaincode"), vchChainCode); 538 // not the other is an incomplete HD wallet (-walletstoragecheck flags
539 // exactly that). Under the SQLite runtime write them in one transaction
540 // so a failure or crash between the two cannot leave that half-state.
541 // Berkeley DB keeps its existing per-write behaviour -- the bracket is a
542 // no-op there.
543 if (!WalletSQLiteRuntimeBeginTxn())
544 return false;
545 if (!WriteWalletRecord(string("hdmaster"), vchMaster) ||
546 !WriteWalletRecord(string("hdchaincode"), vchChainCode))
547 {
548 WalletSQLiteRuntimeRollbackTxn();
549 return false;
550 }
551 return WalletSQLiteRuntimeCommitTxn();
536 } 552 }
537 553
538 bool WriteWalletMinVersion(int nVersion) 554 bool WriteWalletMinVersion(int nVersion)