diff --git a/test/functional/abc_feature_proof_cleanup.py b/test/functional/abc_feature_proof_cleanup.py --- a/test/functional/abc_feature_proof_cleanup.py +++ b/test/functional/abc_feature_proof_cleanup.py @@ -11,10 +11,10 @@ from test_framework.avatools import ( gen_proof, get_ava_p2p_interface, + get_ava_p2p_interface_no_handshake, get_proof_ids, wait_for_proof, ) -from test_framework.key import ECKey from test_framework.test_framework import BitcoinTestFramework from test_framework.util import ( assert_equal, @@ -61,16 +61,9 @@ peers = [] # The first 5 peers have a node attached for _ in range(5): - key, proof = gen_proof(node) - peer = get_ava_p2p_interface(node) - node.addavalanchenode( - peer.nodeid, - key.get_pubkey().get_bytes().hex(), - proof.serialize().hex()) - - proofs.append(proof) - keys.append(key) + proofs.append(peer.proof) + keys.append(peer.master_privkey) peers.append(peer) # The last 5 peers have no node attached @@ -117,7 +110,7 @@ self.log.info("Check the cleaned up proofs are no longer accepted...") - sender = get_ava_p2p_interface(node) + sender = get_ava_p2p_interface_no_handshake(node) for proof in proofs[1:]: with node.assert_debug_log(["dangling-proof"]): sender.send_avaproof(proof) @@ -132,26 +125,11 @@ assert_equal(len(node.p2ps), 0) avanode = get_ava_p2p_interface(node) - - avanode_key = keys[1] - avanode_proof = proofs[1] - - delegated_key = ECKey() - delegated_key.generate() - - delegation = node.delegateavalancheproof( - f"{avanode_proof.limited_proofid:064x}", - bytes_to_wif(avanode_key.get_bytes()), - delegated_key.get_pubkey().get_bytes().hex(), - ) - - avanode.send_avahello(delegation, delegated_key) - avanode.sync_with_ping() avanode.wait_until(lambda: avanode.last_message.get( - "getdata") and avanode.last_message["getdata"].inv[-1].hash == avanode_proof.proofid) + "getdata") and avanode.last_message["getdata"].inv[-1].hash == avanode.proof.proofid) - avanode.send_avaproof(avanode_proof) - self.wait_until(lambda: avanode_proof.proofid in get_proof_ids(node)) + avanode.send_avaproof(avanode.proof) + self.wait_until(lambda: avanode.proof.proofid in get_proof_ids(node)) if __name__ == '__main__': diff --git a/test/functional/abc_p2p_avalanche_peer_discovery.py b/test/functional/abc_p2p_avalanche_peer_discovery.py --- a/test/functional/abc_p2p_avalanche_peer_discovery.py +++ b/test/functional/abc_p2p_avalanche_peer_discovery.py @@ -16,7 +16,7 @@ avalanche_proof_from_hex, create_coinbase_stakes, gen_proof, - get_ava_p2p_interface, + get_ava_p2p_interface_no_handshake, get_proof_ids, wait_for_proof, ) @@ -83,7 +83,7 @@ self.log.info("Test the avahello signature with no proof") - peer = get_ava_p2p_interface(node) + peer = get_ava_p2p_interface_no_handshake(node) avahello = peer.wait_for_avahello().hello assert_equal(avahello.delegation.limited_proofid, 0) @@ -113,7 +113,7 @@ # Restart the node with the given args self.restart_node(0, self.extra_args[0] + args) - peer = get_ava_p2p_interface(node) + peer = get_ava_p2p_interface_no_handshake(node) avahello = peer.wait_for_avahello().hello @@ -162,7 +162,7 @@ None) self.log.info("Test that wrong avahello signature causes a ban") - bad_interface = get_ava_p2p_interface(node) + bad_interface = get_ava_p2p_interface_no_handshake(node) wrong_key = ECKey() wrong_key.generate() with node.assert_debug_log( @@ -173,7 +173,7 @@ self.log.info( 'Check that receiving a valid avahello triggers a proof getdata request') - good_interface = get_ava_p2p_interface(node) + good_interface = get_ava_p2p_interface_no_handshake(node) proofid = good_interface.send_avahello( interface_delegation_hex, delegated_key) @@ -218,7 +218,7 @@ self.log.info( "The proof has not been announced, it cannot be requested") - peer = get_ava_p2p_interface(node, services=NODE_NETWORK) + peer = get_ava_p2p_interface_no_handshake(node, services=NODE_NETWORK) # Build a new proof and only announce this one _, new_proof_obj = gen_proof(node) @@ -257,7 +257,7 @@ assert_equal(len(node.getavalanchepeerinfo()), 1) assert_equal(node.getavalanchepeerinfo()[0]["proof"], proof) - peer = get_ava_p2p_interface(node) + peer = get_ava_p2p_interface_no_handshake(node) peer_proofid = peer.send_avahello( interface_delegation_hex, delegated_key) @@ -280,7 +280,7 @@ "Check that the peer gets added immediately if the proof is already known") # Connect another peer using the same proof - peer_proof_known = get_ava_p2p_interface(node) + peer_proof_known = get_ava_p2p_interface_no_handshake(node) peer_proof_known.send_avahello(interface_delegation_hex, delegated_key) self.wait_until(lambda: has_node_count(2)) @@ -312,7 +312,8 @@ self.log.info( "Check the node sends an avahello message to all peers even if the avalanche service bit is not advertised") for _ in range(3): - nonavapeer = get_ava_p2p_interface(node, services=NODE_NETWORK) + nonavapeer = get_ava_p2p_interface_no_handshake( + node, services=NODE_NETWORK) nonavapeer.wait_for_avahello() 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 @@ -12,7 +12,7 @@ get_ava_p2p_interface, get_proof_ids, ) -from test_framework.key import ECPubKey +from test_framework.key import ECKey, ECPubKey from test_framework.messages import ( MSG_AVA_PROOF, AvalancheProofVoteResponse, @@ -34,13 +34,14 @@ def set_test_params(self): self.setup_clean_chain = True self.num_nodes = 1 + self.avaproof_stake_utxo_confirmations = 1 self.conflicting_proof_cooldown = 100 self.peer_replacement_cooldown = 2000 self.extra_args = [ [ '-avalanche=1', '-avaproofstakeutxodustthreshold=1000000', - '-avaproofstakeutxoconfirmations=1', + f'-avaproofstakeutxoconfirmations={self.avaproof_stake_utxo_confirmations}', f'-avalancheconflictingproofcooldown={self.conflicting_proof_cooldown}', f'-avalanchepeerreplacementcooldown={self.peer_replacement_cooldown}', '-avacooldown=0', @@ -55,18 +56,8 @@ # Build a fake quorum of nodes. def get_quorum(self, node): - quorum = [get_ava_p2p_interface(node) - for _ in range(0, QUORUM_NODE_COUNT)] - - for n in quorum: - success = node.addavalanchenode( - n.nodeid, - self.privkey.get_pubkey().get_bytes().hex(), - self.quorum_proof.serialize().hex(), - ) - assert success is True - - return quorum + return [get_ava_p2p_interface(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 @@ -90,7 +81,7 @@ votes.append(AvalancheVote(r, inv.hash)) - n.send_avaresponse(poll.round, votes, self.privkey) + n.send_avaresponse(poll.round, votes, n.delegated_privkey) return found_hash @@ -112,13 +103,14 @@ def run_test(self): node = self.nodes[0] - self.privkey, self.quorum_proof = gen_proof(node) - self.privkey_wif = bytes_to_wif(self.privkey.get_bytes()) + privkey = ECKey() + privkey.generate() + self.privkey_wif = bytes_to_wif(privkey.get_bytes()) self.quorum = self.get_quorum(node) addrkey0 = node.get_deterministic_priv_key() - blockhash = node.generatetoaddress(10, addrkey0.address) + blockhash = node.generatetoaddress(9, addrkey0.address) self.conflicting_stakes = create_coinbase_stakes( node, blockhash[5:9], addrkey0.key) @@ -190,12 +182,12 @@ # Restart the node to get rid of in-flight requests self.restart_node(0) - mock_time = int(time.time()) - node.setmocktime(mock_time) - self.quorum = self.get_quorum(node) peer = get_ava_p2p_interface(node) + mock_time = int(time.time()) + node.setmocktime(mock_time) + proof_seq30 = self.build_conflicting_proof(node, 30) proof_seq40 = self.build_conflicting_proof(node, 40) proof_seq50 = self.build_conflicting_proof(node, 50) @@ -293,10 +285,13 @@ node.getrawavalancheproof, uint256_hex(proofid_seq50)) + node.setmocktime(0) + def vote_tests(self, node): + self.avaproof_stake_utxo_confirmations = 2 self.restart_node(0, extra_args=['-avalanche=1', '-avaproofstakeutxodustthreshold=1000000', - '-avaproofstakeutxoconfirmations=2', + f'-avaproofstakeutxoconfirmations={self.avaproof_stake_utxo_confirmations}', '-avacooldown=0', '-avalancheconflictingproofcooldown=0', '-avaminquorumstake=0', @@ -304,8 +299,8 @@ '-whitelist=noban@127.0.0.1', ]) self.get_quorum(node) - - ava_node = get_ava_p2p_interface(node) + ava_node = get_ava_p2p_interface( + node, stake_utxo_confirmations=self.avaproof_stake_utxo_confirmations) # Generate coinbases to use for stakes stakes_key = node.get_deterministic_priv_key() @@ -422,12 +417,12 @@ # Restart the node to get rid of in-flight requests self.restart_node(0) - mock_time = int(time.time()) - node.setmocktime(mock_time) - self.quorum = self.get_quorum(node) peer = get_ava_p2p_interface(node) + mock_time = int(time.time()) + node.setmocktime(mock_time) + proof_seq1 = self.build_conflicting_proof(node, 1) proof_seq2 = self.build_conflicting_proof(node, 2) proofid_seq1 = avalanche_proof_from_hex(proof_seq1).proofid @@ -465,12 +460,15 @@ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proofid_seq1), AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proofid_seq2)]) + node.setmocktime(0) + def maturity_poll_tests(self, node): # Restart the node with appropriate flags for this test + self.avaproof_stake_utxo_confirmations = 2 self.restart_node(0, extra_args=[ '-avalanche=1', '-avaproofstakeutxodustthreshold=1000000', - '-avaproofstakeutxoconfirmations=2', + f'-avaproofstakeutxoconfirmations={self.avaproof_stake_utxo_confirmations}', '-avalancheconflictingproofcooldown=0', '-avacooldown=0', '-avaminquorumstake=0', @@ -479,7 +477,8 @@ ]) self.quorum = self.get_quorum(node) - peer = get_ava_p2p_interface(node) + peer = get_ava_p2p_interface( + node, stake_utxo_confirmations=self.avaproof_stake_utxo_confirmations) _, immature_proof = gen_proof(node) diff --git a/test/functional/abc_p2p_avalanche_quorum.py b/test/functional/abc_p2p_avalanche_quorum.py --- a/test/functional/abc_p2p_avalanche_quorum.py +++ b/test/functional/abc_p2p_avalanche_quorum.py @@ -8,7 +8,7 @@ AvaP2PInterface, build_msg_avaproofs, gen_proof, - get_ava_p2p_interface, + get_ava_p2p_interface_no_handshake, get_proof_ids, wait_for_proof, ) @@ -50,10 +50,9 @@ # Initially all nodes start with 8 nodes attached to a single proof privkey, proof = gen_proof(self.nodes[0]) for node in self.nodes: - quorum = [get_ava_p2p_interface(node) - for _ in range(0, 8)] + for _ in range(8): + n = get_ava_p2p_interface_no_handshake(node) - for n in quorum: success = node.addavalanchenode( n.nodeid, privkey.get_pubkey().get_bytes().hex(), @@ -82,7 +81,8 @@ assert self.nodes[2].getblockchaininfo()['initialblockdownload'] # Build polling nodes - pollers = [get_ava_p2p_interface(node) for node in self.nodes] + pollers = [get_ava_p2p_interface_no_handshake( + node) for node in self.nodes] def poll_and_assert_response(node, expected): pubkey = ECPubKey() diff --git a/test/functional/abc_p2p_avalanche_transaction_voting.py b/test/functional/abc_p2p_avalanche_transaction_voting.py --- a/test/functional/abc_p2p_avalanche_transaction_voting.py +++ b/test/functional/abc_p2p_avalanche_transaction_voting.py @@ -17,7 +17,9 @@ def set_test_params(self): self.num_nodes = 1 self.extra_args = [['-avalanche=1', - '-avaproofstakeutxoconfirmations=1']] + '-avaproofstakeutxoconfirmations=1', + '-avaproofstakeutxodustthreshold=25000000', + ]] def run_test(self): node = self.nodes[0] 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,15 +5,11 @@ """Test the resolution of forks via avalanche.""" import random -from test_framework.avatools import ( - create_coinbase_stakes, - get_ava_p2p_interface, -) -from test_framework.key import ECKey, ECPubKey +from test_framework.avatools import get_ava_p2p_interface +from test_framework.key import ECPubKey from test_framework.messages import AvalancheVote, AvalancheVoteError from test_framework.test_framework import BitcoinTestFramework from test_framework.util import assert_equal, uint256_hex -from test_framework.wallet_util import bytes_to_wif QUORUM_NODE_COUNT = 16 @@ -30,6 +26,7 @@ '-avacooldown=0', '-avaminquorumstake=0', '-avaminavaproofsnodecount=0', + '-whitelist=noban@127.0.0.1', ], [ '-avalanche=1', @@ -38,7 +35,8 @@ '-avaminquorumstake=0', '-avaminavaproofsnodecount=0', '-noparkdeepreorg', - '-maxreorgdepth=-1' + '-maxreorgdepth=-1', + '-whitelist=noban@127.0.0.1', ], ] self.supports_cli = False @@ -56,29 +54,10 @@ quorum = get_quorum() poll_node = quorum[0] + assert node.getavalancheinfo()['ready_to_poll'] is True + # Generate many block and poll for them. - addrkey0 = node.get_deterministic_priv_key() - blockhashes = node.generatetoaddress(100, addrkey0.address) - # Use the first coinbase to create a stake - stakes = create_coinbase_stakes(node, [blockhashes[0]], addrkey0.key) - - # duplicate the deterministic sig test from src/test/key_tests.cpp - privkey = ECKey() - privkey.set(bytes.fromhex( - "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747"), True) - - proof_sequence = 11 - proof_expiration = 0 - proof = node.buildavalancheproof( - proof_sequence, proof_expiration, bytes_to_wif( - privkey.get_bytes()), - stakes) - - # Activate the quorum. - for n in quorum: - success = node.addavalanchenode( - n.nodeid, privkey.get_pubkey().get_bytes().hex(), proof) - assert success is True + node.generate(100 - node.getblockcount()) fork_node = self.nodes[1] # Make sure the fork node has synced the blocks @@ -179,7 +158,7 @@ votes.append(AvalancheVote(r, inv.hash)) - n.send_avaresponse(poll.round, votes, privkey) + n.send_avaresponse(poll.round, votes, n.delegated_privkey) return found_hash @@ -241,7 +220,7 @@ ['Misbehaving', 'peer=1 (0 -> 2): unexpected-ava-response']): # unknown voting round poll_node.send_avaresponse( - round=2**32 - 1, votes=[], privkey=privkey) + round=2**32 - 1, votes=[], privkey=poll_node.delegated_privkey) if __name__ == '__main__': diff --git a/test/functional/abc_p2p_compactproofs.py b/test/functional/abc_p2p_compactproofs.py --- a/test/functional/abc_p2p_compactproofs.py +++ b/test/functional/abc_p2p_compactproofs.py @@ -160,17 +160,11 @@ services=NODE_NETWORK | NODE_AVALANCHE, ) p2p_idx += 1 - responding_outbound_avapeer_id = node.getpeerinfo()[-1]['id'] outbound_avapeers.append(responding_outbound_avapeer) self.wait_until(all_peers_received_getavaproofs) - # Register as an avalanche node for the avaproofs message to be counted - key, proof = gen_proof(node) - assert node.addavalanchenode( - responding_outbound_avapeer_id, - key.get_pubkey().get_bytes().hex(), - proof.serialize().hex()) + _, proof = gen_proof(node) # Send the avaproofs message avaproofs = build_msg_avaproofs([proof]) diff --git a/test/functional/abc_rpc_getavalancheinfo.py b/test/functional/abc_rpc_getavalancheinfo.py --- a/test/functional/abc_rpc_getavalancheinfo.py +++ b/test/functional/abc_rpc_getavalancheinfo.py @@ -12,7 +12,7 @@ avalanche_proof_from_hex, create_coinbase_stakes, gen_proof, - get_ava_p2p_interface, + get_ava_p2p_interface_no_handshake, wait_for_proof, ) from test_framework.key import ECKey @@ -106,7 +106,7 @@ # Make sure receiving our own proof from the network before validating # the local proof doesn't change our proof count. - sender = get_ava_p2p_interface(node) + sender = get_ava_p2p_interface_no_handshake(node) sender.send_avaproof(proof) # Make sure getting the proof via RPC doesn't change our proof count @@ -299,7 +299,10 @@ None ) - n = get_ava_p2p_interface(node) + # It would be much simpler to just use get_ava_p2p_interface here + # but the node would be able to download the proof, so the node + # won't be pending. + n = get_ava_p2p_interface_no_handshake(node) n.send_avahello(delegation, dg_priv) # Make sure we completed at least one time the ProcessMessage or we # might miss the last pending node for the following assert diff --git a/test/functional/abc_rpc_getavalanchepeerinfo.py b/test/functional/abc_rpc_getavalanchepeerinfo.py --- a/test/functional/abc_rpc_getavalanchepeerinfo.py +++ b/test/functional/abc_rpc_getavalanchepeerinfo.py @@ -8,7 +8,7 @@ from test_framework.avatools import ( avalanche_proof_from_hex, create_coinbase_stakes, - get_ava_p2p_interface, + get_ava_p2p_interface_no_handshake, ) from test_framework.key import ECKey from test_framework.test_framework import BitcoinTestFramework @@ -56,7 +56,7 @@ return (pubkey.get_bytes().hex(), proof) # Create peercount * nodecount node array - nodes = [[get_ava_p2p_interface(node) for _ in range( + nodes = [[get_ava_p2p_interface_no_handshake(node) for _ in range( nodecount)] for _ in range(peercount)] # Add peercount peers and bind all the nodes to each 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 @@ -34,7 +34,7 @@ ) from .p2p import P2PInterface, p2p_lock from .test_node import TestNode -from .util import satoshi_round, wait_until_helper +from .util import satoshi_round, uint256_hex, wait_until_helper from .wallet_util import bytes_to_wif @@ -330,7 +330,7 @@ self.send_message(msg_notfound(not_found)) -def get_ava_p2p_interface( +def get_ava_p2p_interface_no_handshake( node: TestNode, services=NODE_NETWORK | NODE_AVALANCHE) -> NoHandshakeAvaP2PInterface: """Build and return a NoHandshakeAvaP2PInterface connected to the specified @@ -345,6 +345,38 @@ return n +def get_ava_p2p_interface( + node: TestNode, + services=NODE_NETWORK | NODE_AVALANCHE, + stake_utxo_confirmations=1) -> AvaP2PInterface: + """Build and return an AvaP2PInterface connected to the specified TestNode. + """ + n = AvaP2PInterface(node) + + # Make sure the proof utxos are mature + if stake_utxo_confirmations > 1: + node.generate(stake_utxo_confirmations - 1) + + assert node.verifyavalancheproof(n.proof.serialize().hex()) + + proofid_hex = uint256_hex(n.proof.proofid) + node.add_p2p_connection(n, services=services) + n.nodeid = node.getpeerinfo()[-1]['id'] + + def avapeer_connected(): + node_list = [] + try: + node_list = node.getavalanchepeerinfo(proofid_hex)[0]['node_list'] + except BaseException: + pass + + return n.nodeid in node_list + + wait_until_helper(avapeer_connected, timeout=3) + + return n + + def gen_proof(node, coinbase_utxos=1): blockhashes = node.generate(coinbase_utxos)