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-07-31 08:53:27 -0300
committerGitHub <noreply@github.com>2026-07-31 08:53:27 -0300
commit3bbfb50ef85feeddad936eb1fe8cce232410b8a6 (patch)
treea3a8b628489f81159aa417bbe44650b9c9eaf5c4 /src/main_gui.cpp
parent50b0a91b5dddd38f3094b9e97db77773d8299442 (diff)
db: verify the tail of the chain on startup and back out of a bad tip (#61)
A node that accepted blocks its current rules would reject -- because it was running an older build, or because the tip it landed on was never valid -- had no way to notice. It kept the branch, kept building on it, and kept mining coins the rest of the network throws away. The only cure was deleting blk*.dat by hand, which requires knowing something is wrong. A node here once mined a 323-block fork for five days that way. On load, walk back from the tip running CheckBlock on each block. If one fails, move the best chain back to its parent, disconnect what came after, and let the node re-download from peers. Satoshi added this after the block 74638 incident for the same reason: so it would not have needed anyone to delete files. Only the last 288 blocks are checked by default -- about ten hours at a two-minute target -- because every check costs a RandomX hash. /checkblocks=N changes it, 0 does the whole chain. The repair deliberately runs in LoadBlockIndex() in main.cpp rather than in CTxDB::LoadBlockIndex where the detection happens. CTxDB::LoadBlockIndex walks the index with a cursor it never closes, so it still holds read locks when it returns, and a write transaction opened alongside it waits on them forever. That is measured, not guessed: the first version came up, printed the diagnosis, and hung with nothing in any log. Closing that cursor is a separate fix worth making on its own. A failed rollback reports and starts anyway. Refusing to start would leave the operator with no node to read the message from. What this catches is what CheckBlock catches: proof of work, merkle root, duplicate transactions, sigops, timestamps. It does not re-verify signatures or spends, which would mean rebuilding the transaction index. Verified by forcing a block at tip-5 to fail: the node reported the bad block, moved back six, stayed up, and re-synced past its old tip. Without the forced failure it verifies 288 and says so.
Diffstat (limited to 'src/main_gui.cpp')
-rw-r--r--src/main_gui.cpp5
1 files changed, 5 insertions, 0 deletions
diff --git a/src/main_gui.cpp b/src/main_gui.cpp
index 852ad4d..99bcb6f 100644
--- a/src/main_gui.cpp
+++ b/src/main_gui.cpp
@@ -54,6 +54,7 @@ static void PrintUsage()
54 printf(" /participant=POOL_BTF_ADDRESS\n"); 54 printf(" /participant=POOL_BTF_ADDRESS\n");
55 printf(" /solomine\n"); 55 printf(" /solomine\n");
56 printf(" /genproclimit=N (mining threads; 0 or absent = every core but one)\n"); 56 printf(" /genproclimit=N (mining threads; 0 or absent = every core but one)\n");
57 printf(" /checkblocks=N (blocks re-verified at startup, default 288, 0 = all)\n");
57 printf("\n"); 58 printf("\n");
58 printf("Pool operator announcement:\n"); 59 printf("Pool operator announcement:\n");
59 printf(" /poolname=NAME\n"); 60 printf(" /poolname=NAME\n");
@@ -101,6 +102,10 @@ static void ParseStartupArguments(int argc, char* argv[])
101 if (arg(argc,argv,"/solomine") || arg(argc,argv,"-solomine")) 102 if (arg(argc,argv,"/solomine") || arg(argc,argv,"-solomine"))
102 fSoloMineTest = true; 103 fSoloMineTest = true;
103 104
105 string strCheckBlocks = argval2(argc, argv, "/checkblocks", "-checkblocks");
106 if (!strCheckBlocks.empty())
107 nCheckBlocksOnLoad = atoi(strCheckBlocks.c_str());
108
104 // /genproclimit=N -- threads to hash with. 0 or absent means automatic, 109 // /genproclimit=N -- threads to hash with. 0 or absent means automatic,
105 // which is every core but one. Named after Bitcoin's own option so it reads 110 // which is every core but one. Named after Bitcoin's own option so it reads
106 // familiarly to anyone who has run one of these before. 111 // familiarly to anyone who has run one of these before.