Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_proof_inventory.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2021 The Bitcoin developers | # Copyright (c) 2021 The Bitcoin developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
""" | """ | ||||
Test proof inventory relaying | Test proof inventory relaying | ||||
""" | """ | ||||
import time | import time | ||||
from test_framework.address import ADDRESS_ECREG_UNSPENDABLE | from test_framework.address import ADDRESS_ECREG_UNSPENDABLE | ||||
from test_framework.avatools import ( | from test_framework.avatools import ( | ||||
AvaP2PInterface, | |||||
avalanche_proof_from_hex, | avalanche_proof_from_hex, | ||||
gen_proof, | gen_proof, | ||||
get_proof_ids, | get_proof_ids, | ||||
wait_for_proof, | wait_for_proof, | ||||
) | ) | ||||
from test_framework.key import ECKey | from test_framework.key import ECKey | ||||
from test_framework.messages import ( | from test_framework.messages import ( | ||||
MSG_AVA_PROOF, | MSG_AVA_PROOF, | ||||
MSG_TYPE_MASK, | MSG_TYPE_MASK, | ||||
CInv, | CInv, | ||||
msg_avaproof, | msg_avaproof, | ||||
msg_getavaproofs, | |||||
msg_getdata, | msg_getdata, | ||||
) | ) | ||||
from test_framework.p2p import P2PInterface, p2p_lock | from test_framework.p2p import P2PInterface, p2p_lock | ||||
from test_framework.siphash import siphash256 | |||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal, assert_greater_than | from test_framework.util import assert_equal, assert_greater_than | ||||
from test_framework.wallet_util import bytes_to_wif | from test_framework.wallet_util import bytes_to_wif | ||||
# Broadcast reattempt occurs every 10 to 15 minutes | # Broadcast reattempt occurs every 10 to 15 minutes | ||||
MAX_INITIAL_BROADCAST_DELAY = 15 * 60 | MAX_INITIAL_BROADCAST_DELAY = 15 * 60 | ||||
# Delay to allow the node to respond to getdata requests | # Delay to allow the node to respond to getdata requests | ||||
UNCONDITIONAL_RELAY_DELAY = 2 * 60 | UNCONDITIONAL_RELAY_DELAY = 2 * 60 | ||||
▲ Show 20 Lines • Show All 147 Lines • ▼ Show 20 Lines | def test_manually_sent_proof(self): | ||||
_, proof = gen_proof(node0) | _, proof = gen_proof(node0) | ||||
self.log.info( | self.log.info( | ||||
"Send a proof via RPC and check all the nodes download it") | "Send a proof via RPC and check all the nodes download it") | ||||
node0.sendavalancheproof(proof.serialize().hex()) | node0.sendavalancheproof(proof.serialize().hex()) | ||||
self.sync_proofs() | self.sync_proofs() | ||||
def test_respond_getavaproofs(self): | |||||
self.log.info("Check the node responds to getavaproofs messages") | |||||
self.restart_node(0) | |||||
node = self.nodes[0] | |||||
def received_avaproofs(peer): | |||||
with p2p_lock: | |||||
return peer.last_message.get("avaproofs") | |||||
def send_getavaproof_check_shortid_len(peer, expected_len): | |||||
peer.send_message(msg_getavaproofs()) | |||||
self.wait_until(lambda: received_avaproofs(peer)) | |||||
avaproofs = received_avaproofs(peer) | |||||
assert_equal(len(avaproofs.shortids), expected_len) | |||||
# Initially the node has 0 peer | |||||
assert_equal(len(get_proof_ids(node)), 0) | |||||
peer = node.add_p2p_connection(AvaP2PInterface()) | |||||
send_getavaproof_check_shortid_len(peer, 0) | |||||
# Add some proofs | |||||
sending_peer = node.add_p2p_connection(AvaP2PInterface()) | |||||
for _ in range(50): | |||||
_, proof = gen_proof(node) | |||||
sending_peer.send_avaproof(proof) | |||||
wait_for_proof(node, f"{proof.proofid:0{64}x}") | |||||
proofids = get_proof_ids(node) | |||||
assert_equal(len(proofids), 50) | |||||
receiving_peer = node.add_p2p_connection(AvaP2PInterface()) | |||||
send_getavaproof_check_shortid_len(receiving_peer, len(proofids)) | |||||
avaproofs = received_avaproofs(receiving_peer) | |||||
expected_shortids = [ | |||||
siphash256( | |||||
avaproofs.key0, | |||||
avaproofs.key1, | |||||
proofid) & 0x0000ffffffffffff for proofid in sorted(proofids)] | |||||
assert_equal(expected_shortids, avaproofs.shortids) | |||||
# Don't expect any prefilled proof for now | |||||
assert_equal(len(avaproofs.prefilled_proofs), 0) | |||||
def test_unbroadcast(self): | def test_unbroadcast(self): | ||||
self.log.info("Test broadcasting proofs") | self.log.info("Test broadcasting proofs") | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
# Disconnect the other nodes, or they will request the proof and | # Disconnect the other nodes/peers, or they will request the proof and | ||||
# invalidate the test | # invalidate the test | ||||
[node.stop_node() for node in self.nodes[1:]] | [n.stop_node() for n in self.nodes[1:]] | ||||
node.disconnect_p2ps() | |||||
def add_peers(count): | def add_peers(count): | ||||
peers = [] | peers = [] | ||||
for i in range(count): | for i in range(count): | ||||
peer = node.add_p2p_connection(ProofInvStoreP2PInterface()) | peer = node.add_p2p_connection(ProofInvStoreP2PInterface()) | ||||
peer.wait_for_verack() | peer.wait_for_verack() | ||||
peers.append(peer) | peers.append(peer) | ||||
return peers | return peers | ||||
▲ Show 20 Lines • Show All 78 Lines • ▼ Show 20 Lines | def test_unbroadcast(self): | ||||
assert not proof_inv_received(peers) | assert not proof_inv_received(peers) | ||||
def run_test(self): | def run_test(self): | ||||
self.test_send_proof_inv() | self.test_send_proof_inv() | ||||
self.test_receive_proof() | self.test_receive_proof() | ||||
self.test_proof_relay() | self.test_proof_relay() | ||||
self.test_manually_sent_proof() | self.test_manually_sent_proof() | ||||
self.test_respond_getavaproofs() | |||||
# Run these tests last because they need to disconnect the nodes | # Run these tests last because they need to disconnect the nodes | ||||
self.test_unbroadcast() | self.test_unbroadcast() | ||||
self.test_ban_invalid_proof() | self.test_ban_invalid_proof() | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
ProofInventoryTest().main() | ProofInventoryTest().main() |