upleb.uk

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

summaryrefslogtreecommitdiff
path: root/src/main_gui.cpp
diff options
context:
space:
mode:
authorBitflash <btf01@proton.me>2026-08-01 14:48:27 -0300
committerGitHub <noreply@github.com>2026-08-01 14:48:27 -0300
commitb65c19e559e2fec511f40a4d5481bcf6a35c311c (patch)
treee54c0c58d44c46befae58924b1df913816b569e9 /src/main_gui.cpp
parentae81fa37123730982c4e054d7433c9d0c944a373 (diff)
wallet: walk the chain for coins a key owns but the wallet never saw (#88)
A transaction only entered the wallet when its block arrived over the network, so a key added afterwards was invisible: coins on the chain, private key in wallet.dat, balance zero. /importwallet has always ended that way -- it writes the keys and the money never shows up, which looks exactly like a failed import. ScanForWalletTransactions walks the main chain and hands every transaction that IsMine() to AddToWalletIfMine, the same two primitives the live path uses. Wired into /importwallet, and offered as /rescan. It is also the half that any recovery-phrase feature has to stand on: deriving keys from twelve words is easy, and without this a restore restores nothing.
Diffstat (limited to 'src/main_gui.cpp')
-rw-r--r--src/main_gui.cpp26
1 files changed, 26 insertions, 0 deletions
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; }