Browse Source

Report status of chain tips

0.10
Pieter Wuille 10 years ago
parent
commit
1b91be49f5
  1. 1
      qa/pull-tester/rpc-tests.sh
  2. 7
      qa/rpc-tests/getchaintips.py
  3. 27
      src/rpcblockchain.cpp

1
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/listtransactions.py --srcdir "${BUILDDIR}/src"
${BUILDDIR}/qa/rpc-tests/txn_doublespend.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/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" #${BUILDDIR}/qa/rpc-tests/forknotify.py --srcdir "${BUILDDIR}/src"
else else
echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled" echo "No rpc tests to run. Wallet, utils, and bitcoind must all be enabled"

7
qa/rpc-tests/getchaintips.py

@ -19,6 +19,7 @@ class GetChainTipsTest (BitcoinTestFramework):
assert_equal (len (tips), 1) assert_equal (len (tips), 1)
assert_equal (tips[0]['branchlen'], 0) assert_equal (tips[0]['branchlen'], 0)
assert_equal (tips[0]['height'], 200) assert_equal (tips[0]['height'], 200)
assert_equal (tips[0]['status'], 'active')
# Split the network and build two chains of different lengths. # Split the network and build two chains of different lengths.
self.split_network () self.split_network ()
@ -31,12 +32,14 @@ class GetChainTipsTest (BitcoinTestFramework):
shortTip = tips[0] shortTip = tips[0]
assert_equal (shortTip['branchlen'], 0) assert_equal (shortTip['branchlen'], 0)
assert_equal (shortTip['height'], 210) assert_equal (shortTip['height'], 210)
assert_equal (tips[0]['status'], 'active')
tips = self.nodes[3].getchaintips () tips = self.nodes[3].getchaintips ()
assert_equal (len (tips), 1) assert_equal (len (tips), 1)
longTip = tips[0] longTip = tips[0]
assert_equal (longTip['branchlen'], 0) assert_equal (longTip['branchlen'], 0)
assert_equal (longTip['height'], 220) assert_equal (longTip['height'], 220)
assert_equal (tips[0]['status'], 'active')
# Join the network halves and check that we now have two tips # Join the network halves and check that we now have two tips
# (at least at the nodes that previously had the short chain). # (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[0], longTip)
assert_equal (tips[1]['branchlen'], 10) 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) assert_equal (tips[1], shortTip)
if __name__ == '__main__': if __name__ == '__main__':

27
src/rpcblockchain.cpp

@ -496,11 +496,13 @@ Value getchaintips(const Array& params, bool fHelp)
" \"height\": xxxx, (numeric) height of the chain tip\n" " \"height\": xxxx, (numeric) height of the chain tip\n"
" \"hash\": \"xxxx\", (string) block hash of the tip\n" " \"hash\": \"xxxx\", (string) block hash of the tip\n"
" \"branchlen\": 0 (numeric) zero for main chain\n" " \"branchlen\": 0 (numeric) zero for main chain\n"
" \"status\": \"active\" (string) \"active\" for the main chain\n"
" },\n" " },\n"
" {\n" " {\n"
" \"height\": xxxx,\n" " \"height\": xxxx,\n"
" \"hash\": \"xxxx\",\n" " \"hash\": \"xxxx\",\n"
" \"branchlen\": 1 (numeric) length of branch connecting the tip to the main chain\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"
"]\n" "]\n"
"\nExamples:\n" "\nExamples:\n"
@ -521,6 +523,9 @@ Value getchaintips(const Array& params, bool fHelp)
setTips.erase(pprev); setTips.erase(pprev);
} }
// Always report the currently active tip.
setTips.insert(chainActive.Tip());
/* Construct the output array. */ /* Construct the output array. */
Array res; Array res;
BOOST_FOREACH(const CBlockIndex* block, setTips) 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; const int branchLen = block->nHeight - chainActive.FindFork(block)->nHeight;
obj.push_back(Pair("branchlen", branchLen)); 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); res.push_back(obj);
} }

Loading…
Cancel
Save