Introduce getbestchainlock rpc and fix llmq-is-cl-conflicts.py (#3094)
* Introduce getbestchainlock rpc and fix llmq-is-cl-conflicts.py * Add `known_block` field and move `getbestchainlock` to `blockchain` rpc category * Add CChainLockSig::IsNull() and throw an exception in getbestchainlock if there is no known chainlock yet * drop blockHash initializer
This commit is contained in:
parent
ac0270871c
commit
1c74b668b6
@ -23,6 +23,11 @@ static const std::string CLSIG_REQUESTID_PREFIX = "clsig";
|
||||
|
||||
CChainLocksHandler* chainLocksHandler;
|
||||
|
||||
bool CChainLockSig::IsNull() const
|
||||
{
|
||||
return nHeight == -1 && blockHash == uint256();
|
||||
}
|
||||
|
||||
std::string CChainLockSig::ToString() const
|
||||
{
|
||||
return strprintf("CChainLockSig(nHeight=%d, blockHash=%s)", nHeight, blockHash.ToString());
|
||||
@ -72,6 +77,12 @@ bool CChainLocksHandler::GetChainLockByHash(const uint256& hash, llmq::CChainLoc
|
||||
return true;
|
||||
}
|
||||
|
||||
CChainLockSig CChainLocksHandler::GetBestChainLock()
|
||||
{
|
||||
LOCK(cs);
|
||||
return bestChainLock;
|
||||
}
|
||||
|
||||
void CChainLocksHandler::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
|
||||
{
|
||||
if (!sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED)) {
|
||||
@ -101,7 +112,7 @@ void CChainLocksHandler::ProcessNewChainLock(NodeId from, const llmq::CChainLock
|
||||
return;
|
||||
}
|
||||
|
||||
if (bestChainLock.nHeight != -1 && clsig.nHeight <= bestChainLock.nHeight) {
|
||||
if (!bestChainLock.IsNull() && clsig.nHeight <= bestChainLock.nHeight) {
|
||||
// no need to process/relay older CLSIGs
|
||||
return;
|
||||
}
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
READWRITE(sig);
|
||||
}
|
||||
|
||||
bool IsNull() const;
|
||||
std::string ToString() const;
|
||||
};
|
||||
|
||||
@ -85,6 +86,7 @@ public:
|
||||
|
||||
bool AlreadyHave(const CInv& inv);
|
||||
bool GetChainLockByHash(const uint256& hash, CChainLockSig& ret);
|
||||
CChainLockSig GetBestChainLock();
|
||||
|
||||
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
|
||||
void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash);
|
||||
|
@ -207,6 +207,34 @@ UniValue getbestblockhash(const JSONRPCRequest& request)
|
||||
return chainActive.Tip()->GetBlockHash().GetHex();
|
||||
}
|
||||
|
||||
UniValue getbestchainlock(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() != 0)
|
||||
throw std::runtime_error(
|
||||
"getbestchainlock\n"
|
||||
"\nReturns the block hash of the best chainlock. Throws an error if there is no known chainlock yet.\n"
|
||||
"\nResult:\n"
|
||||
"{\n"
|
||||
" \"blockhash\" : \"hash\", (string) The block hash hex encoded\n"
|
||||
" \"height\" : n, (numeric) The block height or index\n"
|
||||
" \"known_block\" : true|false (boolean) True if the block is known by our node\n"
|
||||
"}\n"
|
||||
"\nExamples:\n"
|
||||
+ HelpExampleCli("getbestchainlock", "")
|
||||
+ HelpExampleRpc("getbestchainlock", "")
|
||||
);
|
||||
UniValue result(UniValue::VOBJ);
|
||||
llmq::CChainLockSig clsig = llmq::chainLocksHandler->GetBestChainLock();
|
||||
if (clsig.IsNull()) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to find any chainlock");
|
||||
}
|
||||
result.push_back(Pair("blockhash", clsig.blockHash.GetHex()));
|
||||
result.push_back(Pair("height", clsig.nHeight));
|
||||
LOCK(cs_main);
|
||||
result.push_back(Pair("known_block", mapBlockIndex.count(clsig.blockHash) > 0));
|
||||
return result;
|
||||
}
|
||||
|
||||
void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
|
||||
{
|
||||
if(pindex) {
|
||||
@ -2161,6 +2189,7 @@ static const CRPCCommand commands[] =
|
||||
{ "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} },
|
||||
{ "blockchain", "getblockstats", &getblockstats, true, {"hash_or_height", "stats"} },
|
||||
{ "blockchain", "getbestblockhash", &getbestblockhash, true, {} },
|
||||
{ "blockchain", "getbestchainlock", &getbestchainlock, true, {} },
|
||||
{ "blockchain", "getblockcount", &getblockcount, true, {} },
|
||||
{ "blockchain", "getblock", &getblock, true, {"blockhash","verbosity|verbose"} },
|
||||
{ "blockchain", "getblockhashes", &getblockhashes, true, {"high","low"} },
|
||||
|
@ -112,9 +112,7 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
|
||||
cl = self.create_chainlock(self.nodes[0].getblockcount() + 1, block.sha256)
|
||||
self.test_node.send_clsig(cl)
|
||||
|
||||
# Give the CLSIG some time to propagate. We unfortunately can't check propagation here as "getblock/getblockheader"
|
||||
# is required to check for CLSIGs, but this requires the block header to be propagated already
|
||||
time.sleep(1)
|
||||
self.wait_for_best_chainlock(self.nodes[1], "%064x" % block.sha256)
|
||||
|
||||
# The block should get accepted now, and at the same time prune the conflicting ISLOCKs
|
||||
submit_result = self.nodes[1].submitblock(ToHex(block))
|
||||
@ -223,6 +221,17 @@ class LLMQ_IS_CL_Conflicts(DashTestFramework):
|
||||
time.sleep(0.1)
|
||||
raise AssertionError("wait_for_chainlock timed out")
|
||||
|
||||
def wait_for_best_chainlock(self, node, block_hash):
|
||||
t = time.time()
|
||||
while time.time() - t < 15:
|
||||
try:
|
||||
if node.getbestchainlock()["blockhash"] == block_hash:
|
||||
return
|
||||
except:
|
||||
pass
|
||||
time.sleep(0.1)
|
||||
raise AssertionError("wait_for_best_chainlock timed out")
|
||||
|
||||
def create_block(self, node, vtx=[]):
|
||||
bt = node.getblocktemplate()
|
||||
height = bt['height']
|
||||
|
Loading…
Reference in New Issue
Block a user