Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche_quorum.py
Show All 18 Lines | |||||
) | ) | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal | from test_framework.util import assert_equal | ||||
class AvalancheQuorumTest(BitcoinTestFramework): | class AvalancheQuorumTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 2 | self.num_nodes = 3 | ||||
self.min_avaproofs_node_count = 8 | self.min_avaproofs_node_count = 8 | ||||
self.extra_args = [[ | self.extra_args = [[ | ||||
'-enableavalanche=1', | '-enableavalanche=1', | ||||
'-avacooldown=0', | '-avacooldown=0', | ||||
'-avatimeout=0', | '-avatimeout=0', | ||||
'-avaminquorumstake=100000000', | '-avaminquorumstake=100000000', | ||||
'-avaminquorumconnectedstakeratio=0.8', | '-avaminquorumconnectedstakeratio=0.8', | ||||
'-minimumchainwork=0', | |||||
]] * self.num_nodes | ]] * self.num_nodes | ||||
self.extra_args[0] = self.extra_args[0] + \ | self.extra_args[0] = self.extra_args[0] + \ | ||||
['-avaminavaproofsnodecount=0'] | ['-avaminavaproofsnodecount=0'] | ||||
self.extra_args[1] = self.extra_args[1] + \ | self.extra_args[1] = self.extra_args[1] + \ | ||||
[f'-avaminavaproofsnodecount={self.min_avaproofs_node_count}'] | [f'-avaminavaproofsnodecount={self.min_avaproofs_node_count}'] | ||||
self.extra_args[2] = self.extra_args[2] + \ | |||||
[f'-avaminavaproofsnodecount={self.min_avaproofs_node_count}'] | |||||
def run_test(self): | def run_test(self): | ||||
# Prepare peers proofs | # Prepare peers proofs | ||||
peers = [] | peers = [] | ||||
for i in range(0, self.min_avaproofs_node_count): | for i in range(0, self.min_avaproofs_node_count): | ||||
key, proof = gen_proof(self.nodes[0]) | key, proof = gen_proof(self.nodes[0]) | ||||
peers.append({'key': key, 'proof': proof}) | peers.append({'key': key, 'proof': proof}) | ||||
# Let the nodes known about all the blocks then disconnect them so we're | # Let the nodes known about all the blocks then disconnect them so we're | ||||
# sure they won't exchange proofs when we start connecting peers. | # sure they won't exchange proofs when we start connecting peers. | ||||
self.sync_all() | self.sync_all() | ||||
self.disconnect_nodes(0, 1) | self.disconnect_nodes(0, 1) | ||||
# Restart node 2 to apply the minimum chainwork and make sure it's still | |||||
# in IBD state. | |||||
chainwork = int(self.nodes[2].getblockchaininfo()['chainwork'], 16) | |||||
self.restart_node( | |||||
2, | |||||
extra_args=self.extra_args[2] + | |||||
[f'-minimumchainwork={chainwork + 2:#x}']) | |||||
assert self.nodes[2].getblockchaininfo()['initialblockdownload'] | |||||
# Build polling nodes | # Build polling nodes | ||||
pollers = [get_ava_p2p_interface(node) for node in self.nodes] | pollers = [get_ava_p2p_interface(node) for node in self.nodes] | ||||
def poll_and_assert_response(node, expected): | def poll_and_assert_response(node, expected): | ||||
pubkey = ECPubKey() | pubkey = ECPubKey() | ||||
pubkey.set(bytes.fromhex(node.getavalanchekey())) | pubkey.set(bytes.fromhex(node.getavalanchekey())) | ||||
poller = pollers[node.index] | poller = pollers[node.index] | ||||
▲ Show 20 Lines • Show All 56 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
[poll_and_assert_response(node, AvalancheVoteError.UNKNOWN) | [poll_and_assert_response(node, AvalancheVoteError.UNKNOWN) | ||||
for node in self.nodes] | for node in self.nodes] | ||||
# Create one peer with half the score and add one node | # Create one peer with half the score and add one node | ||||
add_avapeer_and_check_status( | add_avapeer_and_check_status( | ||||
peers[0], [ | peers[0], [ | ||||
AvalancheVoteError.UNKNOWN, | AvalancheVoteError.UNKNOWN, | ||||
AvalancheVoteError.UNKNOWN, | AvalancheVoteError.UNKNOWN, | ||||
AvalancheVoteError.UNKNOWN, | |||||
]) | ]) | ||||
# Create a second peer with the other half and add one node. | # Create a second peer with the other half and add one node. | ||||
# This is enough for node0 but not node1 | # This is enough for node0 but not node1 | ||||
add_avapeer_and_check_status( | add_avapeer_and_check_status( | ||||
peers[1], [ | peers[1], [ | ||||
AvalancheVoteError.ACCEPTED, | AvalancheVoteError.ACCEPTED, | ||||
AvalancheVoteError.UNKNOWN, | AvalancheVoteError.UNKNOWN, | ||||
AvalancheVoteError.UNKNOWN, | |||||
]) | ]) | ||||
# Add more peers for triggering the avaproofs messaging | # Add more peers for triggering the avaproofs messaging | ||||
for i in range(2, self.min_avaproofs_node_count - 1): | for i in range(2, self.min_avaproofs_node_count - 1): | ||||
add_avapeer_and_check_status( | add_avapeer_and_check_status( | ||||
peers[i], [ | peers[i], [ | ||||
AvalancheVoteError.ACCEPTED, | AvalancheVoteError.ACCEPTED, | ||||
AvalancheVoteError.UNKNOWN, | AvalancheVoteError.UNKNOWN, | ||||
AvalancheVoteError.UNKNOWN, | |||||
]) | |||||
add_avapeer_and_check_status( | |||||
peers[self.min_avaproofs_node_count - 1], [ | |||||
AvalancheVoteError.ACCEPTED, | |||||
AvalancheVoteError.ACCEPTED, | |||||
AvalancheVoteError.UNKNOWN, | |||||
]) | |||||
self.nodes[2].generate(1) | |||||
assert not self.nodes[2].getblockchaininfo()['initialblockdownload'] | |||||
# The avaproofs message are not accounted during IBD, so this is not | |||||
# enough. | |||||
poll_and_assert_response(self.nodes[2], AvalancheVoteError.UNKNOWN) | |||||
# Connect more peers to reach the message threshold while node 2 is out | |||||
# of IBD. | |||||
for i in range(self.min_avaproofs_node_count - 1): | |||||
add_avapeer_and_check_status( | |||||
peers[i], [ | |||||
AvalancheVoteError.ACCEPTED, | |||||
AvalancheVoteError.ACCEPTED, | |||||
AvalancheVoteError.UNKNOWN, | |||||
]) | ]) | ||||
# The messages are accounted and the node quorum finally valid | |||||
add_avapeer_and_check_status( | add_avapeer_and_check_status( | ||||
peers[self.min_avaproofs_node_count - 1], [ | peers[self.min_avaproofs_node_count - 1], [ | ||||
AvalancheVoteError.ACCEPTED, | AvalancheVoteError.ACCEPTED, | ||||
AvalancheVoteError.ACCEPTED, | AvalancheVoteError.ACCEPTED, | ||||
AvalancheVoteError.ACCEPTED, | |||||
]) | ]) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
AvalancheQuorumTest().main() | AvalancheQuorumTest().main() |