Changeset View
Changeset View
Standalone View
Standalone View
test/functional/p2p_eviction.py
Show All 9 Lines | |||||
We cannot currently test the parts of the eviction logic that are based on | We cannot currently test the parts of the eviction logic that are based on | ||||
address/netgroup since in the current framework, all peers are connecting from | address/netgroup since in the current framework, all peers are connecting from | ||||
the same local address. See Issue #14210 for more info. | the same local address. See Issue #14210 for more info. | ||||
Therefore, this test is limited to the remaining protection criteria. | Therefore, this test is limited to the remaining protection criteria. | ||||
""" | """ | ||||
import time | import time | ||||
from test_framework.avatools import create_coinbase_stakes | from test_framework.avatools import AvaP2PInterface, create_coinbase_stakes | ||||
from test_framework.blocktools import create_block, create_coinbase | from test_framework.blocktools import create_block, create_coinbase | ||||
from test_framework.key import ECKey | from test_framework.key import ECKey, bytes_to_wif | ||||
from test_framework.messages import ( | from test_framework.messages import ( | ||||
AvalancheProof, | AvalancheProof, | ||||
CTransaction, | CTransaction, | ||||
FromHex, | FromHex, | ||||
msg_avaproof, | msg_avaproof, | ||||
msg_pong, | msg_pong, | ||||
msg_tx, | msg_tx, | ||||
) | ) | ||||
Show All 9 Lines | |||||
class SlowP2PInterface(P2PInterface): | class SlowP2PInterface(P2PInterface): | ||||
def on_ping(self, message): | def on_ping(self, message): | ||||
time.sleep(0.1) | time.sleep(0.1) | ||||
self.send_message(msg_pong(message.nonce)) | self.send_message(msg_pong(message.nonce)) | ||||
class SlowAvaP2PInterface(AvaP2PInterface): | |||||
def on_ping(self, message): | |||||
time.sleep(0.1) | |||||
self.send_message(msg_pong(message.nonce)) | |||||
class P2PEvict(BitcoinTestFramework): | class P2PEvict(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.setup_clean_chain = True | self.setup_clean_chain = True | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
# The choice of maxconnections=36 results in a maximum of 25 inbound connections | # The choice of maxconnections=164 results in a maximum of 153 inbound | ||||
# (36 - 10 outbound - 1 feeler). 20 inbound peers are protected from eviction: | # connections (164 - 10 outbound - 1 feeler). 152 inbound peers are | ||||
# protected from eviction: | |||||
# 4 by netgroup, 4 that sent us blocks, 4 that sent us proofs, 4 that | # 4 by netgroup, 4 that sent us blocks, 4 that sent us proofs, 4 that | ||||
# sent us transactions and 8 via lowest ping time | # sent us transactions, 8 via lowest ping time, 128 with the best | ||||
self.extra_args = [['-maxconnections=36', "-enableavalanche=1"]] | # avalanche availability score | ||||
self.extra_args = [['-maxconnections=164', "-enableavalanche=1"]] | |||||
def run_test(self): | def run_test(self): | ||||
# peers that we expect to be protected from eviction | # peers that we expect to be protected from eviction | ||||
protected_peers = set() | protected_peers = set() | ||||
current_peer = -1 | current_peer = -1 | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
blocks = node.generatetoaddress( | blocks = node.generatetoaddress( | ||||
101, node.get_deterministic_priv_key().address) | 101, node.get_deterministic_priv_key().address) | ||||
▲ Show 20 Lines • Show All 72 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
self.log.info( | self.log.info( | ||||
"Create 8 peers and protect them from eviction by having faster pings") | "Create 8 peers and protect them from eviction by having faster pings") | ||||
for _ in range(8): | for _ in range(8): | ||||
fastpeer = node.add_p2p_connection(P2PInterface()) | fastpeer = node.add_p2p_connection(P2PInterface()) | ||||
current_peer += 1 | current_peer += 1 | ||||
wait_until(lambda: "ping" in fastpeer.last_message, timeout=10) | wait_until(lambda: "ping" in fastpeer.last_message, timeout=10) | ||||
self.log.info( | |||||
"Create 128 peers and protect them from eviction by sending an avahello message") | |||||
proof = node.buildavalancheproof( | |||||
42, 2000000000, pubkey.get_bytes().hex(), [stakes[0]]) | |||||
proof_obj = FromHex(AvalancheProof(), proof) | |||||
delegation = node.delegateavalancheproof( | |||||
f"{proof_obj.limited_proofid:064x}", | |||||
bytes_to_wif(privkey.get_bytes()), | |||||
pubkey.get_bytes().hex(), | |||||
) | |||||
for _ in range(128): | |||||
avapeer = node.add_p2p_connection(SlowAvaP2PInterface()) | |||||
current_peer += 1 | |||||
avapeer.sync_with_ping() | |||||
avapeer.send_avahello(delegation, privkey) | |||||
# Make sure by asking the node what the actual min pings are | # Make sure by asking the node what the actual min pings are | ||||
peerinfo = node.getpeerinfo() | peerinfo = node.getpeerinfo() | ||||
pings = {} | pings = {} | ||||
for i in range(len(peerinfo)): | for i in range(len(peerinfo)): | ||||
pings[i] = peerinfo[i]['minping'] if 'minping' in peerinfo[i] else 1000000 | pings[i] = peerinfo[i]['minping'] if 'minping' in peerinfo[i] else 1000000 | ||||
sorted_pings = sorted(pings.items(), key=lambda x: x[1]) | sorted_pings = sorted(pings.items(), key=lambda x: x[1]) | ||||
# Usually the 8 fast peers are protected. In rare case of unreliable pings, | # Usually the 8 fast peers are protected. In rare case of unreliable pings, | ||||
Show All 33 Lines |