Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_feature_proof_cleanup.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2022 The Bitcoin developers | # Copyright (c) 2022 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 the dangling proofs cleanup | Test the dangling proofs cleanup | ||||
""" | """ | ||||
import time | import time | ||||
from test_framework.avatools import ( | from test_framework.avatools import ( | ||||
gen_proof, | gen_proof, | ||||
get_ava_p2p_interface, | get_ava_p2p_interface, | ||||
get_proof_ids, | get_proof_ids, | ||||
wait_for_proof, | |||||
) | ) | ||||
from test_framework.key import ECKey | from test_framework.key import ECKey | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal | from test_framework.util import assert_equal | ||||
from test_framework.wallet_util import bytes_to_wif | from test_framework.wallet_util import bytes_to_wif | ||||
# Interval between 2 proof cleanups | # Interval between 2 proof cleanups | ||||
AVALANCHE_CLEANUP_INTERVAL = 5 * 60 | AVALANCHE_CLEANUP_INTERVAL = 5 * 60 | ||||
Show All 10 Lines | def set_test_params(self): | ||||
'-enableavalanchepeerdiscovery=1', | '-enableavalanchepeerdiscovery=1', | ||||
# Get rid of the getdata delay penalty for inbounds | # Get rid of the getdata delay penalty for inbounds | ||||
'-whitelist=noban@127.0.0.1', | '-whitelist=noban@127.0.0.1', | ||||
]] * self.num_nodes | ]] * self.num_nodes | ||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
master_key, local_proof = gen_proof(node) | |||||
self.restart_node(0, self.extra_args[0] + [ | |||||
"-avaproof={}".format(local_proof.serialize().hex()), | |||||
"-avamasterkey={}".format(bytes_to_wif(master_key.get_bytes())), | |||||
]) | |||||
node.generate(1) | |||||
wait_for_proof(node, f"{local_proof.proofid:0{64}x}") | |||||
mocktime = int(time.time()) | mocktime = int(time.time()) | ||||
node.setmocktime(mocktime) | node.setmocktime(mocktime) | ||||
proofs = [] | proofs = [local_proof] | ||||
keys = [] | keys = [master_key] | ||||
peers = [] | peers = [] | ||||
# The first 5 peers have a node attached | # The first 5 peers have a node attached | ||||
for _ in range(5): | for _ in range(5): | ||||
key, proof = gen_proof(node) | key, proof = gen_proof(node) | ||||
peer = get_ava_p2p_interface(node) | peer = get_ava_p2p_interface(node) | ||||
node.addavalanchenode( | node.addavalanchenode( | ||||
peer.nodeid, | peer.nodeid, | ||||
key.get_pubkey().get_bytes().hex(), | key.get_pubkey().get_bytes().hex(), | ||||
proof.serialize().hex()) | proof.serialize().hex()) | ||||
proofs.append(proof) | proofs.append(proof) | ||||
keys.append(key) | keys.append(key) | ||||
peers.append(peer) | peers.append(peer) | ||||
# The last 5 peers have no node attached | # The last 5 peers have no node attached | ||||
for _ in range(5): | for _ in range(5): | ||||
_, proof = gen_proof(node) | _, proof = gen_proof(node) | ||||
node.sendavalancheproof(proof.serialize().hex()) | node.sendavalancheproof(proof.serialize().hex()) | ||||
proofs.append(proof) | proofs.append(proof) | ||||
peer_info = node.getavalanchepeerinfo() | peer_info = node.getavalanchepeerinfo() | ||||
assert_equal(len(peer_info), 10) | assert_equal(len(peer_info), 11) | ||||
assert_equal(set(get_proof_ids(node)), | assert_equal(set(get_proof_ids(node)), | ||||
set([proof.proofid for proof in proofs])) | set([proof.proofid for proof in proofs])) | ||||
self.log.info("No proof is cleaned before the timeout expires") | self.log.info("No proof is cleaned before the timeout expires") | ||||
mocktime += AVALANCHE_DANGLING_PROOF_TIMEOUT - 1 | mocktime += AVALANCHE_DANGLING_PROOF_TIMEOUT - 1 | ||||
node.setmocktime(mocktime) | node.setmocktime(mocktime) | ||||
# Run the cleanup, the proofs are still there | # Run the cleanup, the proofs are still there | ||||
node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | ||||
assert_equal(len(peer_info), 10) | assert_equal(len(peer_info), 11) | ||||
self.log.info("Check the proofs with attached nodes are not cleaned") | self.log.info("Check the proofs with attached nodes are not cleaned") | ||||
# Expire the dangling proof timeout | # Expire the dangling proof timeout | ||||
mocktime += 1 | mocktime += 1 | ||||
node.setmocktime(mocktime) | node.setmocktime(mocktime) | ||||
# Run the cleanup, the proofs with no node are cleaned | # Run the cleanup, the proofs with no node are cleaned excepted our | ||||
# local proof | |||||
node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | ||||
self.wait_until(lambda: set(get_proof_ids(node)) == set( | self.wait_until(lambda: set(get_proof_ids(node)) == set( | ||||
[proof.proofid for proof in proofs[:5]]), timeout=5) | [proof.proofid for proof in proofs[:6]]), timeout=5) | ||||
self.log.info( | self.log.info( | ||||
"Check the proofs are cleaned on next cleanup after the nodes disconnected") | "Check the proofs are cleaned on next cleanup after the nodes disconnected") | ||||
for peer in peers: | for peer in peers: | ||||
peer.peer_disconnect() | peer.peer_disconnect() | ||||
peer.wait_for_disconnect() | peer.wait_for_disconnect() | ||||
node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | ||||
self.wait_until(lambda: get_proof_ids(node) == []) | self.wait_until(lambda: get_proof_ids(node) == [local_proof.proofid]) | ||||
self.log.info("Check the cleaned up proofs are no longer accepted...") | self.log.info("Check the cleaned up proofs are no longer accepted...") | ||||
sender = get_ava_p2p_interface(node) | sender = get_ava_p2p_interface(node) | ||||
for proof in proofs: | for proof in proofs[1:]: | ||||
with node.assert_debug_log(["dangling-proof"]): | with node.assert_debug_log(["dangling-proof"]): | ||||
sender.send_avaproof(proof) | sender.send_avaproof(proof) | ||||
assert_equal(get_proof_ids(node), []) | assert_equal(get_proof_ids(node), [local_proof.proofid]) | ||||
self.log.info("...until there is a node to attach") | self.log.info("...until there is a node to attach") | ||||
node.disconnect_p2ps() | node.disconnect_p2ps() | ||||
assert_equal(len(node.p2ps), 0) | assert_equal(len(node.p2ps), 0) | ||||
avanode = get_ava_p2p_interface(node) | avanode = get_ava_p2p_interface(node) | ||||
avanode_key = keys[0] | avanode_key = keys[1] | ||||
avanode_proof = proofs[0] | avanode_proof = proofs[1] | ||||
delegated_key = ECKey() | delegated_key = ECKey() | ||||
delegated_key.generate() | delegated_key.generate() | ||||
delegation = node.delegateavalancheproof( | delegation = node.delegateavalancheproof( | ||||
f"{avanode_proof.limited_proofid:064x}", | f"{avanode_proof.limited_proofid:064x}", | ||||
bytes_to_wif(avanode_key.get_bytes()), | bytes_to_wif(avanode_key.get_bytes()), | ||||
delegated_key.get_pubkey().get_bytes().hex(), | delegated_key.get_pubkey().get_bytes().hex(), | ||||
Show All 13 Lines |