diff options
Diffstat (limited to 'src/main.cpp')
| -rw-r--r-- | src/main.cpp | 42 |
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 | } |