Skip to content

Commit ad8e060

Browse files
committed
Add more assertions to both PoS and PoW functional tests
1 parent f211d96 commit ad8e060

File tree

2 files changed

+102
-68
lines changed

2 files changed

+102
-68
lines changed

test/functional/blockprod_generate_pos_blocks.py

Lines changed: 71 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,13 @@
1515
# limitations under the License.
1616

1717
from hashlib import blake2b
18+
from scalecodec.base import ScaleBytes, RuntimeConfiguration, ScaleDecoder
1819
from test_framework.mintlayer import mintlayer_hash
1920
from test_framework.test_framework import BitcoinTestFramework
2021
from test_framework.util import (
2122
assert_equal,
2223
)
23-
24-
import random, scalecodec
24+
import random
2525

2626
GENESIS_POOL_ID = "123c4c600097c513e088b9be62069f0c74c7671c523c8e3469a1c3f14b7ea2c4"
2727
GENESIS_STAKE_PRIVATE_KEY = "8717e6946febd3a33ccdc3f3a27629ec80c33461c33a0fc56b4836fcedd26638"
@@ -33,52 +33,50 @@
3333
"e9f3cd7b78d45750afd17292031373fddb5e7a8090db51221038f5e05f29998e"
3434
)
3535

36-
block_input_data_obj = scalecodec.base.RuntimeConfiguration().create_scale_object('GenerateBlockInputData')
37-
outpoint_obj = scalecodec.base.RuntimeConfiguration().create_scale_object('OutPoint')
38-
signed_transaction_obj = scalecodec.base.RuntimeConfiguration().create_scale_object('SignedTransaction')
39-
transaction_obj = scalecodec.base.RuntimeConfiguration().create_scale_object('TransactionV1')
36+
block_input_data_obj = RuntimeConfiguration().create_scale_object('GenerateBlockInputData')
37+
outpoint_obj = RuntimeConfiguration().create_scale_object('OutPoint')
38+
signed_transaction_obj = RuntimeConfiguration().create_scale_object('SignedTransaction')
39+
transaction_obj = RuntimeConfiguration().create_scale_object('TransactionV1')
4040

4141
class GeneratePoSBlocksTest(BitcoinTestFramework):
4242
def set_test_params(self):
4343
self.setup_clean_chain = True
4444
self.num_nodes = 1
4545
self.extra_args = [["--chain-pos-netupgrades=true"]]
4646

47-
def block_height(self, n):
48-
tip = self.nodes[n].chainstate_best_block_id()
49-
return self.nodes[n].chainstate_block_height_in_main_chain(tip)
50-
51-
def assert_tip(self, expected):
52-
tip = self.nodes[0].chainstate_best_block_id()
53-
block = self.nodes[0].chainstate_get_block(tip)
54-
assert_equal(block, expected)
47+
def assert_chain(self, block, previous_tip):
48+
assert_equal(block["header"]["header"]["prev_block_id"][2:], previous_tip)
5549

56-
def hex_to_dec_array(self, hex_string):
57-
return [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
50+
def assert_height(self, expected_height, expected_block):
51+
block_id = self.nodes[0].chainstate_block_id_at_height(expected_height)
52+
block = self.nodes[0].chainstate_get_block(block_id)
53+
assert_equal(block, expected_block)
5854

59-
def generate_block(self, block_input_data, transactions):
60-
old_block_height = self.block_height(0)
55+
def assert_pos_consensus(self, block):
56+
if block["header"]["header"]["consensus_data"].get("PoS") is None:
57+
raise AssertionError("Block {} was not PoS".format(block_hex))
6158

62-
block = self.nodes[0].blockprod_generate_block(block_input_data, transactions)
63-
self.nodes[0].chainstate_submit_block(block)
59+
def assert_tip(self, expected_block):
60+
tip = self.nodes[0].chainstate_best_block_id()
61+
block = self.nodes[0].chainstate_get_block(tip)
62+
assert_equal(block, expected_block)
6463

65-
assert_equal(self.block_height(0), old_block_height + 1)
66-
self.assert_tip(block)
64+
def block_height(self, n):
65+
tip = self.nodes[n].chainstate_best_block_id()
66+
return self.nodes[n].chainstate_block_height_in_main_chain(tip)
6767

68-
def previous_block_id(self):
68+
def generate_block(self, expected_height, block_input_data, transactions):
6969
previous_block_id = self.nodes[0].chainstate_best_block_id()
70-
return self.hex_to_dec_array(previous_block_id)
70+
block_hex = self.nodes[0].blockprod_generate_block(block_input_data, transactions)
71+
block_hex_array = bytearray.fromhex(block_hex)
72+
block = ScaleDecoder.get_decoder_class('BlockV1', ScaleBytes(block_hex_array)).decode()
7173

72-
def pack_transaction(self, transaction):
73-
transaction_encoded = signed_transaction_obj.encode(transaction).to_hex()[2:]
74-
transaction_id = scalecodec.ScaleBytes(
75-
mintlayer_hash(transaction_obj.encode(transaction["transaction"]).data)
76-
).to_hex()[2:]
74+
self.nodes[0].chainstate_submit_block(block_hex)
7775

78-
return (transaction_encoded, transaction_id)
79-
80-
def genesis_pool_id(self):
81-
return self.hex_to_dec_array(GENESIS_POOL_ID)
76+
self.assert_tip(block_hex)
77+
self.assert_height(expected_height, block_hex)
78+
self.assert_pos_consensus(block)
79+
self.assert_chain(block, previous_block_id)
8280

8381
def generate_pool_id(self, transaction_id):
8482
kernel_input_outpoint = outpoint_obj.encode({
@@ -88,8 +86,6 @@ def generate_pool_id(self, transaction_id):
8886
"index": 0,
8987
}).to_hex()[2:]
9088

91-
outpoint = self.hex_to_dec_array(kernel_input_outpoint)
92-
9389
# Include PoolId pre-image suffix of [0, 0, 0, 0]
9490
blake2b_hasher = blake2b()
9591
blake2b_hasher.update(bytes.fromhex(kernel_input_outpoint))
@@ -98,6 +94,42 @@ def generate_pool_id(self, transaction_id):
9894
# Truncate output to match Rust's split()
9995
return self.hex_to_dec_array(blake2b_hasher.hexdigest()[:64])
10096

97+
def genesis_pool_id(self):
98+
return self.hex_to_dec_array(GENESIS_POOL_ID)
99+
100+
def hex_to_dec_array(self, hex_string):
101+
return [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
102+
103+
def new_stake_keys(self):
104+
new_stake_private_key_hex = self.nodes[0].test_functions_new_private_key()
105+
new_stake_private_key = self.stake_private_key(new_stake_private_key_hex[2:])
106+
107+
new_stake_public_key_hex = self.nodes[0].test_functions_public_key_from_private_key(new_stake_private_key_hex)
108+
new_stake_public_key = self.stake_public_key(new_stake_public_key_hex[2:])
109+
110+
return (new_stake_private_key, new_stake_public_key)
111+
112+
def new_vrf_keys(self):
113+
new_vrf_private_key_hex = self.nodes[0].test_functions_new_vrf_private_key()
114+
new_vrf_private_key = self.vrf_private_key(new_vrf_private_key_hex[2:])
115+
116+
new_vrf_public_key_hex = self.nodes[0].test_functions_vrf_public_key_from_private_key(new_vrf_private_key_hex)
117+
new_vrf_public_key = self.vrf_public_key(new_vrf_public_key_hex[2:])
118+
119+
return (new_vrf_private_key, new_vrf_public_key)
120+
121+
def pack_transaction(self, transaction):
122+
transaction_encoded = signed_transaction_obj.encode(transaction).to_hex()[2:]
123+
transaction_id = ScaleBytes(
124+
mintlayer_hash(transaction_obj.encode(transaction["transaction"]).data)
125+
).to_hex()[2:]
126+
127+
return (transaction_encoded, transaction_id)
128+
129+
def previous_block_id(self):
130+
previous_block_id = self.nodes[0].chainstate_best_block_id()
131+
return self.hex_to_dec_array(previous_block_id)
132+
101133
def stake_private_key(self, stake_private_key):
102134
return {
103135
"key": {
@@ -134,24 +166,6 @@ def vrf_public_key(self, vrf_public_key):
134166
},
135167
}
136168

137-
def new_stake_keys(self):
138-
new_stake_private_key_hex = self.nodes[0].test_functions_new_private_key()
139-
new_stake_private_key = self.stake_private_key(new_stake_private_key_hex[2:])
140-
141-
new_stake_public_key_hex = self.nodes[0].test_functions_public_key_from_private_key(new_stake_private_key_hex)
142-
new_stake_public_key = self.stake_public_key(new_stake_public_key_hex[2:])
143-
144-
return (new_stake_private_key, new_stake_public_key)
145-
146-
def new_vrf_keys(self):
147-
new_vrf_private_key_hex = self.nodes[0].test_functions_new_vrf_private_key()
148-
new_vrf_private_key = self.vrf_private_key(new_vrf_private_key_hex[2:])
149-
150-
new_vrf_public_key_hex = self.nodes[0].test_functions_vrf_public_key_from_private_key(new_vrf_private_key_hex)
151-
new_vrf_public_key = self.vrf_public_key(new_vrf_public_key_hex[2:])
152-
153-
return (new_vrf_private_key, new_vrf_public_key)
154-
155169
def run_test(self):
156170
#
157171
# Transfer Genesis UTXO to AnyoneCanSpend
@@ -227,7 +241,7 @@ def run_test(self):
227241
}
228242

229243
(transfer_transaction_encoded, transfer_transaction_id) = self.pack_transaction(transfer_transaction)
230-
self.generate_block(block_input_data, [transfer_transaction_encoded])
244+
self.generate_block(1, block_input_data, [transfer_transaction_encoded])
231245

232246
#
233247
# Create the new stake pool using the AnyoneCanSpend transaction
@@ -306,7 +320,7 @@ def run_test(self):
306320
}
307321

308322
(create_new_pool_transaction_encoded, create_new_pool_transaction_id) = self.pack_transaction(create_new_pool_transaction)
309-
self.generate_block(block_input_data, [create_new_pool_transaction_encoded])
323+
self.generate_block(2, block_input_data, [create_new_pool_transaction_encoded])
310324

311325
#
312326
# Stake many blocks with the new stake pool
@@ -335,7 +349,7 @@ def run_test(self):
335349
],
336350
}
337351

338-
for _ in range(1, random.randint(1,100)):
352+
for i in range(0, random.randint(10,100)):
339353
block_input_data = block_input_data_obj.encode({
340354
"PoS": {
341355
"stake_private_key": new_stake_private_key,
@@ -350,7 +364,7 @@ def run_test(self):
350364
}
351365
}).to_hex()[2:]
352366

353-
self.generate_block(block_input_data, [])
367+
self.generate_block(3 + i, block_input_data, [])
354368

355369
kernel_input_outpoint = {
356370
"id": {

test/functional/blockprod_generate_pow_blocks.py

Lines changed: 31 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# See the License for the specific language governing permissions and
1515
# limitations under the License.
1616

17+
from scalecodec.base import ScaleBytes, RuntimeConfiguration, ScaleDecoder
1718
from test_framework.test_framework import BitcoinTestFramework
1819
from test_framework.util import (
1920
assert_equal,
@@ -28,23 +29,42 @@ def set_test_params(self):
2829
self.setup_clean_chain = True
2930
self.num_nodes = 1
3031

31-
def block_height(self, n):
32-
tip = self.nodes[n].chainstate_best_block_id()
33-
return self.nodes[n].chainstate_block_height_in_main_chain(tip)
32+
def assert_chain(self, block, previous_tip):
33+
assert_equal(block["header"]["header"]["prev_block_id"][2:], previous_tip)
34+
35+
def assert_height(self, expected_height, expected_block):
36+
block_id = self.nodes[0].chainstate_block_id_at_height(expected_height)
37+
block = self.nodes[0].chainstate_get_block(block_id)
38+
assert_equal(block, expected_block)
39+
40+
def assert_pow_consensus(self, block):
41+
if block["header"]["header"]["consensus_data"].get("PoW") is None:
42+
raise AssertionError("Block {} was not PoS".format(block_hex))
3443

3544
def assert_tip(self, expected):
3645
tip = self.nodes[0].chainstate_best_block_id()
3746
block = self.nodes[0].chainstate_get_block(tip)
3847
assert_equal(block, expected)
3948

40-
def generate_block(self, block_input_data, transactions):
41-
old_block_height = self.block_height(0)
49+
def block_height(self, n):
50+
tip = self.nodes[n].chainstate_best_block_id()
51+
return self.nodes[n].chainstate_block_height_in_main_chain(tip)
52+
53+
def generate_block(self, expected_height, block_input_data, transactions):
54+
previous_block_id = self.nodes[0].chainstate_best_block_id()
55+
block_hex = self.nodes[0].blockprod_generate_block(block_input_data, transactions)
56+
block_hex_array = bytearray.fromhex(block_hex)
57+
block = ScaleDecoder.get_decoder_class('BlockV1', ScaleBytes(block_hex_array)).decode()
58+
59+
self.nodes[0].chainstate_submit_block(block_hex)
4260

43-
block = self.nodes[0].blockprod_generate_block(block_input_data, transactions)
44-
self.nodes[0].chainstate_submit_block(block)
61+
self.assert_tip(block_hex)
62+
self.assert_height(expected_height, block_hex)
63+
self.assert_pow_consensus(block)
64+
self.assert_chain(block, previous_block_id)
4565

46-
assert_equal(self.block_height(0), old_block_height + 1)
47-
self.assert_tip(block)
66+
def hex_to_dec_array(self, hex_string):
67+
return [int(hex_string[i:i+2], 16) for i in range(0, len(hex_string), 2)]
4868

4969
def run_test(self):
5070
block_input_data = block_input_data_obj.encode(
@@ -55,8 +75,8 @@ def run_test(self):
5575
}
5676
).to_hex()[2:]
5777

58-
for i in range(random.randint(100, 1000)):
59-
self.nodes[0].blockprod_generate_block(block_input_data, [])
78+
for i in range(random.randint(10, 100)):
79+
self.generate_block(i + 1, block_input_data, [])
6080

6181
if __name__ == '__main__':
6282
GeneratePoWBlocksTest().main()

0 commit comments

Comments
 (0)