From 7131c30c33c980f0ba1d37dfc6a3fbe8c319813e Mon Sep 17 00:00:00 2001 From: Bitflash Date: Sat, 1 Aug 2026 12:56:16 -0300 Subject: wallet: generate keys ahead of use so a backup outlives the next block (#85) The wallet made a key per address and per block mined, so a backup only ever contained the keys that existed the moment it was taken -- mine one block and the coin lands on a key the backup has never heard of. The README warned about it, which is an admission rather than a fix. Keys are now generated a hundred at a time and handed out one at a time, each written to wallet.dat before it can be pointed at. A backup covers the next hundred addresses. Deterministic derivation (#47) stays open; this buys back the distance between a backup and the next mistake. --- src/main.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) (limited to 'src/main.h') diff --git a/src/main.h b/src/main.h index a50485f..1d9efac 100644 --- a/src/main.h +++ b/src/main.h @@ -124,6 +124,32 @@ FILE* OpenBlockFile(unsigned int nFile, unsigned int nBlockPos, const char* pszM FILE* AppendBlockFile(unsigned int& nFileRet); bool AddKey(const CKey& key); vector GenerateNewKey(); + +// --- Key pool ------------------------------------------------------------- +// +// A backup of this wallet only ever contained the keys that existed the moment +// it was taken. Mine a block or take a new address afterwards and the coin +// lands on a key the backup has never heard of -- it is on the chain, and the +// file you carefully put away cannot spend it. The LEIA-ME shipped with a +// warning about this, which is an admission, not a fix. +// +// Keys are now generated a hundred at a time and handed out one by one, so a +// backup covers the next hundred addresses this node will use. It is the same +// answer Bitcoin arrived at, and it is not deterministic derivation (#47) -- +// it just buys back the distance between a backup and the next mistake. +static const int KEYPOOL_SIZE = 100; +extern CCriticalSection cs_keyPool; +extern map > mapKeyPool; + +// Fill the pool back up to KEYPOOL_SIZE. Every key it creates is written to +// wallet.dat before it is offered to anybody. +void TopUpKeyPool(); + +// Hand out the oldest unused key. Falls back to generating one on the spot if +// the pool cannot be filled, which is exactly what this code did before the +// pool existed -- a wallet that cannot pre-generate should still be able to +// mine. +vector GetKeyFromPool(); bool AddToWallet(const CWalletTx& wtxIn); void ReacceptWalletTransactions(); // Returns how many wallet transactions the chain corrected. -- cgit v1.2.3