Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche.py
Show First 20 Lines • Show All 187 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
# Make sure the fork node has synced the blocks | # Make sure the fork node has synced the blocks | ||||
self.sync_blocks([node, fork_node]) | self.sync_blocks([node, fork_node]) | ||||
# Create a fork 2 blocks deep. This should trigger polling. | # Create a fork 2 blocks deep. This should trigger polling. | ||||
fork_node.invalidateblock(fork_node.getblockhash(100)) | fork_node.invalidateblock(fork_node.getblockhash(100)) | ||||
fork_address = fork_node.get_deterministic_priv_key().address | fork_address = fork_node.get_deterministic_priv_key().address | ||||
fork_node.generatetoaddress(2, fork_address) | fork_node.generatetoaddress(2, fork_address) | ||||
def can_find_block_in_poll(hash): | # Because the new tip is a deep reorg, the node will not accept it | ||||
# right away, but poll for it. | |||||
def parked_block(blockhash): | |||||
for tip in node.getchaintips(): | |||||
if tip["hash"] == blockhash: | |||||
assert tip["status"] != "active" | |||||
return tip["status"] == "parked" | |||||
return False | |||||
fork_tip = fork_node.getbestblockhash() | |||||
wait_until(lambda: parked_block(fork_tip)) | |||||
self.log.info("Answer all polls to finalize...") | |||||
def can_find_block_in_poll(hash, resp): | |||||
found_hash = False | found_hash = False | ||||
for n in quorum: | for n in quorum: | ||||
poll = n.get_avapoll_if_available() | poll = n.get_avapoll_if_available() | ||||
# 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 | |||||
r = BLOCK_ACCEPTED | |||||
# Look for what we expect | # Look for what we expect | ||||
if inv.hash == hash: | if inv.hash == hash: | ||||
r = resp | |||||
found_hash = True | found_hash = True | ||||
# Vote yes to everything | |||||
votes.append(AvalancheVote(BLOCK_ACCEPTED, inv.hash)) | votes.append(AvalancheVote(r, inv.hash)) | ||||
n.send_avaresponse(poll.round, votes, privkey) | n.send_avaresponse(poll.round, votes, privkey) | ||||
return found_hash | return found_hash | ||||
# Because the new tip is a deep reorg, the node should start to poll | hash_to_find = int(fork_tip, 16) | ||||
# for it. | |||||
hash_to_find = int(fork_node.getbestblockhash(), 16) | def has_accepted_new_tip(): | ||||
wait_until(lambda: can_find_block_in_poll(hash_to_find), timeout=5) | can_find_block_in_poll(hash_to_find, BLOCK_ACCEPTED) | ||||
return node.getbestblockhash() == fork_tip | |||||
# To verify that responses are processed, do it a few more times. | |||||
for _ in range(10): | # Because everybody answers yes, the node will accept that block. | ||||
wait_until(lambda: can_find_block_in_poll(hash_to_find), timeout=5) | wait_until(has_accepted_new_tip, timeout=15) | ||||
assert_equal(node.getbestblockhash(), fork_tip) | |||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
AvalancheTest().main() | AvalancheTest().main() |