From 0bc1e2c4319a0c0e7e3435e139cb9783d28eef1c Mon Sep 17 00:00:00 2001 From: Jack Grigg Date: Fri, 10 Mar 2017 20:04:14 +1300 Subject: [PATCH] Add anchor to output of getblock Closes #2164. --- src/chain.h | 4 ++++ src/main.cpp | 21 +++++++++++++++++++++ src/rpcblockchain.cpp | 1 + 3 files changed, 26 insertions(+) diff --git a/src/chain.h b/src/chain.h index 2abb23c5..e4076e00 100644 --- a/src/chain.h +++ b/src/chain.h @@ -141,6 +141,9 @@ public: //! The anchor for the tree state up to the start of this block uint256 hashAnchor; + //! (memory only) The anchor for the tree state up to the end of this block + uint256 hashAnchorEnd; + //! block header int nVersion; uint256 hashMerkleRoot; @@ -167,6 +170,7 @@ public: nChainTx = 0; nStatus = 0; hashAnchor = uint256(); + hashAnchorEnd = uint256(); nSequenceId = 0; nVersion = 0; diff --git a/src/main.cpp b/src/main.cpp index 52e8ca4c..a430ec27 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2061,6 +2061,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Before the genesis block, there was an empty tree ZCIncrementalMerkleTree tree; pindex->hashAnchor = tree.root(); + // The genesis block contained no JoinSplits + pindex->hashAnchorEnd = pindex->hashAnchor; } return true; } @@ -2175,6 +2177,9 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin } view.PushAnchor(tree); + if (!fJustCheck) { + pindex->hashAnchorEnd = tree.root(); + } blockundo.old_tree_root = old_tree_root; int64_t nTime1 = GetTimeMicros(); nTimeConnect += nTime1 - nTimeStart; @@ -3579,11 +3584,27 @@ bool static LoadBlockIndexDB() pblocktree->ReadFlag("txindex", fTxIndex); LogPrintf("%s: transaction index %s\n", __func__, fTxIndex ? "enabled" : "disabled"); + // Fill in-memory data + BOOST_FOREACH(const PAIRTYPE(uint256, CBlockIndex*)& item, mapBlockIndex) + { + CBlockIndex* pindex = item.second; + // - This relationship will always be true even if pprev has multiple + // children, because hashAnchor is technically a property of pprev, + // not its children. + // - This will miss chain tips; we handle the best tip below, and other + // tips will be handled by ConnectTip during a re-org. + if (pindex->pprev) { + pindex->pprev->hashAnchorEnd = pindex->hashAnchor; + } + } + // Load pointer to end of best chain BlockMap::iterator it = mapBlockIndex.find(pcoinsTip->GetBestBlock()); if (it == mapBlockIndex.end()) return true; chainActive.SetTip(it->second); + // Set hashAnchorEnd for the end of best chain + it->second->hashAnchorEnd = pcoinsTip->GetBestAnchor(); PruneBlockIndexCandidates(); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index 24bff3f4..0936640c 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -131,6 +131,7 @@ UniValue blockToJSON(const CBlock& block, const CBlockIndex* blockindex, bool tx result.push_back(Pair("bits", strprintf("%08x", block.nBits))); result.push_back(Pair("difficulty", GetDifficulty(blockindex))); result.push_back(Pair("chainwork", blockindex->nChainWork.GetHex())); + result.push_back(Pair("anchor", blockindex->hashAnchorEnd.GetHex())); if (blockindex->pprev) result.push_back(Pair("previousblockhash", blockindex->pprev->GetBlockHash().GetHex()));