Test RandomX P2P header validation
This commit is contained in:
parent
c469e3c9ed
commit
0411c96b45
1 changed files with 63 additions and 22 deletions
|
|
@ -10,7 +10,13 @@ import threading
|
||||||
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR
|
from test_framework.address import ADDRESS_BCRT1_UNSPENDABLE_DESCRIPTOR
|
||||||
from test_framework.authproxy import JSONRPCException
|
from test_framework.authproxy import JSONRPCException
|
||||||
from test_framework.blocktools import NORMAL_GBT_REQUEST_PARAMS
|
from test_framework.blocktools import NORMAL_GBT_REQUEST_PARAMS
|
||||||
from test_framework.messages import CBlock, CBlockHeader, from_hex
|
from test_framework.messages import (
|
||||||
|
CBlock,
|
||||||
|
CBlockHeader,
|
||||||
|
from_hex,
|
||||||
|
msg_headers,
|
||||||
|
)
|
||||||
|
from test_framework.p2p import P2PDataStore
|
||||||
from test_framework.test_framework import DigiByteTestFramework
|
from test_framework.test_framework import DigiByteTestFramework
|
||||||
from test_framework.util import (
|
from test_framework.util import (
|
||||||
assert_equal,
|
assert_equal,
|
||||||
|
|
@ -26,16 +32,17 @@ BLOCK_VERSION_RANDOMX = 4 << 8
|
||||||
|
|
||||||
class RandomXGetBlockTemplateTest(DigiByteTestFramework):
|
class RandomXGetBlockTemplateTest(DigiByteTestFramework):
|
||||||
def set_test_params(self):
|
def set_test_params(self):
|
||||||
self.num_nodes = 2
|
self.num_nodes = 3
|
||||||
self.setup_clean_chain = True
|
self.setup_clean_chain = True
|
||||||
self.supports_cli = False
|
self.supports_cli = False
|
||||||
|
|
||||||
def run_test(self):
|
def run_test(self):
|
||||||
node = self.nodes[0]
|
node = self.nodes[0]
|
||||||
|
|
||||||
# Keep node 1 isolated at genesis so RandomX blocks can later be
|
# Keep nodes 1 and 2 isolated at genesis for independent
|
||||||
# submitted to it explicitly through submitblock.
|
# RandomX validation-path tests later in this test.
|
||||||
self.stop_node(1)
|
self.stop_node(1)
|
||||||
|
self.stop_node(2)
|
||||||
|
|
||||||
self.log.info("RandomX GBT is rejected before activation")
|
self.log.info("RandomX GBT is rejected before activation")
|
||||||
assert_raises_rpc_error(
|
assert_raises_rpc_error(
|
||||||
|
|
@ -412,7 +419,7 @@ class RandomXGetBlockTemplateTest(DigiByteTestFramework):
|
||||||
self.log.info("submitheader rejects invalid RandomX proof of work")
|
self.log.info("submitheader rejects invalid RandomX proof of work")
|
||||||
invalid_header_block = from_hex(CBlock(), randomx_proposal_block)
|
invalid_header_block = from_hex(CBlock(), randomx_proposal_block)
|
||||||
original_nonce = invalid_header_block.nNonce
|
original_nonce = invalid_header_block.nNonce
|
||||||
saw_high_hash = False
|
high_hash_nonce = None
|
||||||
|
|
||||||
for nonce_offset in range(1, 33):
|
for nonce_offset in range(1, 33):
|
||||||
invalid_header_block.nNonce = (
|
invalid_header_block.nNonce = (
|
||||||
|
|
@ -425,34 +432,68 @@ class RandomXGetBlockTemplateTest(DigiByteTestFramework):
|
||||||
)
|
)
|
||||||
except JSONRPCException as e:
|
except JSONRPCException as e:
|
||||||
if "high-hash" in e.error["message"]:
|
if "high-hash" in e.error["message"]:
|
||||||
saw_high_hash = True
|
high_hash_nonce = invalid_header_block.nNonce
|
||||||
break
|
break
|
||||||
raise
|
raise
|
||||||
|
|
||||||
assert saw_high_hash
|
assert high_hash_nonce is not None
|
||||||
assert_equal(submit_node.getblockcount(), 0)
|
assert_equal(submit_node.getblockcount(), 0)
|
||||||
|
|
||||||
self.log.info("submitblock rejects invalid RandomX proof of work")
|
self.log.info("submitblock rejects invalid RandomX proof of work")
|
||||||
|
self.start_node(
|
||||||
|
2,
|
||||||
|
extra_args=["-testactivationheight=randomx@1"],
|
||||||
|
)
|
||||||
|
invalid_submit_node = self.nodes[2]
|
||||||
|
assert_equal(invalid_submit_node.getblockcount(), 0)
|
||||||
|
|
||||||
invalid_block = from_hex(CBlock(), randomx_proposal_block)
|
invalid_block = from_hex(CBlock(), randomx_proposal_block)
|
||||||
original_nonce = invalid_block.nNonce
|
invalid_block.nNonce = high_hash_nonce
|
||||||
saw_submitblock_high_hash = False
|
|
||||||
|
|
||||||
# Use a separate nonce range from the submitheader test so these
|
assert_equal(
|
||||||
# candidate block hashes have not already been marked invalid.
|
invalid_submit_node.submitblock(
|
||||||
for nonce_offset in range(1000, 1032):
|
|
||||||
invalid_block.nNonce = (
|
|
||||||
original_nonce + nonce_offset
|
|
||||||
) & 0xffffffff
|
|
||||||
|
|
||||||
result = submit_node.submitblock(
|
|
||||||
invalid_block.serialize().hex()
|
invalid_block.serialize().hex()
|
||||||
|
),
|
||||||
|
"high-hash",
|
||||||
)
|
)
|
||||||
|
|
||||||
if result == "high-hash":
|
self.stop_node(2)
|
||||||
saw_submitblock_high_hash = True
|
assert_equal(submit_node.getblockcount(), 0)
|
||||||
break
|
|
||||||
|
|
||||||
assert saw_submitblock_high_hash
|
self.log.info("P2P headers accepts a valid RandomX header")
|
||||||
|
p2p_peer = submit_node.add_p2p_connection(P2PDataStore())
|
||||||
|
|
||||||
|
valid_p2p_block = from_hex(CBlock(), randomx_proposal_block)
|
||||||
|
p2p_peer.send_message(
|
||||||
|
msg_headers([CBlockHeader(valid_p2p_block)])
|
||||||
|
)
|
||||||
|
p2p_peer.sync_with_ping()
|
||||||
|
|
||||||
|
valid_p2p_header = submit_node.getblockheader(
|
||||||
|
randomx_proposal_hash
|
||||||
|
)
|
||||||
|
assert_equal(valid_p2p_header["hash"], randomx_proposal_hash)
|
||||||
|
assert_equal(valid_p2p_header["pow_algo_id"], 1)
|
||||||
|
assert_equal(valid_p2p_header["pow_algo"], "randomx")
|
||||||
|
assert_equal(submit_node.getblockcount(), 0)
|
||||||
|
|
||||||
|
self.log.info("P2P headers rejects invalid RandomX difficulty")
|
||||||
|
invalid_p2p_block = from_hex(CBlock(), randomx_proposal_block)
|
||||||
|
invalid_p2p_block.nBits ^= 1
|
||||||
|
invalid_p2p_hash = invalid_p2p_block.rehash()
|
||||||
|
invalid_p2p_hash_hex = f"{invalid_p2p_hash:064x}"
|
||||||
|
|
||||||
|
p2p_peer.send_message(
|
||||||
|
msg_headers([CBlockHeader(invalid_p2p_block)])
|
||||||
|
)
|
||||||
|
p2p_peer.sync_with_ping()
|
||||||
|
|
||||||
|
assert_raises_rpc_error(
|
||||||
|
-5,
|
||||||
|
"Block not found",
|
||||||
|
submit_node.getblockheader,
|
||||||
|
invalid_p2p_hash_hex,
|
||||||
|
)
|
||||||
assert_equal(submit_node.getblockcount(), 0)
|
assert_equal(submit_node.getblockcount(), 0)
|
||||||
|
|
||||||
self.log.info("Submit the mixed SHA256D and RandomX headers first")
|
self.log.info("Submit the mixed SHA256D and RandomX headers first")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue