diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/main.cpp | 49 | ||||
| -rw-r--r-- | src/main.h | 5 | ||||
| -rw-r--r-- | src/main_gui.cpp | 26 |
3 files changed, 80 insertions, 0 deletions
diff --git a/src/main.cpp b/src/main.cpp index b027cef..68ae44c 100644 --- a/src/main.cpp +++ b/src/main.cpp | |||
| @@ -305,6 +305,55 @@ bool AddToWalletIfMine(const CTransaction& tx, const CBlock* pblock) | |||
| 305 | return true; | 305 | return true; |
| 306 | } | 306 | } |
| 307 | 307 | ||
| 308 | int ScanForWalletTransactions(CBlockIndex* pindexStart) | ||
| 309 | { | ||
| 310 | // Walk the chain looking for transactions that belong to keys this wallet | ||
| 311 | // holds now, whatever it held when those blocks arrived. | ||
| 312 | // | ||
| 313 | // Nothing in this tree could do that. A key added after the fact -- from | ||
| 314 | // /importwallet, or from a backup restored onto a node that had since | ||
| 315 | // moved on -- was simply invisible: the coins were on the chain, the | ||
| 316 | // private key was in wallet.dat, and the balance did not show them, | ||
| 317 | // because a transaction only ever entered the wallet at the moment its | ||
| 318 | // block arrived over the network. | ||
| 319 | // | ||
| 320 | // Bitcoin grew the same function for the same reason. It is also what any | ||
| 321 | // recovery-phrase feature has to stand on: deriving the keys is the easy | ||
| 322 | // half, and without this the other half does not exist. | ||
| 323 | int nFound = 0; | ||
| 324 | int nScanned = 0; | ||
| 325 | CBlockIndex* pindex = pindexStart; | ||
| 326 | CRITICAL_BLOCK(cs_main) | ||
| 327 | { | ||
| 328 | while (pindex) | ||
| 329 | { | ||
| 330 | CBlock block; | ||
| 331 | if (block.ReadFromDisk(pindex, true)) | ||
| 332 | { | ||
| 333 | foreach(CTransaction& tx, block.vtx) | ||
| 334 | { | ||
| 335 | // Ask before handing it over: AddToWalletIfMine returns | ||
| 336 | // true for a transaction that is none of our business, so | ||
| 337 | // its return value cannot be counted. | ||
| 338 | if (tx.IsMine()) | ||
| 339 | { | ||
| 340 | if (AddToWalletIfMine(tx, &block)) | ||
| 341 | nFound++; | ||
| 342 | } | ||
| 343 | } | ||
| 344 | } | ||
| 345 | nScanned++; | ||
| 346 | if ((nScanned % 500) == 0) | ||
| 347 | printf("ScanForWalletTransactions() : %d blocks scanned, %d transaction(s) found\n", | ||
| 348 | nScanned, nFound); | ||
| 349 | pindex = pindex->pnext; | ||
| 350 | } | ||
| 351 | } | ||
| 352 | printf("ScanForWalletTransactions() : %d block(s) scanned, %d transaction(s) added or updated\n", | ||
| 353 | nScanned, nFound); | ||
| 354 | return nFound; | ||
| 355 | } | ||
| 356 | |||
| 308 | bool EraseFromWallet(uint256 hash) | 357 | bool EraseFromWallet(uint256 hash) |
| 309 | { | 358 | { |
| 310 | CRITICAL_BLOCK(cs_mapWallet) | 359 | CRITICAL_BLOCK(cs_mapWallet) |
| @@ -152,6 +152,11 @@ void TopUpKeyPool(); | |||
| 152 | vector<unsigned char> GetKeyFromPool(); | 152 | vector<unsigned char> GetKeyFromPool(); |
| 153 | bool AddToWallet(const CWalletTx& wtxIn); | 153 | bool AddToWallet(const CWalletTx& wtxIn); |
| 154 | void ReacceptWalletTransactions(); | 154 | void ReacceptWalletTransactions(); |
| 155 | // Walk the chain from pindexStart forward, adding every transaction that pays | ||
| 156 | // a key this wallet holds. Returns how many were added or updated. Needed by | ||
| 157 | // anything that puts a key into the wallet after the fact -- an import, a | ||
| 158 | // restored backup, and later a recovery phrase. | ||
| 159 | int ScanForWalletTransactions(CBlockIndex* pindexStart); | ||
| 155 | // Returns how many wallet transactions the chain corrected. | 160 | // Returns how many wallet transactions the chain corrected. |
| 156 | int RescanSpentFlags(); | 161 | int RescanSpentFlags(); |
| 157 | void RelayWalletTransactions(); | 162 | void RelayWalletTransactions(); |
diff --git a/src/main_gui.cpp b/src/main_gui.cpp index 5c87fe0..c9e27a9 100644 --- a/src/main_gui.cpp +++ b/src/main_gui.cpp | |||
| @@ -76,6 +76,8 @@ static void PrintUsage() | |||
| 76 | printf(" /dumpwallet=FILE (export private keys as text -- readable by\n"); | 76 | printf(" /dumpwallet=FILE (export private keys as text -- readable by\n"); |
| 77 | printf(" anyone, so guard it like cash)\n"); | 77 | printf(" anyone, so guard it like cash)\n"); |
| 78 | printf(" /importwallet=FILE (load keys from such a file back in)\n"); | 78 | printf(" /importwallet=FILE (load keys from such a file back in)\n"); |
| 79 | printf(" /rescan (walk the chain for coins this wallet owns\n"); | ||
| 80 | printf(" but never recorded, then exit)\n"); | ||
| 79 | printf("\n"); | 81 | printf("\n"); |
| 80 | printf("Each option also accepts '-' instead of '/'.\n"); | 82 | printf("Each option also accepts '-' instead of '/'.\n"); |
| 81 | } | 83 | } |
| @@ -307,13 +309,37 @@ int main(int argc, char* argv[]) | |||
| 307 | int nAdded = 0, nSkipped = 0; | 309 | int nAdded = 0, nSkipped = 0; |
| 308 | bool fOk = ImportWallet(strImport, nAdded, nSkipped); | 310 | bool fOk = ImportWallet(strImport, nAdded, nSkipped); |
| 309 | if (fOk) | 311 | if (fOk) |
| 312 | { | ||
| 310 | printf("Imported %d key(s); %d were already here.\n", nAdded, nSkipped); | 313 | printf("Imported %d key(s); %d were already here.\n", nAdded, nSkipped); |
| 314 | // Importing a key without looking for its coins leaves the user | ||
| 315 | // holding a wallet that says zero about money that is on the | ||
| 316 | // chain. That was the old behaviour and it looks exactly like the | ||
| 317 | // import having failed. | ||
| 318 | if (nAdded > 0) | ||
| 319 | { | ||
| 320 | printf("Looking through the chain for coins belonging to the imported key(s)...\n"); | ||
| 321 | int nFound = ScanForWalletTransactions(pindexGenesisBlock); | ||
| 322 | printf("Found %d transaction(s). Start the node normally to see the balance.\n", nFound); | ||
| 323 | } | ||
| 324 | } | ||
| 311 | else | 325 | else |
| 312 | fprintf(stderr, "Import failed.\n"); | 326 | fprintf(stderr, "Import failed.\n"); |
| 313 | DBFlush(true); | 327 | DBFlush(true); |
| 314 | return fOk ? 0 : 1; | 328 | return fOk ? 0 : 1; |
| 315 | } | 329 | } |
| 316 | 330 | ||
| 331 | // /rescan -- walk the chain and pick up anything the wallet's keys own but | ||
| 332 | // the wallet never recorded. Cheap to offer and the only recourse when a | ||
| 333 | // balance is wrong for this reason. | ||
| 334 | if (arg(argc,argv,"/rescan") || arg(argc,argv,"-rescan")) | ||
| 335 | { | ||
| 336 | printf("Rescanning the chain for this wallet's transactions...\n"); | ||
| 337 | int nFound = ScanForWalletTransactions(pindexGenesisBlock); | ||
| 338 | printf("Rescan done: %d transaction(s) added or updated.\n", nFound); | ||
| 339 | DBFlush(true); | ||
| 340 | return 0; | ||
| 341 | } | ||
| 342 | |||
| 317 | ReacceptWalletTransactions(); | 343 | ReacceptWalletTransactions(); |
| 318 | 344 | ||
| 319 | if (!StartNode(strErrors)) { fprintf(stderr,"StartNode: %s\n",strErrors.c_str()); return 1; } | 345 | if (!StartNode(strErrors)) { fprintf(stderr,"StartNode: %s\n",strErrors.c_str()); return 1; } |