Skip to content

Commit

Permalink
test: add signet mining tests
Browse files Browse the repository at this point in the history
Also adds a condition to test initialization code to not generate blocks for signet chains.
  • Loading branch information
kallewoof committed Jan 15, 2020
1 parent d1a31a8 commit 1a8c3a1
Show file tree
Hide file tree
Showing 5 changed files with 114 additions and 15 deletions.
95 changes: 95 additions & 0 deletions test/functional/mining_signet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
#!/usr/bin/env python3
# Copyright (c) 2019-2020 The Bitcoin Core developers
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test signet mining RPCs
- getmininginfo
- getblocktemplate proposal mode
- submitblock"""

from decimal import Decimal

from test_framework.blocktools import (
create_coinbase,
)
from test_framework.messages import (
CBlock,
)
from test_framework.test_framework import BitcoinTestFramework
from test_framework.util import (
assert_equal,
)

private_key = "ZFNp4W4HSatHDc4zsheMsDWgUg2uiB5PtnY2Y2hUCNCkQiF81KyV"
pubkey = "02c72b24ae2ee333f2da24aea66ce4338c01db8f26d0cc96f586d77edcb5238a4f"
address = "sb1qghzjzc0jvkjvvvymxnadmjjpu2tywmvagduwfj"
blockscript = "5121" + pubkey + "51ae" # 1-of-1 multisig
genesisnonce = 405557

def assert_template(node, block, expect, rehash=True):
if rehash:
block.hashMerkleRoot = block.calc_merkle_root()
rsp = node.getblocktemplate(template_request={'data': block.serialize().hex(), 'mode': 'proposal', 'rules': ['segwit']})
assert_equal(rsp, expect)

def generate(node, count):
for _ in range(count):
addr = node.getnewaddress()
block = node.getnewblockhex(addr)
signed = node.signblock(block)
node.grindblock(signed)


class SigMiningTest(BitcoinTestFramework):
def set_test_params(self):
self.chain = "signet"
self.num_nodes = 2
self.setup_clean_chain = True
shared_args = ["-signet_blockscript=" + blockscript, "-signet_genesisnonce=" + str(genesisnonce), "-signet_seednode=localhost:1234"]
self.extra_args = [shared_args, shared_args]

def skip_test_if_missing_module(self):
self.skip_if_no_wallet()

def run_test(self):
node = self.nodes[0]

# give the privkey to node 1 so it can sign
node.importprivkey(private_key)
self.log.info('Imported network private key')
self.log.info('address: %s, privkey: %s', address, node.dumpprivkey(address))

self.log.info('getmininginfo')
mining_info = node.getmininginfo()
assert_equal(mining_info['blocks'], 0)
assert_equal(mining_info['chain'], 'signet')
assert 'currentblocktx' not in mining_info
assert 'currentblockweight' not in mining_info
assert_equal(mining_info['networkhashps'], Decimal('0'))
assert_equal(mining_info['pooledtx'], 0)

# Mine a block to leave initial block download
# Actually we mine 20 cause there's a bug in the coinbase height serializers

generate(node, 20)
tmpl = node.getblocktemplate({'rules': ['segwit']})
self.log.info("getblocktemplate: Test capability advertised")
assert 'proposal' in tmpl['capabilities']
assert 'coinbasetxn' not in tmpl

coinbase_tx = create_coinbase(height=int(tmpl["height"]))
# sequence numbers must not be max for nLockTime to have effect
coinbase_tx.vin[0].nSequence = 2 ** 32 - 2
coinbase_tx.rehash()

block = CBlock()
block.nVersion = tmpl["version"]
block.hashPrevBlock = int(tmpl["previousblockhash"], 16)
block.nTime = tmpl["curtime"]
block.nBits = int(tmpl["bits"], 16)
block.nNonce = 0
block.vtx = [coinbase_tx]

if __name__ == '__main__':
SigMiningTest().main()
2 changes: 1 addition & 1 deletion test/functional/rpc_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def test_categories(self):
# command titles
titles = [line[3:-3] for line in node.help().splitlines() if line.startswith('==')]

components = ['Blockchain', 'Control', 'Generating', 'Mining', 'Network', 'Rawtransactions', 'Util']
components = ['Blockchain', 'Control', 'Generating', 'Mining', 'Network', 'Rawtransactions', 'Signet', 'Util']

if self.is_wallet_compiled():
components.append('Wallet')
Expand Down
1 change: 1 addition & 0 deletions test/functional/test_framework/mininode.py
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@
"mainnet": b"\xf9\xbe\xb4\xd9", # mainnet
"testnet3": b"\x0b\x11\x09\x07", # testnet3
"regtest": b"\xfa\xbf\xb5\xda", # regtest
"signet": b"\xf0\xc7\x70\x6a", # signet
}


Expand Down
30 changes: 16 additions & 14 deletions test/functional/test_framework/test_framework.py
Original file line number Diff line number Diff line change
Expand Up @@ -338,7 +338,8 @@ def setup_nodes(self):
extra_args = self.extra_args
self.add_nodes(self.num_nodes, extra_args)
self.start_nodes()
self.import_deterministic_coinbase_privkeys()
if self.chain != "signet":
self.import_deterministic_coinbase_privkeys()
if not self.setup_clean_chain:
for n in self.nodes:
assert_equal(n.getblockchaininfo()["blocks"], 199)
Expand Down Expand Up @@ -546,19 +547,20 @@ def _initialize_chain(self):
# Wait for RPC connections to be ready
self.nodes[CACHE_NODE_ID].wait_for_rpc_connection()

# Create a 199-block-long chain; each of the 4 first nodes
# gets 25 mature blocks and 25 immature.
# The 4th node gets only 24 immature blocks so that the very last
# block in the cache does not age too much (have an old tip age).
# This is needed so that we are out of IBD when the test starts,
# see the tip age check in IsInitialBlockDownload().
for i in range(8):
self.nodes[CACHE_NODE_ID].generatetoaddress(
nblocks=25 if i != 7 else 24,
address=TestNode.PRIV_KEYS[i % 4].address,
)

assert_equal(self.nodes[CACHE_NODE_ID].getblockchaininfo()["blocks"], 199)
if self.chain != "signet":
# Create a 199-block-long chain; each of the 4 first nodes
# gets 25 mature blocks and 25 immature.
# The 4th node gets only 24 immature blocks so that the very last
# block in the cache does not age too much (have an old tip age).
# This is needed so that we are out of IBD when the test starts,
# see the tip age check in IsInitialBlockDownload().
for i in range(8):
self.nodes[CACHE_NODE_ID].generatetoaddress(
nblocks=25 if i != 7 else 24,
address=TestNode.PRIV_KEYS[i % 4].address,
)

assert_equal(self.nodes[CACHE_NODE_ID].getblockchaininfo()["blocks"], 199)

# Shut it down, and clean up cache directories:
self.stop_nodes()
Expand Down
1 change: 1 addition & 0 deletions test/functional/test_runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
'rpc_bind.py --ipv6',
'rpc_bind.py --nonloopback',
'mining_basic.py',
'mining_signet.py',
'wallet_bumpfee.py',
'wallet_bumpfee_totalfee_deprecation.py',
'wallet_implicitsegwit.py',
Expand Down

0 comments on commit 1a8c3a1

Please sign in to comment.