diff options
author | Pieter Wuille <pieter.wuille@gmail.com> | 2014-11-27 10:46:55 +0100 |
---|---|---|
committer | Pieter Wuille <pieter.wuille@gmail.com> | 2014-11-27 11:50:14 +0100 |
commit | 1b91be49f53936429d16fb841433139a66af6262 (patch) | |
tree | cca11383e87193ef82fefe2ceba69e344cfdcf7a | |
parent | 9ff0bc9beb90cf96fb0a9698de22e2bc60fed2f2 (diff) |
Report status of chain tips
-rwxr-xr-x | qa/pull-tester/rpc-tests.sh | 1 | ||||
-rwxr-xr-x | qa/rpc-tests/getchaintips.py | 7 | ||||
-rw-r--r-- | src/rpcblockchain.cpp | 27 |
3 files changed, 34 insertions, 1 deletions
diff --git a/qa/pull-tester/rpc-tests.sh b/qa/pull-tester/rpc-tests.sh index e01e870390..2f1e24b78d 100755 --- a/qa/pull-tester/rpc-tests.sh +++ b/qa/pull-tester/rpc-tests.sh @@ -20,6 +20,7 @@ if [ "x${ENABLE_BITCOIND}${ENABLE_UTILS}${ENABLE_WALLET}" = "x111" ]; then ${BUILDDIR}/qa/rpc-tests/listtransactions.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --srcdir "${BUILDDIR}/src" ${BUILDDIR}/qa/rpc-tests/txn_doublespend.py --mineblock --srcdir "${BUILDDIR}/src" + ${BUILDDIR}/qa/rpc-tests/getchaintips.py --srcdir "${BUILDDIR}/src" #${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src" else echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" diff --git a/qa/rpc-tests/getchaintips.py b/qa/rpc-tests/getchaintips.py index dda3450eb6..1e84b40e43 100755 --- a/qa/rpc-tests/getchaintips.py +++ b/qa/rpc-tests/getchaintips.py @@ -19,6 +19,7 @@ class GetChainTipsTest (BitcoinTestFramework): assert_equal (len (tips), 1) assert_equal (tips[0]['branchlen'], 0) assert_equal (tips[0]['height'], 200) + assert_equal (tips[0]['status'], 'active') # Split the network and build two chains of different lengths. self.split_network () @@ -31,12 +32,14 @@ class GetChainTipsTest (BitcoinTestFramework): shortTip = tips[0] assert_equal (shortTip['branchlen'], 0) assert_equal (shortTip['height'], 210) + assert_equal (tips[0]['status'], 'active') tips = self.nodes[3].getchaintips () assert_equal (len (tips), 1) longTip = tips[0] assert_equal (longTip['branchlen'], 0) assert_equal (longTip['height'], 220) + assert_equal (tips[0]['status'], 'active') # Join the network halves and check that we now have two tips # (at least at the nodes that previously had the short chain). @@ -47,7 +50,9 @@ class GetChainTipsTest (BitcoinTestFramework): assert_equal (tips[0], longTip) assert_equal (tips[1]['branchlen'], 10) - tips[1]['branchlen'] = 0; + assert_equal (tips[1]['status'], 'valid-fork') + tips[1]['branchlen'] = 0 + tips[1]['status'] = 'active' assert_equal (tips[1], shortTip) if __name__ == '__main__': diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index e8b0f62a83..5c4ee691dd 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -496,11 +496,13 @@ Value getchaintips(const Array& params, bool fHelp) " \"height\": xxxx, (numeric) height of the chain tip\n" " \"hash\": \"xxxx\", (string) block hash of the tip\n" " \"branchlen\": 0 (numeric) zero for main chain\n" + " \"status\": \"active\" (string) \"active\" for the main chain\n" " },\n" " {\n" " \"height\": xxxx,\n" " \"hash\": \"xxxx\",\n" " \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\n" + " \"status\": \"xxxx\" (string) status of the chain (active, valid-fork, valid-headers, headers-only, invalid)\n" " }\n" "]\n" "\nExamples:\n" @@ -521,6 +523,9 @@ Value getchaintips(const Array& params, bool fHelp) setTips.erase(pprev); } + // Always report the currently active tip. + setTips.insert(chainActive.Tip()); + /* Construct the output array. */ Array res; BOOST_FOREACH(const CBlockIndex* block, setTips) @@ -532,6 +537,28 @@ Value getchaintips(const Array& params, bool fHelp) const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight; obj.push_back(Pair("branchlen", branchLen)); + string status; + if (chainActive.Contains(block)) { + // This block is part of the currently active chain. + status = "active"; + } else if (block->nStatus & BLOCK_FAILED_MASK) { + // This block or one of its ancestors is invalid. + status = "invalid"; + } else if (block->nChainTx == 0) { + // This block cannot be connected because full block data for it or one of its parents is missing. + status = "headers-only"; + } else if (block->IsValid(BLOCK_VALID_SCRIPTS)) { + // This block is fully validated, but no longer part of the active chain. It was probably the active block once, but was reorganized. + status = "valid-fork"; + } else if (block->IsValid(BLOCK_VALID_TREE)) { + // The headers for this block are valid, but it has not been validated. It was probably never part of the most-work chain. + status = "valid-headers"; + } else { + // No clue. + status = "unknown"; + } + obj.push_back(Pair("status", status)); + res.push_back(obj); } |