diff --git a/test/functional/abc_p2p_avalanche_policy_minerfund.py b/test/functional/abc_p2p_avalanche_policy_minerfund.py --- a/test/functional/abc_p2p_avalanche_policy_minerfund.py +++ b/test/functional/abc_p2p_avalanche_policy_minerfund.py @@ -5,7 +5,7 @@ """Test the resolution of miner fund changes via avalanche.""" import random -from test_framework.avatools import get_ava_p2p_interface +from test_framework.avatools import can_find_inv_in_poll, get_ava_p2p_interface from test_framework.blocktools import create_block, create_coinbase from test_framework.cashaddr import decode from test_framework.messages import ( @@ -72,40 +72,14 @@ policy_miner_fund_amount = int( block_reward * XEC * MINER_FUND_RATIO / 100) - def can_find_block_in_poll(hash, resp=AvalancheVoteError.ACCEPTED): - found_hash = False - for n in quorum: - poll = n.get_avapoll_if_available() - - # That node has not received a poll - if poll is None: - continue - - # We got a poll, check for the hash and repond - votes = [] - for inv in poll.invs: - # Vote yes to everything - r = AvalancheVoteError.ACCEPTED - - # Look for what we expect - if inv.hash == hash: - r = resp - found_hash = True - - votes.append(AvalancheVote(r, inv.hash)) - - n.send_avaresponse(poll.round, votes, n.delegated_privkey) - - return found_hash - def has_accepted_tip(tip_expected): hash_tip_final = int(tip_expected, 16) - can_find_block_in_poll(hash_tip_final) + can_find_inv_in_poll(quorum, hash_tip_final) return node.getbestblockhash() == tip_expected def has_finalized_tip(tip_expected): hash_tip_final = int(tip_expected, 16) - can_find_block_in_poll(hash_tip_final) + can_find_inv_in_poll(quorum, hash_tip_final) return node.isfinalblock(tip_expected) def create_cb_pay_to_address(address, miner_fund_amount): @@ -198,7 +172,7 @@ reject_hash = int(reject, 16) with node.wait_for_debug_log( [f"Avalanche invalidated block {reject}".encode()], - chatty_callable=lambda: can_find_block_in_poll(reject_hash, AvalancheVoteError.PARKED)): + chatty_callable=lambda: can_find_inv_in_poll(quorum, reject_hash, AvalancheVoteError.PARKED)): pass # Build a block on the accepted tip and the chain continues as normal diff --git a/test/functional/abc_p2p_avalanche_proof_voting.py b/test/functional/abc_p2p_avalanche_proof_voting.py --- a/test/functional/abc_p2p_avalanche_proof_voting.py +++ b/test/functional/abc_p2p_avalanche_proof_voting.py @@ -7,6 +7,7 @@ from test_framework.avatools import ( avalanche_proof_from_hex, + can_find_inv_in_poll, create_coinbase_stakes, gen_proof, get_ava_p2p_interface, @@ -58,32 +59,6 @@ return [get_ava_p2p_interface(self, node, stake_utxo_confirmations=self.avaproof_stake_utxo_confirmations) for _ in range(0, QUORUM_NODE_COUNT)] - def can_find_proof_in_poll(self, hash, response): - found_hash = False - for n in self.quorum: - poll = n.get_avapoll_if_available() - - # That node has not received a poll - if poll is None: - continue - - # We got a poll, check for the hash and repond - votes = [] - for inv in poll.invs: - # Vote yes to everything - r = AvalancheProofVoteResponse.ACTIVE - - # Look for what we expect - if inv.hash == hash: - r = response - found_hash = True - - votes.append(AvalancheVote(r, inv.hash)) - - n.send_avaresponse(poll.round, votes, n.delegated_privkey) - - return found_hash - @staticmethod def send_proof(from_peer, proof_hex): proof = avalanche_proof_from_hex(proof_hex) @@ -93,7 +68,7 @@ def send_and_check_for_polling(self, peer, proof_hex, response=AvalancheProofVoteResponse.ACTIVE): proofid = self.send_proof(peer, proof_hex) - self.wait_until(lambda: self.can_find_proof_in_poll(proofid, response)) + self.wait_until(lambda: can_find_inv_in_poll(self.quorum, proofid, response)) def build_conflicting_proof(self, node, sequence): return node.buildavalancheproof( @@ -102,8 +77,8 @@ def wait_for_invalidated_proof(self, node, proofid): def invalidate_proof(proofid): self.wait_until( - lambda: self.can_find_proof_in_poll( - proofid, response=AvalancheProofVoteResponse.REJECTED)) + lambda: can_find_inv_in_poll(self.quorum, + proofid, response=AvalancheProofVoteResponse.REJECTED)) return try_rpc(-8, "Proof not found", node.getrawavalancheproof, uint256_hex(proofid)) @@ -115,8 +90,8 @@ def wait_for_finalized_proof(self, node, proofid): def finalize_proof(proofid): - self.can_find_proof_in_poll( - proofid, response=AvalancheProofVoteResponse.ACTIVE) + can_find_inv_in_poll(self.quorum, + proofid, response=AvalancheProofVoteResponse.ACTIVE) return node.getrawavalancheproof( uint256_hex(proofid)).get("finalized", False) @@ -242,8 +217,8 @@ self.log.info("Test proof acceptance") def accept_proof(proofid): - self.wait_until(lambda: self.can_find_proof_in_poll( - proofid, response=AvalancheProofVoteResponse.ACTIVE)) + self.wait_until(lambda: can_find_inv_in_poll(self.quorum, + proofid, response=AvalancheProofVoteResponse.ACTIVE)) return proofid in get_proof_ids(node) mock_time += self.conflicting_proof_cooldown @@ -277,8 +252,8 @@ def reject_proof(proofid): self.wait_until( - lambda: self.can_find_proof_in_poll( - proofid, response=AvalancheProofVoteResponse.REJECTED)) + lambda: can_find_inv_in_poll(self.quorum, + proofid, response=AvalancheProofVoteResponse.REJECTED)) return proofid not in get_proof_ids(node) with node.assert_debug_log( @@ -459,8 +434,8 @@ peer, proof_seq1, response=AvalancheProofVoteResponse.UNKNOWN) def vote_until_dropped(proofid): - self.can_find_proof_in_poll( - proofid, response=AvalancheProofVoteResponse.UNKNOWN) + can_find_inv_in_poll(self.quorum, + proofid, response=AvalancheProofVoteResponse.UNKNOWN) return try_rpc(-8, "Proof not found", node.getrawavalancheproof, uint256_hex(proofid)) diff --git a/test/functional/abc_p2p_avalanche_voting.py b/test/functional/abc_p2p_avalanche_voting.py --- a/test/functional/abc_p2p_avalanche_voting.py +++ b/test/functional/abc_p2p_avalanche_voting.py @@ -5,7 +5,7 @@ """Test the resolution of forks via avalanche.""" import random -from test_framework.avatools import get_ava_p2p_interface +from test_framework.avatools import can_find_inv_in_poll, get_ava_p2p_interface from test_framework.key import ECPubKey from test_framework.messages import AvalancheVote, AvalancheVoteError from test_framework.test_framework import BitcoinTestFramework @@ -140,35 +140,9 @@ self.log.info("Trigger polling from the node...") - def can_find_block_in_poll(hash, resp=AvalancheVoteError.ACCEPTED): - found_hash = False - for n in quorum: - poll = n.get_avapoll_if_available() - - # That node has not received a poll - if poll is None: - continue - - # We got a poll, check for the hash and repond - votes = [] - for inv in poll.invs: - # Vote yes to everything - r = AvalancheVoteError.ACCEPTED - - # Look for what we expect - if inv.hash == hash: - r = resp - found_hash = True - - votes.append(AvalancheVote(r, inv.hash)) - - n.send_avaresponse(poll.round, votes, n.delegated_privkey) - - return found_hash - # Now that we have a peer, we should start polling for the tip. hash_tip = int(node.getbestblockhash(), 16) - self.wait_until(lambda: can_find_block_in_poll(hash_tip)) + self.wait_until(lambda: can_find_inv_in_poll(quorum, hash_tip)) # Make sure the fork node has synced the blocks self.sync_blocks([node, fork_node]) @@ -193,7 +167,7 @@ def has_accepted_tip(tip_expected): hash_tip_accept = int(tip_expected, 16) - can_find_block_in_poll(hash_tip_accept) + can_find_inv_in_poll(quorum, hash_tip_accept) return node.getbestblockhash() == tip_expected # Because everybody answers yes, the node will accept that block. @@ -202,7 +176,7 @@ def has_finalized_tip(tip_expected): hash_tip_final = int(tip_expected, 16) - can_find_block_in_poll(hash_tip_final) + can_find_inv_in_poll(quorum, hash_tip_final) return node.isfinalblock(tip_expected) # And continuing to answer yes finalizes the block. @@ -218,8 +192,8 @@ def has_parked_tip(tip_park): hash_tip_park = int(tip_park, 16) - can_find_block_in_poll( - hash_tip_park, AvalancheVoteError.PARKED) + can_find_inv_in_poll(quorum, + hash_tip_park, AvalancheVoteError.PARKED) for tip in node.getchaintips(): if tip["hash"] == tip_park: @@ -244,8 +218,8 @@ hash_tip_park = int(tip_to_park, 16) with node.wait_for_debug_log( [f"Avalanche invalidated block {tip_to_park}".encode()], - chatty_callable=lambda: can_find_block_in_poll( - hash_tip_park, AvalancheVoteError.PARKED) + chatty_callable=lambda: can_find_inv_in_poll(quorum, + hash_tip_park, AvalancheVoteError.PARKED) ): pass diff --git a/test/functional/abc_rpc_isfinal.py b/test/functional/abc_rpc_isfinal.py --- a/test/functional/abc_rpc_isfinal.py +++ b/test/functional/abc_rpc_isfinal.py @@ -7,14 +7,9 @@ from test_framework.address import ADDRESS_ECREG_UNSPENDABLE from test_framework.authproxy import JSONRPCException -from test_framework.avatools import AvaP2PInterface +from test_framework.avatools import AvaP2PInterface, can_find_inv_in_poll from test_framework.blocktools import create_block, create_coinbase -from test_framework.messages import ( - AvalancheVote, - AvalancheVoteError, - CBlockHeader, - msg_headers, -) +from test_framework.messages import CBlockHeader, msg_headers from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, assert_raises_rpc_error, uint256_hex @@ -66,40 +61,13 @@ return node.getavalancheinfo()['ready_to_poll'] is True self.wait_until(is_quorum_established) - def can_find_block_in_poll( - blockhash, resp=AvalancheVoteError.ACCEPTED): - found_hash = False - for n in quorum: - poll = n.get_avapoll_if_available() - - # That node has not received a poll - if poll is None: - continue - - # We got a poll, check for the hash and repond - votes = [] - for inv in poll.invs: - # Vote yes to everything - r = AvalancheVoteError.ACCEPTED - - # Look for what we expect - if inv.hash == int(blockhash, 16): - r = resp - found_hash = True - - votes.append(AvalancheVote(r, inv.hash)) - - n.send_avaresponse(poll.round, votes, n.delegated_privkey) - - return found_hash - blockhash = self.generate(node, 1, sync_fun=self.no_op)[0] cb_txid = node.getblock(blockhash)['tx'][0] assert not node.isfinalblock(blockhash) assert not node.isfinaltransaction(cb_txid, blockhash) def is_finalblock(blockhash): - can_find_block_in_poll(blockhash) + can_find_inv_in_poll(quorum, int(blockhash, 16)) return node.isfinalblock(blockhash) with node.assert_debug_log([f"Avalanche finalized block {blockhash}"]): diff --git a/test/functional/test_framework/avatools.py b/test/functional/test_framework/avatools.py --- a/test/functional/test_framework/avatools.py +++ b/test/functional/test_framework/avatools.py @@ -18,6 +18,8 @@ AvalancheDelegation, AvalancheProof, AvalancheResponse, + AvalancheVote, + AvalancheVoteError, CInv, CTransaction, FromHex, @@ -428,3 +430,30 @@ proof.proofid) for proof in proofs] return msg + + +def can_find_inv_in_poll(quorum, hash, response=AvalancheVoteError.ACCEPTED): + found_hash = False + for n in quorum: + poll = n.get_avapoll_if_available() + + # That node has not received a poll + if poll is None: + continue + + # We got a poll, check for the hash and repond + votes = [] + for inv in poll.invs: + # Vote yes to everything + r = AvalancheVoteError.ACCEPTED + + # Look for what we expect + if inv.hash == hash: + r = response + found_hash = True + + votes.append(AvalancheVote(r, inv.hash)) + + n.send_avaresponse(poll.round, votes, n.delegated_privkey) + + return found_hash