Skip to content

Commit 563e022

Browse files
UdjinM6barrystyle
authored andcommitted
Introduce getbestchainlock rpc and fix llmq-is-cl-conflicts.py (dashpay#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
1 parent 79ff5cb commit 563e022

File tree

4 files changed

+55
-4
lines changed

4 files changed

+55
-4
lines changed

src/llmq/quorums_chainlocks.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,11 @@ static const std::string CLSIG_REQUESTID_PREFIX = "clsig";
2323

2424
CChainLocksHandler* chainLocksHandler;
2525

26+
bool CChainLockSig::IsNull() const
27+
{
28+
return nHeight == -1 && blockHash == uint256();
29+
}
30+
2631
std::string CChainLockSig::ToString() const
2732
{
2833
return strprintf("CChainLockSig(nHeight=%d, blockHash=%s)", nHeight, blockHash.ToString());
@@ -72,6 +77,12 @@ bool CChainLocksHandler::GetChainLockByHash(const uint256& hash, llmq::CChainLoc
7277
return true;
7378
}
7479

80+
CChainLockSig CChainLocksHandler::GetBestChainLock()
81+
{
82+
LOCK(cs);
83+
return bestChainLock;
84+
}
85+
7586
void CChainLocksHandler::ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman)
7687
{
7788
if (!sporkManager.IsSporkActive(SPORK_19_CHAINLOCKS_ENABLED)) {
@@ -101,7 +112,7 @@ void CChainLocksHandler::ProcessNewChainLock(NodeId from, const llmq::CChainLock
101112
return;
102113
}
103114

104-
if (bestChainLock.nHeight != -1 && clsig.nHeight <= bestChainLock.nHeight) {
115+
if (!bestChainLock.IsNull() && clsig.nHeight <= bestChainLock.nHeight) {
105116
// no need to process/relay older CLSIGs
106117
return;
107118
}

src/llmq/quorums_chainlocks.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ class CChainLockSig
3838
READWRITE(sig);
3939
}
4040

41+
bool IsNull() const;
4142
std::string ToString() const;
4243
};
4344

@@ -85,6 +86,7 @@ class CChainLocksHandler : public CRecoveredSigsListener
8586

8687
bool AlreadyHave(const CInv& inv);
8788
bool GetChainLockByHash(const uint256& hash, CChainLockSig& ret);
89+
CChainLockSig GetBestChainLock();
8890

8991
void ProcessMessage(CNode* pfrom, const std::string& strCommand, CDataStream& vRecv, CConnman& connman);
9092
void ProcessNewChainLock(NodeId from, const CChainLockSig& clsig, const uint256& hash);

src/rpc/blockchain.cpp

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,34 @@ UniValue getbestblockhash(const JSONRPCRequest& request)
208208
return chainActive.Tip()->GetBlockHash().GetHex();
209209
}
210210

211+
UniValue getbestchainlock(const JSONRPCRequest& request)
212+
{
213+
if (request.fHelp || request.params.size() != 0)
214+
throw std::runtime_error(
215+
"getbestchainlock\n"
216+
"\nReturns the block hash of the best chainlock. Throws an error if there is no known chainlock yet.\n"
217+
"\nResult:\n"
218+
"{\n"
219+
" \"blockhash\" : \"hash\", (string) The block hash hex encoded\n"
220+
" \"height\" : n, (numeric) The block height or index\n"
221+
" \"known_block\" : true|false (boolean) True if the block is known by our node\n"
222+
"}\n"
223+
"\nExamples:\n"
224+
+ HelpExampleCli("getbestchainlock", "")
225+
+ HelpExampleRpc("getbestchainlock", "")
226+
);
227+
UniValue result(UniValue::VOBJ);
228+
llmq::CChainLockSig clsig = llmq::chainLocksHandler->GetBestChainLock();
229+
if (clsig.IsNull()) {
230+
throw JSONRPCError(RPC_INTERNAL_ERROR, "Unable to find any chainlock");
231+
}
232+
result.push_back(Pair("blockhash", clsig.blockHash.GetHex()));
233+
result.push_back(Pair("height", clsig.nHeight));
234+
LOCK(cs_main);
235+
result.push_back(Pair("known_block", mapBlockIndex.count(clsig.blockHash) > 0));
236+
return result;
237+
}
238+
211239
void RPCNotifyBlockChange(bool ibd, const CBlockIndex * pindex)
212240
{
213241
if(pindex) {
@@ -2162,6 +2190,7 @@ static const CRPCCommand commands[] =
21622190
{ "blockchain", "getchaintxstats", &getchaintxstats, true, {"nblocks", "blockhash"} },
21632191
{ "blockchain", "getblockstats", &getblockstats, true, {"hash_or_height", "stats"} },
21642192
{ "blockchain", "getbestblockhash", &getbestblockhash, true, {} },
2193+
{ "blockchain", "getbestchainlock", &getbestchainlock, true, {} },
21652194
{ "blockchain", "getblockcount", &getblockcount, true, {} },
21662195
{ "blockchain", "getblock", &getblock, true, {"blockhash","verbosity|verbose"} },
21672196
{ "blockchain", "getblockhashes", &getblockhashes, true, {"high","low"} },

test/functional/llmq-is-cl-conflicts.py

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,9 +112,7 @@ def test_chainlock_overrides_islock(self, test_block_conflict):
112112
cl = self.create_chainlock(self.nodes[0].getblockcount() + 1, block.sha256)
113113
self.test_node.send_clsig(cl)
114114

115-
# Give the CLSIG some time to propagate. We unfortunately can't check propagation here as "getblock/getblockheader"
116-
# is required to check for CLSIGs, but this requires the block header to be propagated already
117-
time.sleep(1)
115+
self.wait_for_best_chainlock(self.nodes[1], "%064x" % block.sha256)
118116

119117
# The block should get accepted now, and at the same time prune the conflicting ISLOCKs
120118
submit_result = self.nodes[1].submitblock(ToHex(block))
@@ -223,6 +221,17 @@ def wait_for_chainlock(self, node, block_hash):
223221
time.sleep(0.1)
224222
raise AssertionError("wait_for_chainlock timed out")
225223

224+
def wait_for_best_chainlock(self, node, block_hash):
225+
t = time.time()
226+
while time.time() - t < 15:
227+
try:
228+
if node.getbestchainlock()["blockhash"] == block_hash:
229+
return
230+
except:
231+
pass
232+
time.sleep(0.1)
233+
raise AssertionError("wait_for_best_chainlock timed out")
234+
226235
def create_block(self, node, vtx=[]):
227236
bt = node.getblocktemplate()
228237
height = bt['height']

0 commit comments

Comments
 (0)