Page MenuHomePhabricator

D7870.diff
No OneTemporary

D7870.diff

diff --git a/src/interfaces/chain.h b/src/interfaces/chain.h
--- a/src/interfaces/chain.h
+++ b/src/interfaces/chain.h
@@ -175,12 +175,26 @@
virtual bool findBlock(const BlockHash &hash,
const FoundBlock &block = {}) = 0;
+ //! Find ancestor of block at specified height and optionally return
+ //! ancestor information.
+ virtual bool findAncestorByHeight(const BlockHash &block_hash,
+ int ancestor_height,
+ const FoundBlock &ancestor_out = {}) = 0;
+
//! Return whether block descends from a specified ancestor, and
//! optionally return ancestor information.
virtual bool findAncestorByHash(const BlockHash &block_hash,
const BlockHash &ancestor_hash,
const FoundBlock &ancestor_out = {}) = 0;
+ //! Find most recent common ancestor between two blocks and optionally
+ //! return block information.
+ virtual bool findCommonAncestor(const BlockHash &block_hash1,
+ const BlockHash &block_hash2,
+ const FoundBlock &ancestor_out = {},
+ const FoundBlock &block1_out = {},
+ const FoundBlock &block2_out = {}) = 0;
+
//! Look up unspent output information. Returns coins in the mempool and in
//! the current chain UTXO set. Iterates through all the keys in the map and
//! populates the values.
diff --git a/src/interfaces/chain.cpp b/src/interfaces/chain.cpp
--- a/src/interfaces/chain.cpp
+++ b/src/interfaces/chain.cpp
@@ -283,6 +283,18 @@
WAIT_LOCK(cs_main, lock);
return FillBlock(LookupBlockIndex(hash), block, lock);
}
+ bool findAncestorByHeight(const BlockHash &block_hash,
+ int ancestor_height,
+ const FoundBlock &ancestor_out) override {
+ WAIT_LOCK(cs_main, lock);
+ if (const CBlockIndex *block = LookupBlockIndex(block_hash)) {
+ if (const CBlockIndex *ancestor =
+ block->GetAncestor(ancestor_height)) {
+ return FillBlock(ancestor, ancestor_out, lock);
+ }
+ }
+ return FillBlock(nullptr, ancestor_out, lock);
+ }
bool findAncestorByHash(const BlockHash &block_hash,
const BlockHash &ancestor_hash,
const FoundBlock &ancestor_out) override {
@@ -295,6 +307,20 @@
}
return FillBlock(ancestor, ancestor_out, lock);
}
+ bool findCommonAncestor(const BlockHash &block_hash1,
+ const BlockHash &block_hash2,
+ const FoundBlock &ancestor_out,
+ const FoundBlock &block1_out,
+ const FoundBlock &block2_out) override {
+ WAIT_LOCK(cs_main, lock);
+ const CBlockIndex *block1 = LookupBlockIndex(block_hash1);
+ const CBlockIndex *block2 = LookupBlockIndex(block_hash2);
+ const CBlockIndex *ancestor =
+ block1 && block2 ? LastCommonAncestor(block1, block2) : nullptr;
+ return FillBlock(ancestor, ancestor_out, lock) &
+ FillBlock(block1, block1_out, lock) &
+ FillBlock(block2, block2_out, lock);
+ }
void findCoins(std::map<COutPoint, Coin> &coins) override {
return FindCoins(coins);
}
diff --git a/src/test/interfaces_tests.cpp b/src/test/interfaces_tests.cpp
--- a/src/test/interfaces_tests.cpp
+++ b/src/test/interfaces_tests.cpp
@@ -3,7 +3,10 @@
// file COPYING or http://www.opensource.org/licenses/mit-license.php.
#include <chainparams.h>
+#include <config.h>
+#include <consensus/validation.h>
#include <interfaces/chain.h>
+#include <script/standard.h>
#include <test/util/setup_common.h>
#include <validation.h>
@@ -50,6 +53,16 @@
BOOST_CHECK(!chain->findBlock(BlockHash(), FoundBlock()));
}
+BOOST_AUTO_TEST_CASE(findAncestorByHeight) {
+ auto chain = interfaces::MakeChain(m_node, Params());
+ auto &active = ChainActive();
+ BlockHash hash;
+ BOOST_CHECK(chain->findAncestorByHeight(active[20]->GetBlockHash(), 10,
+ FoundBlock().hash(hash)));
+ BOOST_CHECK_EQUAL(hash, active[10]->GetBlockHash());
+ BOOST_CHECK(!chain->findAncestorByHeight(active[10]->GetBlockHash(), 20));
+}
+
BOOST_AUTO_TEST_CASE(findAncestorByHash) {
auto chain = interfaces::MakeChain(m_node, Params());
auto &active = ChainActive();
@@ -62,4 +75,31 @@
active[20]->GetBlockHash()));
}
+BOOST_AUTO_TEST_CASE(findCommonAncestor) {
+ auto chain = interfaces::MakeChain(m_node, Params());
+ auto &active = ChainActive();
+ auto *orig_tip = active.Tip();
+ for (int i = 0; i < 10; ++i) {
+ BlockValidationState state;
+ ChainstateActive().InvalidateBlock(GetConfig(), state, active.Tip());
+ }
+ BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight - 10);
+ coinbaseKey.MakeNewKey(true);
+ for (int i = 0; i < 20; ++i) {
+ CreateAndProcessBlock({},
+ GetScriptForRawPubKey(coinbaseKey.GetPubKey()));
+ }
+ BOOST_CHECK_EQUAL(active.Height(), orig_tip->nHeight + 10);
+ BlockHash fork_hash;
+ int fork_height;
+ int orig_height;
+ BOOST_CHECK(chain->findCommonAncestor(
+ orig_tip->GetBlockHash(), active.Tip()->GetBlockHash(),
+ FoundBlock().height(fork_height).hash(fork_hash),
+ FoundBlock().height(orig_height)));
+ BOOST_CHECK_EQUAL(orig_height, orig_tip->nHeight);
+ BOOST_CHECK_EQUAL(fork_height, orig_tip->nHeight - 10);
+ BOOST_CHECK_EQUAL(fork_hash, active[fork_height]->GetBlockHash());
+}
+
BOOST_AUTO_TEST_SUITE_END()
diff --git a/src/wallet/rpcwallet.cpp b/src/wallet/rpcwallet.cpp
--- a/src/wallet/rpcwallet.cpp
+++ b/src/wallet/rpcwallet.cpp
@@ -1870,8 +1870,12 @@
BlockHash blockId;
if (!request.params[0].isNull() && !request.params[0].get_str().empty()) {
blockId = BlockHash(ParseHashV(request.params[0], "blockhash"));
- height = locked_chain->findFork(blockId, &altheight);
- if (!height) {
+ height.emplace();
+ altheight.emplace();
+ if (!pwallet->chain().findCommonAncestor(
+ blockId, pwallet->GetLastBlockHash(),
+ /* ancestor out */ FoundBlock().height(*height),
+ /* blockId out */ FoundBlock().height(*altheight))) {
throw JSONRPCError(RPC_INVALID_ADDRESS_OR_KEY, "Block not found");
}
}
@@ -1891,8 +1895,7 @@
bool include_removed =
(request.params[3].isNull() || request.params[3].get_bool());
- const Optional<int> tip_height = locked_chain->getHeight();
- int depth = tip_height && height ? (1 + *tip_height - *height) : -1;
+ int depth = height ? pwallet->GetLastBlockHeight() + 1 - *height : -1;
UniValue transactions(UniValue::VARR);
@@ -1930,10 +1933,11 @@
--*altheight;
}
- int last_height = tip_height ? *tip_height + 1 - target_confirms : -1;
- BlockHash lastblock = last_height >= 0
- ? locked_chain->getBlockHash(last_height)
- : BlockHash();
+ BlockHash lastblock;
+ CHECK_NONFATAL(pwallet->chain().findAncestorByHeight(
+ pwallet->GetLastBlockHash(),
+ pwallet->GetLastBlockHeight() + 1 - target_confirms,
+ FoundBlock().hash(lastblock)));
UniValue ret(UniValue::VOBJ);
ret.pushKV("transactions", transactions);

File Metadata

Mime Type
text/plain
Expires
Sat, Mar 1, 11:03 (11 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5187465
Default Alt Text
D7870.diff (7 KB)

Event Timeline