Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_feature_proof_cleanup.py
Show All 23 Lines | |||||
AVALANCHE_CLEANUP_INTERVAL = 5 * 60 | AVALANCHE_CLEANUP_INTERVAL = 5 * 60 | ||||
# Dangling proof timeout | # Dangling proof timeout | ||||
AVALANCHE_DANGLING_PROOF_TIMEOUT = 15 * 60 | AVALANCHE_DANGLING_PROOF_TIMEOUT = 15 * 60 | ||||
class ProofsCleanupTest(BitcoinTestFramework): | class ProofsCleanupTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.extra_args = [[ | self.extra_args = [ | ||||
'-avaproofstakeutxodustthreshold=1000000', | [ | ||||
'-avaproofstakeutxoconfirmations=1', | "-avaproofstakeutxodustthreshold=1000000", | ||||
"-avaproofstakeutxoconfirmations=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(self, node) | master_key, local_proof = gen_proof(self, node) | ||||
self.restart_node(0, self.extra_args[0] + [ | self.restart_node( | ||||
0, | |||||
self.extra_args[0] | |||||
+ [ | |||||
f"-avaproof={local_proof.serialize().hex()}", | f"-avaproof={local_proof.serialize().hex()}", | ||||
f"-avamasterkey={bytes_to_wif(master_key.get_bytes())}", | f"-avamasterkey={bytes_to_wif(master_key.get_bytes())}", | ||||
]) | ], | ||||
) | |||||
# Add an inbound so the node proof can be registered and advertised | # Add an inbound so the node proof can be registered and advertised | ||||
node.add_p2p_connection(P2PInterface()) | node.add_p2p_connection(P2PInterface()) | ||||
self.generate(node, 1, sync_fun=self.no_op) | self.generate(node, 1, sync_fun=self.no_op) | ||||
wait_for_proof(node, uint256_hex(local_proof.proofid)) | wait_for_proof(node, uint256_hex(local_proof.proofid)) | ||||
mocktime = int(time.time()) | mocktime = int(time.time()) | ||||
node.setmocktime(mocktime) | node.setmocktime(mocktime) | ||||
Show All 11 Lines | def run_test(self): | ||||
# 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(self, node) | _, proof = gen_proof(self, 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), 11) | assert_equal(len(peer_info), 11) | ||||
assert_equal(set(get_proof_ids(node)), | assert_equal(set(get_proof_ids(node)), {proof.proofid for proof in proofs}) | ||||
{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), 11) | 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") | ||||
# Run the cleanup, the proofs with no node are cleaned excepted our | # Run the cleanup, the proofs with no node are cleaned excepted our | ||||
# local proof | # local proof | ||||
with node.assert_debug_log([f"Proof dropped for dangling too long (no connected node): {uint256_hex(p.proofid)}" for p in proofs[6:]]): | with node.assert_debug_log( | ||||
[ | |||||
"Proof dropped for dangling too long (no connected node):" | |||||
f" {uint256_hex(p.proofid)}" | |||||
for p in proofs[6:] | |||||
] | |||||
): | |||||
# Expire the dangling proof timeout | # Expire the dangling proof timeout | ||||
mocktime += 1 | mocktime += 1 | ||||
node.setmocktime(mocktime) | node.setmocktime(mocktime) | ||||
node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | node.mockscheduler(AVALANCHE_CLEANUP_INTERVAL) | ||||
self.wait_until( | self.wait_until( | ||||
lambda: set(get_proof_ids(node)) == { | lambda: set(get_proof_ids(node)) | ||||
proof.proofid for proof in proofs[:6]}, | == {proof.proofid for proof in proofs[:6]}, | ||||
timeout=5) | 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) == [local_proof.proofid]) | 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_no_handshake(node) | sender = get_ava_p2p_interface_no_handshake(node) | ||||
for proof in proofs[1:]: | 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_raises_rpc_error(-8, "dangling-proof", | assert_raises_rpc_error( | ||||
node.sendavalancheproof, proof.serialize().hex()) | -8, "dangling-proof", node.sendavalancheproof, proof.serialize().hex() | ||||
) | |||||
assert_equal(get_proof_ids(node), [local_proof.proofid]) | 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(self, node) | avanode = get_ava_p2p_interface(self, node) | ||||
avanode.wait_until(lambda: avanode.last_message.get( | avanode.wait_until( | ||||
"getdata") and avanode.last_message["getdata"].inv[-1].hash == avanode.proof.proofid) | lambda: avanode.last_message.get("getdata") | ||||
and avanode.last_message["getdata"].inv[-1].hash == avanode.proof.proofid | |||||
) | |||||
avanode.send_avaproof(avanode.proof) | avanode.send_avaproof(avanode.proof) | ||||
self.wait_until(lambda: avanode.proof.proofid in get_proof_ids(node)) | self.wait_until(lambda: avanode.proof.proofid in get_proof_ids(node)) | ||||
if __name__ == '__main__': | if __name__ == "__main__": | ||||
ProofsCleanupTest().main() | ProofsCleanupTest().main() |