Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche_quorum.py
Show All 14 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 | ||||
from test_framework.wallet_util import bytes_to_wif | from test_framework.wallet_util import bytes_to_wif | ||||
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 = 1 | self.num_nodes = 3 | ||||
self.extra_args = [ | |||||
['-enableavalanche=1', | self.extra_args = [['-enableavalanche=1', | ||||
'-avacooldown=0', | '-avacooldown=0', | ||||
'-avatimeout=0', | '-avatimeout=0', | ||||
'-avaminquorumstake=100000000', | '-avaminquorumstake=100000000', | ||||
'-avaminquorumconnectedstakeratio=0.8'] | '-avaminquorumconnectedstakeratio=0.8']] | ||||
] | |||||
# Nodes 2 and 3 are a single peer | |||||
self.extra_args.extend(2 * [['-enableavalanche=1', | |||||
'-avacooldown=0', | |||||
'-avatimeout=0', | |||||
'-avaminquorumstake=100000000', | |||||
'-avaminquorumconnectedstakeratio=0.8', | |||||
'-avamasterkey=cPaKTtT3Nxk5E8uERSqnDiDSSnCSZPP6qa4AiipQb2ETgYukADtR', | |||||
'-avaproof=0000000000000000000000000000000021025582a9ca9e57a560306c07b2ed2124fa97a14969f449106747e91490d30012c501b123754aaeb592ae6282bc169b3a68a92d9fca6afa1ad6aaaa5e323f4684304c000000000000c16ff2862300030000002103e6aefd9321197f88f23d0f4ffe18b84d4997998ca0da9b7097399aef8433b1e018473378520efbd5f64ea867675665cc8fbdbe953bc7e77bcbe47c4505d85c1037026b42d00d9e439aef0112d6fb3fa66cc55031daeddd722ba485cd91206d71']]) | |||||
def mock_forward(self, delta): | def mock_forward(self, delta): | ||||
self.mock_time += delta | self.mock_time += delta | ||||
self.nodes[0].setmocktime(self.mock_time) | self.nodes[0].setmocktime(self.mock_time) | ||||
def run_test(self): | def run_test(self): | ||||
self.mock_time = int(time()) | self.mock_time = int(time()) | ||||
self.mock_forward(0) | self.mock_forward(0) | ||||
# Create a local node to poll from and a helper to send polls from it | # Create a local node to poll from and a helper to send polls from it | ||||
# and assert on the response | # and assert on the response | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
poll_node = get_ava_p2p_interface(node) | poll_node = get_ava_p2p_interface(node) | ||||
poll_node_pubkey = ECPubKey() | poll_node_pubkey = ECPubKey() | ||||
poll_node_pubkey.set(bytes.fromhex(node.getavalanchekey())) | poll_node_pubkey.set(bytes.fromhex(node.getavalanchekey())) | ||||
def poll_and_assert_response(expected): | def poll_and_assert_response( | ||||
expected, poll_node=poll_node, pubkey=poll_node_pubkey): | |||||
# Send poll for best block | # Send poll for best block | ||||
block = int(node.getbestblockhash(), 16) | block = int(node.getbestblockhash(), 16) | ||||
poll_node.send_poll([block]) | poll_node.send_poll([block]) | ||||
# Get response and check that the vote is what we expect | # Get response and check that the vote is what we expect | ||||
response = poll_node.wait_for_avaresponse() | response = poll_node.wait_for_avaresponse() | ||||
r = response.response | r = response.response | ||||
assert poll_node_pubkey.verify_schnorr(response.sig, r.get_hash()) | assert pubkey.verify_schnorr(response.sig, r.get_hash()) | ||||
assert_equal(len(r.votes), 1) | assert_equal(len(r.votes), 1) | ||||
actual = repr(r.votes[0]) | actual = repr(r.votes[0]) | ||||
expected = repr(AvalancheVote(expected, block)) | expected = repr(AvalancheVote(expected, block)) | ||||
assert_equal(actual, expected) | assert_equal(actual, expected) | ||||
# Create peers to poll | # Create peers to poll | ||||
num_quorum_peers = 2 | num_quorum_peers = 2 | ||||
Show All 37 Lines | def run_test(self): | ||||
peers[1]['node'].wait_for_disconnect() | peers[1]['node'].wait_for_disconnect() | ||||
poll_and_assert_response(AvalancheVoteError.ACCEPTED) | poll_and_assert_response(AvalancheVoteError.ACCEPTED) | ||||
# Reconnect node and re-establish quorum | # Reconnect node and re-establish quorum | ||||
peers[1]['node'] = get_ava_p2p_interface(node) | peers[1]['node'] = get_ava_p2p_interface(node) | ||||
addavalanchenode(peers[1]) | addavalanchenode(peers[1]) | ||||
poll_and_assert_response(AvalancheVoteError.ACCEPTED) | poll_and_assert_response(AvalancheVoteError.ACCEPTED) | ||||
# Nodes 2 and 3 represent the same peer, and their own stake is required | |||||
# to form a quorum. Even though they don't connect to each other they | |||||
# are active due to their own local stakes. | |||||
for node in [self.nodes[1], self.nodes[2]]: | |||||
info = node.getavalancheinfo() | |||||
assert info['active'] | |||||
assert_equal(info['network']['node_count'], 0) | |||||
poll_node = get_ava_p2p_interface(node) | |||||
pubkey = ECPubKey() | |||||
pubkey.set(bytes.fromhex(node.getavalanchekey())) | |||||
poll_and_assert_response( | |||||
AvalancheVoteError.ACCEPTED, poll_node, pubkey) | |||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
AvalancheQuorumTest().main() | AvalancheQuorumTest().main() |