Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche.py
Show All 9 Lines | from test_framework.key import ( | ||||
ECKey, | ECKey, | ||||
ECPubKey, | ECPubKey, | ||||
) | ) | ||||
from test_framework.mininode import P2PInterface, mininode_lock | from test_framework.mininode import P2PInterface, mininode_lock | ||||
from test_framework.messages import ( | from test_framework.messages import ( | ||||
AvalancheResponse, | AvalancheResponse, | ||||
AvalancheVote, | AvalancheVote, | ||||
CInv, | CInv, | ||||
MSG_AVALANCHE_PROOF, | |||||
msg_avapoll, | msg_avapoll, | ||||
msg_avahello, | |||||
msg_getdata, | |||||
msg_tcpavaresponse, | msg_tcpavaresponse, | ||||
NODE_AVALANCHE, | NODE_AVALANCHE, | ||||
NODE_NETWORK, | NODE_NETWORK, | ||||
TCPAvalancheResponse, | TCPAvalancheResponse, | ||||
) | ) | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import ( | from test_framework.util import ( | ||||
assert_equal, | assert_equal, | ||||
assert_raises_rpc_error, | assert_raises_rpc_error, | ||||
wait_until, | wait_until, | ||||
) | ) | ||||
AVALANCHE_MAX_PROOF_STAKES = 1000 | AVALANCHE_MAX_PROOF_STAKES = 1000 | ||||
BLOCK_ACCEPTED = 0 | BLOCK_ACCEPTED = 0 | ||||
BLOCK_INVALID = 1 | BLOCK_INVALID = 1 | ||||
BLOCK_PARKED = 2 | BLOCK_PARKED = 2 | ||||
BLOCK_FORK = 3 | BLOCK_FORK = 3 | ||||
BLOCK_UNKNOWN = -1 | BLOCK_UNKNOWN = -1 | ||||
BLOCK_MISSING = -2 | BLOCK_MISSING = -2 | ||||
BLOCK_PENDING = -3 | BLOCK_PENDING = -3 | ||||
QUORUM_NODE_COUNT = 16 | QUORUM_NODE_COUNT = 16 | ||||
DUMMY_PROOFID = 1337 | |||||
class TestNode(P2PInterface): | class TestNode(P2PInterface): | ||||
def __init__(self): | def __init__(self): | ||||
self.round = 0 | self.round = 0 | ||||
self.avahello = None | self.avahello = None | ||||
self.avaresponses = [] | self.avaresponses = [] | ||||
self.avapolls = [] | self.avapolls = [] | ||||
self.avaproof = None | |||||
super().__init__() | super().__init__() | ||||
def peer_connect(self, *args, **kwargs): | def peer_connect(self, *args, **kwargs): | ||||
create_conn = super().peer_connect(*args, **kwargs) | create_conn = super().peer_connect(*args, **kwargs) | ||||
# Save the nonce and extra entropy so they can be reused later. | # Save the nonce and extra entropy so they can be reused later. | ||||
self.local_nonce = self.on_connection_send_msg.nNonce | self.local_nonce = self.on_connection_send_msg.nNonce | ||||
self.local_extra_entropy = self.on_connection_send_msg.nExtraEntropy | self.local_extra_entropy = self.on_connection_send_msg.nExtraEntropy | ||||
▲ Show 20 Lines • Show All 52 Lines • ▼ Show 20 Lines | def wait_for_avahello(self, timeout=5): | ||||
wait_until( | wait_until( | ||||
lambda: self.avahello is not None, | lambda: self.avahello is not None, | ||||
timeout=timeout, | timeout=timeout, | ||||
lock=mininode_lock) | lock=mininode_lock) | ||||
with mininode_lock: | with mininode_lock: | ||||
return self.avahello | return self.avahello | ||||
def send_avahello(self): | |||||
msg = msg_avahello() | |||||
msg.hello.delegation.proofid = DUMMY_PROOFID | |||||
self.send_message(msg) | |||||
def send_getdata(self, inv: List[CInv]): | |||||
msg = msg_getdata() | |||||
msg.inv = inv | |||||
self.send_message(msg) | |||||
def on_avaproof(self, message): | |||||
with mininode_lock: | |||||
assert(self.avaproof is None) | |||||
self.avaproof = message | |||||
def wait_for_avaproof(self, timeout=10): | |||||
wait_until( | |||||
lambda: self.avaproof is not None, | |||||
timeout=timeout, | |||||
lock=mininode_lock) | |||||
with mininode_lock: | |||||
return self.avaproof | |||||
def get_stakes(coinbases: List[Dict], | def get_stakes(coinbases: List[Dict], | ||||
priv_key: str) -> List[Dict]: | priv_key: str) -> List[Dict]: | ||||
return [{ | return [{ | ||||
'txid': coinbase['txid'], | 'txid': coinbase['txid'], | ||||
'vout': coinbase['n'], | 'vout': coinbase['n'], | ||||
'amount': coinbase['value'], | 'amount': coinbase['value'], | ||||
'height': coinbase['height'], | 'height': coinbase['height'], | ||||
▲ Show 20 Lines • Show All 264 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
assert node.getblockchaininfo()["initialblockdownload"] is False | assert node.getblockchaininfo()["initialblockdownload"] is False | ||||
assert_equal(len(node.getavalanchepeerinfo()), 1) | assert_equal(len(node.getavalanchepeerinfo()), 1) | ||||
# Rebuild the quorum | # Rebuild the quorum | ||||
self.log.info("Test the avahello signature") | self.log.info("Test the avahello signature") | ||||
quorum = get_quorum() | quorum = get_quorum() | ||||
poll_node = quorum[0] | poll_node = quorum[0] | ||||
# Check the handshake sequence | |||||
self.log.info("Receive AVAHELLO, request the corresponding proof") | |||||
avahello = poll_node.wait_for_avahello().hello | avahello = poll_node.wait_for_avahello().hello | ||||
avakey.set(bytes.fromhex(node.getavalanchekey())) | avakey.set(bytes.fromhex(node.getavalanchekey())) | ||||
assert avakey.verify_schnorr( | assert avakey.verify_schnorr( | ||||
avahello.sig, avahello.get_sighash(poll_node)) | avahello.sig, avahello.get_sighash(poll_node)) | ||||
poll_node.send_getdata([CInv(MSG_AVALANCHE_PROOF, | |||||
avahello.delegation.proofid)]) | |||||
poll_node.wait_for_avaproof() | |||||
# TODO: deserialize proof and check it in more details | |||||
self.log.info( | |||||
"Send an AVAHELLO to the node, check that it ask for our prooof") | |||||
poll_node.send_avahello() | |||||
poll_node.wait_for_getdata([DUMMY_PROOFID]) | |||||
# TODO: reply with a new AVAPROOF message and verify that poll node is | |||||
# added to node's avalanche peers | |||||
# Check the maximum number of stakes policy | # Check the maximum number of stakes policy | ||||
blocks = node.generatetoaddress(AVALANCHE_MAX_PROOF_STAKES + 1, | blocks = node.generatetoaddress(AVALANCHE_MAX_PROOF_STAKES + 1, | ||||
addrkey0.address) | addrkey0.address) | ||||
too_many_coinbases = [get_coinbase(h) for h in blocks] | too_many_coinbases = [get_coinbase(h) for h in blocks] | ||||
too_many_stakes = get_stakes(too_many_coinbases, addrkey0.key) | too_many_stakes = get_stakes(too_many_coinbases, addrkey0.key) | ||||
self.log.info( | self.log.info( | ||||
▲ Show 20 Lines • Show All 76 Lines • Show Last 20 Lines |