mirror of
https://github.com/dashpay/dash.git
synced 2024-12-25 12:02:48 +01:00
rpc|llmq|test: Implement verifychainlock
(#4119)
* llmq: Make CLSIG_REQUESTID_PREFIX available outside of quorums_chainlocks.cpp * rpc: Implement `verifychainlock` * test: Add rpc_verifychainlock.py * rpc: Fix help text Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com> Co-authored-by: UdjinM6 <UdjinM6@users.noreply.github.com>
This commit is contained in:
parent
5f3c580b4d
commit
97e75f0147
@ -17,7 +17,7 @@
|
||||
namespace llmq
|
||||
{
|
||||
|
||||
static const std::string CLSIG_REQUESTID_PREFIX = "clsig";
|
||||
const std::string CLSIG_REQUESTID_PREFIX = "clsig";
|
||||
|
||||
CChainLocksHandler* chainLocksHandler;
|
||||
|
||||
|
@ -22,6 +22,8 @@ class CScheduler;
|
||||
namespace llmq
|
||||
{
|
||||
|
||||
extern const std::string CLSIG_REQUESTID_PREFIX;
|
||||
|
||||
class CChainLockSig
|
||||
{
|
||||
public:
|
||||
|
@ -15,6 +15,10 @@
|
||||
#include <llmq/quorums_signing.h>
|
||||
#include <llmq/quorums_signing_shares.h>
|
||||
|
||||
namespace llmq {
|
||||
extern const std::string CLSIG_REQUESTID_PREFIX;
|
||||
}
|
||||
|
||||
void quorum_list_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
@ -652,6 +656,48 @@ UniValue quorum(const JSONRPCRequest& request)
|
||||
}
|
||||
}
|
||||
|
||||
void verifychainlock_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
"verifychainlock \"blockHash\" \"signature\" ( blockHeight )\n"
|
||||
"Test if a quorum signature is valid for a ChainLock.\n"
|
||||
"\nArguments:\n"
|
||||
"1. \"blockHash\" (string, required) The block hash of the ChainLock.\n"
|
||||
"2. \"signature\" (string, required) The signature of the ChainLock.\n"
|
||||
"3. blockHeight (integer, optional) The height of the ChainLock. There will be an internal lookup of \"blockHash\" if this is not provided.\n"
|
||||
);
|
||||
}
|
||||
|
||||
UniValue verifychainlock(const JSONRPCRequest& request)
|
||||
{
|
||||
if (request.fHelp || request.params.size() < 2 || request.params.size() > 3) {
|
||||
verifychainlock_help();
|
||||
}
|
||||
|
||||
const uint256 nBlockHash = ParseHashV(request.params[0], "blockHash");
|
||||
|
||||
CBLSSignature chainLockSig;
|
||||
if (!chainLockSig.SetHexStr(request.params[1].get_str())) {
|
||||
throw JSONRPCError(RPC_INVALID_PARAMETER, "invalid signature format");
|
||||
}
|
||||
|
||||
int nBlockHeight;
|
||||
if (request.params[2].isNull()) {
|
||||
LOCK(cs_main);
|
||||
const CBlockIndex* pIndex = LookupBlockIndex(nBlockHash);
|
||||
if (pIndex == nullptr) {
|
||||
throw JSONRPCError(RPC_INTERNAL_ERROR, "blockHash not found");
|
||||
}
|
||||
nBlockHeight = pIndex->nHeight;
|
||||
} else {
|
||||
nBlockHeight = ParseInt32V(request.params[2], "blockHeight");
|
||||
}
|
||||
|
||||
const auto llmqType = Params().GetConsensus().llmqTypeChainLocks;
|
||||
const uint256 nRequestId = ::SerializeHash(std::make_pair(llmq::CLSIG_REQUESTID_PREFIX, nBlockHeight));
|
||||
return llmq::CSigningManager::VerifyRecoveredSig(llmqType, nBlockHeight, nRequestId, nBlockHash, chainLockSig);
|
||||
}
|
||||
|
||||
void verifyislock_help()
|
||||
{
|
||||
throw std::runtime_error(
|
||||
@ -713,6 +759,7 @@ static const CRPCCommand commands[] =
|
||||
{ // category name actor (function)
|
||||
// --------------------- ------------------------ -----------------------
|
||||
{ "evo", "quorum", &quorum, {} },
|
||||
{ "evo", "verifychainlock", &verifychainlock, {"blockHash", "signature", "blockHeight"} },
|
||||
{ "evo", "verifyislock", &verifyislock, {"id", "txid", "signature", "maxHeight"} },
|
||||
};
|
||||
|
||||
|
61
test/functional/rpc_verifychainlock.py
Executable file
61
test/functional/rpc_verifychainlock.py
Executable file
@ -0,0 +1,61 @@
|
||||
#!/usr/bin/env python3
|
||||
# Copyright (c) 2021 The Dash Core developers
|
||||
# Distributed under the MIT software license, see the accompanying
|
||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
|
||||
|
||||
from test_framework.test_framework import DashTestFramework
|
||||
from test_framework.util import assert_raises_rpc_error
|
||||
|
||||
'''
|
||||
rpc_verifychainlock.py
|
||||
|
||||
Test verifychainlock rpc
|
||||
|
||||
'''
|
||||
|
||||
|
||||
class RPCVerifyChainLockTest(DashTestFramework):
|
||||
def set_test_params(self):
|
||||
# -whitelist is needed to avoid the trickling logic on node0
|
||||
self.set_dash_test_params(5, 3, [["-whitelist=127.0.0.1"], [], [], [], []], fast_dip3_enforcement=True)
|
||||
self.set_dash_llmq_test_params(3, 2)
|
||||
|
||||
def run_test(self):
|
||||
node0 = self.nodes[0]
|
||||
node1 = self.nodes[1]
|
||||
self.activate_dip8()
|
||||
self.nodes[0].spork("SPORK_17_QUORUM_DKG_ENABLED", 0)
|
||||
self.wait_for_sporks_same()
|
||||
self.mine_quorum()
|
||||
self.wait_for_chainlocked_block(node0, node0.generate(1)[0])
|
||||
chainlock = node0.getbestchainlock()
|
||||
block_hash = chainlock["blockhash"]
|
||||
height = chainlock["height"]
|
||||
chainlock_signature = chainlock["signature"]
|
||||
# No "blockHeight"
|
||||
assert node0.verifychainlock(block_hash, chainlock_signature)
|
||||
# Invalid "blockHeight"
|
||||
assert not node0.verifychainlock(block_hash, chainlock_signature, 0)
|
||||
# Valid "blockHeight"
|
||||
assert node0.verifychainlock(block_hash, chainlock_signature, height)
|
||||
# Invalid "blockHash"
|
||||
assert not node0.verifychainlock(node0.getblockhash(0), chainlock_signature, height)
|
||||
# Isolate node1, mine a block on node0 and wait for its ChainLock
|
||||
node1.setnetworkactive(False)
|
||||
node0.generate(1)
|
||||
self.wait_for_chainlocked_block(node0, node0.generate(1)[0])
|
||||
chainlock = node0.getbestchainlock()
|
||||
assert chainlock != node1.getbestchainlock()
|
||||
block_hash = chainlock["blockhash"]
|
||||
height = chainlock["height"]
|
||||
chainlock_signature = chainlock["signature"]
|
||||
# Now it should verify on node0 without "blockHeight" but fail on node1
|
||||
assert node0.verifychainlock(block_hash, chainlock_signature)
|
||||
assert_raises_rpc_error(-32603, "blockHash not found", node1.verifychainlock, block_hash, chainlock_signature)
|
||||
# But they should still both verify with the height provided
|
||||
assert node0.verifychainlock(block_hash, chainlock_signature, height)
|
||||
assert node1.verifychainlock(block_hash, chainlock_signature, height)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
RPCVerifyChainLockTest().main()
|
@ -162,6 +162,7 @@ BASE_SCRIPTS= [
|
||||
'rpc_masternode.py',
|
||||
'rpc_mnauth.py',
|
||||
'rpc_verifyislock.py',
|
||||
'rpc_verifychainlock.py',
|
||||
'p2p_fingerprint.py',
|
||||
'rpc_platform_filter.py',
|
||||
'feature_dip0020_activation.py',
|
||||
|
Loading…
Reference in New Issue
Block a user