Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche_proof_voting.py
Show All 33 Lines | class AvalancheProofVotingTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.conflicting_proof_cooldown = 100 | self.conflicting_proof_cooldown = 100 | ||||
self.peer_replacement_cooldown = 2000 | self.peer_replacement_cooldown = 2000 | ||||
self.extra_args = [ | self.extra_args = [ | ||||
['-enableavalanche=1', | ['-enableavalanche=1', | ||||
'-enableavalancheproofreplacement=1', | '-enableavalancheproofreplacement=1', | ||||
'-avaproofstakeutxoconfirmations=1', | '-avaproofstakeutxoconfirmations=2', | ||||
f'-avalancheconflictingproofcooldown={self.conflicting_proof_cooldown}', f'-avalanchepeerreplacementcooldown={self.peer_replacement_cooldown}', '-avacooldown=0', '-avastalevotethreshold=140', '-avastalevotefactor=1'], | f'-avalancheconflictingproofcooldown={self.conflicting_proof_cooldown}', f'-avalanchepeerreplacementcooldown={self.peer_replacement_cooldown}', '-avacooldown=0', '-avastalevotethreshold=140', '-avastalevotefactor=1'], | ||||
] | ] | ||||
self.supports_cli = False | self.supports_cli = False | ||||
# Build a fake quorum of nodes. | # Build a fake quorum of nodes. | ||||
def get_quorum(self, node): | def get_quorum(self, node): | ||||
quorum = [get_ava_p2p_interface(node) | quorum = [get_ava_p2p_interface(node) | ||||
for _ in range(0, QUORUM_NODE_COUNT)] | for _ in range(0, QUORUM_NODE_COUNT)] | ||||
▲ Show 20 Lines • Show All 50 Lines • ▼ Show 20 Lines | def build_conflicting_proof(self, node, sequence): | ||||
sequence, 0, self.privkey_wif, self.conflicting_stakes) | sequence, 0, self.privkey_wif, self.conflicting_stakes) | ||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
self.privkey, self.quorum_proof = gen_proof(node) | self.privkey, self.quorum_proof = gen_proof(node) | ||||
self.privkey_wif = bytes_to_wif(self.privkey.get_bytes()) | self.privkey_wif = bytes_to_wif(self.privkey.get_bytes()) | ||||
# Make the quorum proof mature before preparing the quorum | |||||
node.generate(1) | |||||
self.quorum = self.get_quorum(node) | self.quorum = self.get_quorum(node) | ||||
addrkey0 = node.get_deterministic_priv_key() | addrkey0 = node.get_deterministic_priv_key() | ||||
blockhash = node.generatetoaddress(10, addrkey0.address) | blockhash = node.generatetoaddress(10, addrkey0.address) | ||||
self.conflicting_stakes = create_coinbase_stakes( | self.conflicting_stakes = create_coinbase_stakes( | ||||
node, blockhash[5:], addrkey0.key) | node, blockhash[5:9], addrkey0.key) | ||||
self.immature_stakes = create_coinbase_stakes( | |||||
node, blockhash[9:], addrkey0.key) | |||||
self.poll_tests(node) | self.poll_tests(node) | ||||
self.update_tests(node) | self.update_tests(node) | ||||
self.vote_tests(node) | self.vote_tests(node) | ||||
self.stale_proof_tests(node) | self.stale_proof_tests(node) | ||||
self.unorphan_poll_tests(node) | self.unorphan_poll_tests(node) | ||||
def poll_tests(self, node): | def poll_tests(self, node): | ||||
proof_seq10 = self.build_conflicting_proof(node, 10) | proof_seq10 = self.build_conflicting_proof(node, 10) | ||||
proof_seq20 = self.build_conflicting_proof(node, 20) | proof_seq20 = self.build_conflicting_proof(node, 20) | ||||
proof_seq30 = self.build_conflicting_proof(node, 30) | proof_seq30 = self.build_conflicting_proof(node, 30) | ||||
proof_seq40 = self.build_conflicting_proof(node, 40) | proof_seq40 = self.build_conflicting_proof(node, 40) | ||||
orphan = node.buildavalancheproof( | orphan = node.buildavalancheproof( | ||||
100, 2000000000, self.privkey_wif, [{ | 100, 0, self.privkey_wif, self.immature_stakes) | ||||
'txid': '0' * 64, | |||||
'vout': 0, | |||||
'amount': 10e6, | |||||
'height': 42, | |||||
'iscoinbase': False, | |||||
'privatekey': self.privkey_wif, | |||||
}] | |||||
) | |||||
no_stake = node.buildavalancheproof( | no_stake = node.buildavalancheproof( | ||||
200, 2000000000, self.privkey_wif, [] | 200, 2000000000, self.privkey_wif, [] | ||||
) | ) | ||||
# Get the key so we can verify signatures. | # Get the key so we can verify signatures. | ||||
avakey = ECPubKey() | avakey = ECPubKey() | ||||
avakey.set(bytes.fromhex(node.getavalanchekey())) | avakey.set(bytes.fromhex(node.getavalanchekey())) | ||||
▲ Show 20 Lines • Show All 159 Lines • ▼ Show 20 Lines | def update_tests(self, node): | ||||
self.send_proof(peer, proof_seq50) | self.send_proof(peer, proof_seq50) | ||||
assert_raises_rpc_error(-8, | assert_raises_rpc_error(-8, | ||||
"Proof not found", | "Proof not found", | ||||
node.getrawavalancheproof, | node.getrawavalancheproof, | ||||
f"{proofid_seq50:0{64}x}") | f"{proofid_seq50:0{64}x}") | ||||
def vote_tests(self, node): | def vote_tests(self, node): | ||||
self.restart_node(0, extra_args=['-enableavalanche=1', | self.restart_node(0, extra_args=['-enableavalanche=1', | ||||
'-avaproofstakeutxoconfirmations=1', | '-avaproofstakeutxoconfirmations=2', | ||||
'-avacooldown=0', | '-avacooldown=0', | ||||
'-avalancheconflictingproofcooldown=0', | '-avalancheconflictingproofcooldown=0', | ||||
'-whitelist=noban@127.0.0.1', ]) | '-whitelist=noban@127.0.0.1', ]) | ||||
ava_node = get_ava_p2p_interface(node) | ava_node = get_ava_p2p_interface(node) | ||||
# Generate coinbases to use for stakes | # Generate coinbases to use for stakes | ||||
stakes_key = node.get_deterministic_priv_key() | stakes_key = node.get_deterministic_priv_key() | ||||
Show All 11 Lines | def vote_tests(self, node): | ||||
# proof_0 is valid right now | # proof_0 is valid right now | ||||
stakes_0 = create_coinbase_stakes(node, [blocks[0]], stakes_key.key) | stakes_0 = create_coinbase_stakes(node, [blocks[0]], stakes_key.key) | ||||
proof_0, proof_0_id = create_proof(stakes_0) | proof_0, proof_0_id = create_proof(stakes_0) | ||||
# proof_1 is valid right now, and from different stakes | # proof_1 is valid right now, and from different stakes | ||||
stakes_1 = create_coinbase_stakes(node, [blocks[1]], stakes_key.key) | stakes_1 = create_coinbase_stakes(node, [blocks[1]], stakes_key.key) | ||||
proof_1, proof_1_id = create_proof(stakes_1) | proof_1, proof_1_id = create_proof(stakes_1) | ||||
# proof_2 is an orphan because the stake UTXO is unknown | # proof_2 is an orphan because the stake UTXO is immature | ||||
stakes_2 = create_coinbase_stakes(node, [blocks[2]], stakes_key.key) | stakes_2 = create_coinbase_stakes(node, [blocks[3]], stakes_key.key) | ||||
stakes_2[0]['height'] = 5 | |||||
proof_2, proof_2_id = create_proof(stakes_2) | proof_2, proof_2_id = create_proof(stakes_2) | ||||
# proof_3 conflicts with proof_0 and proof_1 | # proof_3 conflicts with proof_0 and proof_1 | ||||
stakes_3 = create_coinbase_stakes( | stakes_3 = create_coinbase_stakes( | ||||
node, [blocks[0], blocks[1]], stakes_key.key) | node, [blocks[0], blocks[1]], stakes_key.key) | ||||
proof_3, proof_3_id = create_proof(stakes_3) | proof_3, proof_3_id = create_proof(stakes_3) | ||||
# proof_4 is invalid and should be rejected | # proof_4 is invalid and should be rejected | ||||
stakes_4 = create_coinbase_stakes(node, [blocks[3]], stakes_key.key) | stakes_4 = create_coinbase_stakes(node, [blocks[2]], stakes_key.key) | ||||
stakes_4[0]['amount'] -= 100000 | stakes_4[0]['amount'] -= 100000 | ||||
proof_4, proof_4_id = create_proof(stakes_4) | proof_4, proof_4_id = create_proof(stakes_4) | ||||
# Create a helper to issue a poll and validate the responses | # Create a helper to issue a poll and validate the responses | ||||
def poll_assert_response(expected): | def poll_assert_response(expected): | ||||
# Issue a poll for each proof | # Issue a poll for each proof | ||||
self.log.info("Trigger polling from the node...") | self.log.info("Trigger polling from the node...") | ||||
ava_node.send_poll( | ava_node.send_poll( | ||||
▲ Show 20 Lines • Show All 149 Lines • Show Last 20 Lines |