upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/main.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/main.cpp')
-rw-r--r--src/main.cpp42
1 files changed, 34 insertions, 8 deletions
diff --git a/src/main.cpp b/src/main.cpp
index 2c4e346..9082bd5 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -254,21 +254,46 @@ bool SetHDSeedFromMnemonic(const string& strMnemonic, string& strErrorRet)
254 254
255 CRITICAL_BLOCK(cs_keyPool) 255 CRITICAL_BLOCK(cs_keyPool)
256 { 256 {
257 // Old private keys stay in wallet.dat, but old unused pool records must 257 // The pool is cleared before the seed is written, and the order is the
258 // not survive the seed. Otherwise the next address can still be random 258 // safe one of the two. Old private keys stay in wallet.dat either way;
259 // while the UI says a recovery phrase exists. 259 // what is at stake is which half-finished state a failure can leave.
260 //
261 // clear, then write -- a failed write leaves the old seed and an
262 // empty pool. TopUpKeyPool refills it, and nothing was promised to
263 // anybody.
264 //
265 // write, then clear -- a failed clear leaves a seed installed and the
266 // old random pool intact. The user has just been shown twelve words
267 // and the wallet goes on handing out addresses those words cannot
268 // reproduce. That is the bug this function exists to prevent.
269 //
270 // An earlier comment here said the seed was written first so a failure
271 // left the wallet untouched. That was true of the seed alone and stops
272 // being true once the pool has to move with it.
260 if (!ClearKeyPoolRecords(strErrorRet)) 273 if (!ClearKeyPoolRecords(strErrorRet))
261 return false; 274 return false;
262 275
263 if (!CWalletDB().WriteHDMaster(master.privateKey, master.chainCode) || 276 if (!CWalletDB().WriteHDMaster(master.privateKey, master.chainCode) ||
264 !CWalletDB().WriteHDNext(0)) 277 !CWalletDB().WriteHDNext(1))
265 { 278 {
266 strErrorRet = "could not write the seed to wallet.dat"; 279 strErrorRet = "could not write the seed to wallet.dat";
267 return false; 280 return false;
268 } 281 }
269 vchHDMaster = master.privateKey; 282 vchHDMaster = master.privateKey;
270 vchHDChainCode = master.chainCode; 283 vchHDChainCode = master.chainCode;
271 nHDNext = 0; 284
285 // Index 0 is spoken for before it is derived, so a failure below cannot
286 // leave the pool free to hand it out as an ordinary key. The cost of
287 // the counter being ahead of the derivation is one unused index; the
288 // cost of the reverse is the default address and a pool key sharing a
289 // derivation path.
290 nHDNext = 1;
291
292 // Remember which address stops being the default, so it can be named
293 // for what it is. Two entries reading "Your Address" -- one covered by
294 // the phrase and one not -- is the wrong thing to find at the moment a
295 // person has just written twelve words down.
296 vector<unsigned char> vchOldDefault = keyUser.GetPubKey();
272 297
273 CKey key; 298 CKey key;
274 if (!DeriveHDKey(0, key, strErrorRet)) 299 if (!DeriveHDKey(0, key, strErrorRet))
@@ -280,14 +305,15 @@ bool SetHDSeedFromMnemonic(const string& strMnemonic, string& strErrorRet)
280 } 305 }
281 vector<unsigned char> vchPubKey = key.GetPubKey(); 306 vector<unsigned char> vchPubKey = key.GetPubKey();
282 if (!CWalletDB().WriteDefaultKey(vchPubKey) || 307 if (!CWalletDB().WriteDefaultKey(vchPubKey) ||
283 !SetAddressBookName(PubKeyToAddress(vchPubKey), "Your Address") || 308 !SetAddressBookName(PubKeyToAddress(vchPubKey), "Your Address"))
284 !CWalletDB().WriteHDNext(1))
285 { 309 {
286 strErrorRet = "could not set the default derived receiving key"; 310 strErrorRet = "could not set the default derived receiving key";
287 return false; 311 return false;
288 } 312 }
313 if (!vchOldDefault.empty() && vchOldDefault != vchPubKey)
314 SetAddressBookName(PubKeyToAddress(vchOldDefault),
315 "Your Address (created before the recovery phrase)");
289 keyUser = key; 316 keyUser = key;
290 nHDNext = 1;
291 } 317 }
292 return true; 318 return true;
293} 319}