Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche_proof_voting.py
Show All 11 Lines | from test_framework.avatools import ( | ||||
get_ava_p2p_interface, | get_ava_p2p_interface, | ||||
get_proof_ids, | get_proof_ids, | ||||
) | ) | ||||
from test_framework.key import ECPubKey | from test_framework.key import ECPubKey | ||||
from test_framework.messages import ( | from test_framework.messages import ( | ||||
MSG_AVA_PROOF, | MSG_AVA_PROOF, | ||||
AvalancheProofVoteResponse, | AvalancheProofVoteResponse, | ||||
AvalancheVote, | AvalancheVote, | ||||
AvalancheVoteError, | |||||
) | ) | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_greater_than, | assert_greater_than, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
try_rpc, | try_rpc, | ||||
) | ) | ||||
Show All 37 Lines | def can_find_proof_in_poll(self, hash, response): | ||||
# That node has not received a poll | # That node has not received a poll | ||||
if poll is None: | if poll is None: | ||||
continue | continue | ||||
# We got a poll, check for the hash and repond | # We got a poll, check for the hash and repond | ||||
votes = [] | votes = [] | ||||
for inv in poll.invs: | for inv in poll.invs: | ||||
# Vote yes to everything | # Vote yes to everything | ||||
r = AvalancheVoteError.ACCEPTED | r = AvalancheProofVoteResponse.ACTIVE | ||||
# Look for what we expect | # Look for what we expect | ||||
if inv.hash == hash: | if inv.hash == hash: | ||||
r = response | r = response | ||||
found_hash = True | found_hash = True | ||||
votes.append(AvalancheVote(r, inv.hash)) | votes.append(AvalancheVote(r, inv.hash)) | ||||
n.send_avaresponse(poll.round, votes, self.privkey) | n.send_avaresponse(poll.round, votes, self.privkey) | ||||
return found_hash | return found_hash | ||||
@staticmethod | @staticmethod | ||||
def send_proof(from_peer, proof_hex): | def send_proof(from_peer, proof_hex): | ||||
proof = avalanche_proof_from_hex(proof_hex) | proof = avalanche_proof_from_hex(proof_hex) | ||||
from_peer.send_avaproof(proof) | from_peer.send_avaproof(proof) | ||||
return proof.proofid | return proof.proofid | ||||
def send_and_check_for_polling(self, peer, | def send_and_check_for_polling(self, peer, | ||||
proof_hex, response=AvalancheVoteError.ACCEPTED): | proof_hex, response=AvalancheProofVoteResponse.ACTIVE): | ||||
proofid = self.send_proof(peer, proof_hex) | proofid = self.send_proof(peer, proof_hex) | ||||
self.wait_until(lambda: self.can_find_proof_in_poll(proofid, response)) | self.wait_until(lambda: self.can_find_proof_in_poll(proofid, response)) | ||||
def build_conflicting_proof(self, node, sequence): | def build_conflicting_proof(self, node, sequence): | ||||
return node.buildavalancheproof( | return node.buildavalancheproof( | ||||
sequence, 0, self.privkey_wif, self.conflicting_stakes) | sequence, 0, self.privkey_wif, self.conflicting_stakes) | ||||
def run_test(self): | def run_test(self): | ||||
▲ Show 20 Lines • Show All 58 Lines • ▼ Show 20 Lines | def poll_tests(self, node): | ||||
with node.assert_debug_log(["Not polling the avalanche proof (cooldown-not-elapsed)"]): | with node.assert_debug_log(["Not polling the avalanche proof (cooldown-not-elapsed)"]): | ||||
peer.send_avaproof(avalanche_proof_from_hex(proof_seq40)) | peer.send_avaproof(avalanche_proof_from_hex(proof_seq40)) | ||||
self.log.info( | self.log.info( | ||||
"Check we poll for conflicting proof if the proof is not the favorite") | "Check we poll for conflicting proof if the proof is not the favorite") | ||||
mock_time += self.conflicting_proof_cooldown | mock_time += self.conflicting_proof_cooldown | ||||
node.setmocktime(mock_time) | node.setmocktime(mock_time) | ||||
self.send_and_check_for_polling( | self.send_and_check_for_polling( | ||||
peer, proof_seq20, response=AvalancheVoteError.INVALID) | peer, proof_seq20, response=AvalancheProofVoteResponse.REJECTED) | ||||
self.log.info( | self.log.info( | ||||
"Check we poll for conflicting proof if the proof is the favorite") | "Check we poll for conflicting proof if the proof is the favorite") | ||||
mock_time += self.conflicting_proof_cooldown | mock_time += self.conflicting_proof_cooldown | ||||
node.setmocktime(mock_time) | node.setmocktime(mock_time) | ||||
self.send_and_check_for_polling(peer, proof_seq40) | self.send_and_check_for_polling(peer, proof_seq40) | ||||
mock_time += self.conflicting_proof_cooldown | mock_time += self.conflicting_proof_cooldown | ||||
Show All 34 Lines | def update_tests(self, node): | ||||
assert proofid_seq40 in get_proof_ids(node) | assert proofid_seq40 in get_proof_ids(node) | ||||
assert proofid_seq30 not in get_proof_ids(node) | assert proofid_seq30 not in get_proof_ids(node) | ||||
self.log.info("Test proof acceptance") | self.log.info("Test proof acceptance") | ||||
def accept_proof(proofid): | def accept_proof(proofid): | ||||
self.wait_until(lambda: self.can_find_proof_in_poll( | self.wait_until(lambda: self.can_find_proof_in_poll( | ||||
proofid, response=AvalancheVoteError.ACCEPTED), timeout=5) | proofid, response=AvalancheProofVoteResponse.ACTIVE), timeout=5) | ||||
return proofid in get_proof_ids(node) | return proofid in get_proof_ids(node) | ||||
mock_time += self.conflicting_proof_cooldown | mock_time += self.conflicting_proof_cooldown | ||||
node.setmocktime(mock_time) | node.setmocktime(mock_time) | ||||
self.send_and_check_for_polling(peer, proof_seq30) | self.send_and_check_for_polling(peer, proof_seq30) | ||||
# Let the quorum vote for it | # Let the quorum vote for it | ||||
self.wait_until(lambda: accept_proof(proofid_seq30)) | self.wait_until(lambda: accept_proof(proofid_seq30)) | ||||
assert proofid_seq40 not in get_proof_ids(node) | assert proofid_seq40 not in get_proof_ids(node) | ||||
self.log.info("Test the peer replacement rate limit") | self.log.info("Test the peer replacement rate limit") | ||||
# Wait until proof_seq30 is finalized | # Wait until proof_seq30 is finalized | ||||
retry = 5 | retry = 5 | ||||
while retry > 0: | while retry > 0: | ||||
try: | try: | ||||
with node.assert_debug_log([f"Avalanche finalized proof {proofid_seq30:0{64}x}"]): | with node.assert_debug_log([f"Avalanche finalized proof {proofid_seq30:0{64}x}"]): | ||||
self.wait_until(lambda: not self.can_find_proof_in_poll( | self.wait_until(lambda: not self.can_find_proof_in_poll( | ||||
proofid_seq30, response=AvalancheVoteError.ACCEPTED)) | proofid_seq30, response=AvalancheProofVoteResponse.ACTIVE)) | ||||
break | break | ||||
except AssertionError: | except AssertionError: | ||||
retry -= 1 | retry -= 1 | ||||
assert_greater_than(retry, 0) | assert_greater_than(retry, 0) | ||||
# Not enough | # Not enough | ||||
assert self.conflicting_proof_cooldown < self.peer_replacement_cooldown | assert self.conflicting_proof_cooldown < self.peer_replacement_cooldown | ||||
Show All 12 Lines | def update_tests(self, node): | ||||
self.send_proof(peer, proof_seq50) | self.send_proof(peer, proof_seq50) | ||||
self.wait_until(lambda: proofid_seq50 in get_proof_ids(node)) | self.wait_until(lambda: proofid_seq50 in get_proof_ids(node)) | ||||
assert proofid_seq40 not in get_proof_ids(node) | assert proofid_seq40 not in get_proof_ids(node) | ||||
def reject_proof(proofid): | def reject_proof(proofid): | ||||
self.wait_until( | self.wait_until( | ||||
lambda: self.can_find_proof_in_poll( | lambda: self.can_find_proof_in_poll( | ||||
proofid, response=AvalancheVoteError.INVALID)) | proofid, response=AvalancheProofVoteResponse.REJECTED)) | ||||
return proofid not in get_proof_ids(node) | return proofid not in get_proof_ids(node) | ||||
self.wait_until(lambda: reject_proof(proofid_seq50)) | self.wait_until(lambda: reject_proof(proofid_seq50)) | ||||
assert proofid_seq50 not in get_proof_ids(node) | assert proofid_seq50 not in get_proof_ids(node) | ||||
assert proofid_seq40 in get_proof_ids(node) | assert proofid_seq40 in get_proof_ids(node) | ||||
self.log.info("Test proof invalidation") | self.log.info("Test proof invalidation") | ||||
def invalidate_proof(proofid): | def invalidate_proof(proofid): | ||||
self.wait_until( | self.wait_until( | ||||
lambda: self.can_find_proof_in_poll( | lambda: self.can_find_proof_in_poll( | ||||
proofid, response=AvalancheVoteError.INVALID)) | proofid, response=AvalancheProofVoteResponse.REJECTED)) | ||||
return try_rpc(-8, "Proof not found", | return try_rpc(-8, "Proof not found", | ||||
node.getrawavalancheproof, f"{proofid:0{64}x}") | node.getrawavalancheproof, f"{proofid:0{64}x}") | ||||
self.wait_until(lambda: invalidate_proof(proofid_seq50)) | self.wait_until(lambda: invalidate_proof(proofid_seq50)) | ||||
self.log.info("The node will now ignore the invalid proof") | self.log.info("The node will now ignore the invalid proof") | ||||
for i in range(5): | for i in range(5): | ||||
▲ Show 20 Lines • Show All 130 Lines • Show Last 20 Lines |