Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_p2p_avalanche.py
Show First 20 Lines • Show All 282 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
[AvalancheVote(BLOCK_FORK, h) for h in various_block_hashes[3:6]] + | [AvalancheVote(BLOCK_FORK, h) for h in various_block_hashes[3:6]] + | ||||
[AvalancheVote(BLOCK_UNKNOWN, h) for h in various_block_hashes[-3:]]) | [AvalancheVote(BLOCK_UNKNOWN, h) for h in various_block_hashes[-3:]]) | ||||
self.log.info("Trigger polling from the node...") | self.log.info("Trigger polling from the node...") | ||||
# duplicate the deterministic sig test from src/test/key_tests.cpp | # duplicate the deterministic sig test from src/test/key_tests.cpp | ||||
privkey = ECKey() | privkey = ECKey() | ||||
privkey.set(bytes.fromhex( | privkey.set(bytes.fromhex( | ||||
"12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747"), True) | "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747"), True) | ||||
pubkey = privkey.get_pubkey() | proof_master = privkey.get_pubkey().get_bytes().hex() | ||||
proof_sequence = 11 | proof_sequence = 11 | ||||
proof_expiration = 12 | proof_expiration = 12 | ||||
proof = node.buildavalancheproof( | proof = node.buildavalancheproof( | ||||
proof_sequence, proof_expiration, pubkey.get_bytes().hex(), | proof_sequence, proof_expiration, proof_master, | ||||
[{ | [{ | ||||
'txid': coinbases[0]['txid'], | 'txid': coinbases[0]['txid'], | ||||
'vout': coinbases[0]['n'], | 'vout': coinbases[0]['n'], | ||||
'amount': coinbases[0]['value'], | 'amount': coinbases[0]['value'], | ||||
'height': coinbases[0]['height'], | 'height': coinbases[0]['height'], | ||||
'iscoinbase': True, | 'iscoinbase': True, | ||||
'privatekey': addrkey0.key, | 'privatekey': addrkey0.key, | ||||
}]) | }]) | ||||
# Activate the quorum. | # Activate the quorum. | ||||
for n in quorum: | for n in quorum: | ||||
success = node.addavalanchenode( | success = node.addavalanchenode( | ||||
n.nodeid, pubkey.get_bytes().hex(), proof) | n.nodeid, proof_master, proof) | ||||
assert success is True | assert success is True | ||||
self.log.info("Testing getavalanchepeerinfo...") | self.log.info("Testing getavalanchepeerinfo...") | ||||
avapeerinfo = node.getavalanchepeerinfo() | avapeerinfo = node.getavalanchepeerinfo() | ||||
# There is a single peer because all nodes share the same proof. | # There is a single peer because all nodes share the same proof. | ||||
assert_equal(len(avapeerinfo), 1) | assert_equal(len(avapeerinfo), 1) | ||||
assert_equal(avapeerinfo[0]["peerid"], 0) | assert_equal(avapeerinfo[0]["peerid"], 0) | ||||
assert_equal(avapeerinfo[0]["nodecount"], len(quorum)) | assert_equal(avapeerinfo[0]["nodecount"], len(quorum)) | ||||
# The first avalanche node index is 1, because 0 is self.nodes[1]. | # The first avalanche node index is 1, because 0 is self.nodes[1]. | ||||
assert_equal(sorted(avapeerinfo[0]["nodes"]), | assert_equal(sorted(avapeerinfo[0]["nodes"]), | ||||
list(range(1, QUORUM_NODE_COUNT + 1))) | list(range(1, QUORUM_NODE_COUNT + 1))) | ||||
assert_equal(avapeerinfo[0]["sequence"], proof_sequence) | assert_equal(avapeerinfo[0]["sequence"], proof_sequence) | ||||
assert_equal(avapeerinfo[0]["expiration"], proof_expiration) | assert_equal(avapeerinfo[0]["expiration"], proof_expiration) | ||||
assert_equal(avapeerinfo[0]["master"], pubkey.get_bytes().hex()) | assert_equal(avapeerinfo[0]["master"], proof_master) | ||||
assert_equal(avapeerinfo[0]["proof"], proof) | assert_equal(avapeerinfo[0]["proof"], proof) | ||||
assert_equal(len(avapeerinfo[0]["stakes"]), 1) | assert_equal(len(avapeerinfo[0]["stakes"]), 1) | ||||
assert_equal(avapeerinfo[0]["stakes"][0]["txid"], coinbases[0]['txid']) | assert_equal(avapeerinfo[0]["stakes"][0]["txid"], coinbases[0]['txid']) | ||||
def can_find_block_in_poll(hash, resp=BLOCK_ACCEPTED): | def can_find_block_in_poll(hash, resp=BLOCK_ACCEPTED): | ||||
found_hash = False | found_hash = False | ||||
for n in quorum: | for n in quorum: | ||||
poll = n.get_avapoll_if_available() | poll = n.get_avapoll_if_available() | ||||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Lines | def run_test(self): | ||||
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 | # Check the handshake sequence | ||||
self.log.info("Receive AVAHELLO, request the corresponding proof") | self.log.info("Test avahello sequence node -> poll_node") | ||||
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, | poll_node.send_getdata([CInv(MSG_AVALANCHE_PROOF, | ||||
avahello.delegation.proofid)]) | avahello.delegation.proofid)]) | ||||
poll_node.wait_for_avaproof() | avaproof = poll_node.wait_for_avaproof().proof | ||||
# TODO: deserialize proof and check it in more details | assert_equal(proof, avaproof.serialize().hex()) | ||||
assert_equal(avaproof.proofid, avahello.delegation.proofid) | |||||
self.log.info( | self.log.info( | ||||
"Send an AVAHELLO to the node, check that it ask for our prooof") | "Test avahello sequence poll_node -> node") | ||||
# This is testing only the first couple of steps (for now) | |||||
# TODO: make a proper delegation and a valid signature for avahello, | |||||
# reply with a valid avaproof, test that the node adds us. | |||||
poll_node.send_avahello() | poll_node.send_avahello() | ||||
poll_node.wait_for_getdata([DUMMY_PROOFID]) | 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( | ||||
"A proof using the maximum number of stakes is accepted...") | "A proof using the maximum number of stakes is accepted...") | ||||
maximum_stakes = get_stakes(too_many_coinbases[:-1], | maximum_stakes = get_stakes(too_many_coinbases[:-1], | ||||
addrkey0.key) | addrkey0.key) | ||||
good_proof = node.buildavalancheproof( | good_proof = node.buildavalancheproof( | ||||
proof_sequence, proof_expiration, | proof_sequence, proof_expiration, | ||||
pubkey.get_bytes().hex(), maximum_stakes) | proof_master, maximum_stakes) | ||||
node.addavalanchenode( | node.addavalanchenode( | ||||
get_node().nodeid, pubkey.get_bytes().hex(), good_proof) | get_node().nodeid, proof_master, good_proof) | ||||
self.log.info("A proof using too many stakes should be rejected...") | self.log.info("A proof using too many stakes should be rejected...") | ||||
bad_proof = node.buildavalancheproof( | bad_proof = node.buildavalancheproof( | ||||
proof_sequence, proof_expiration, | proof_sequence, proof_expiration, | ||||
pubkey.get_bytes().hex(), too_many_stakes) | proof_master, too_many_stakes) | ||||
assert_raises_rpc_error(-32602, "Avalanche proof has too many UTXOs", | assert_raises_rpc_error(-32602, "Avalanche proof has too many UTXOs", | ||||
node.addavalanchenode, | node.addavalanchenode, | ||||
get_node().nodeid, pubkey.get_bytes().hex(), | get_node().nodeid, proof_master, | ||||
bad_proof) | bad_proof) | ||||
self.log.info("Bad proof should be rejected at startup") | self.log.info("Bad proof should be rejected at startup") | ||||
no_stake = node.buildavalancheproof( | no_stake = node.buildavalancheproof( | ||||
proof_sequence, proof_expiration, pubkey.get_bytes().hex(), []) | proof_sequence, proof_expiration, proof_master, []) | ||||
dust = node.buildavalancheproof( | dust = node.buildavalancheproof( | ||||
proof_sequence, proof_expiration, pubkey.get_bytes().hex(), | proof_sequence, proof_expiration, proof_master, | ||||
[{ | [{ | ||||
'txid': coinbases[0]['txid'], | 'txid': coinbases[0]['txid'], | ||||
'vout': coinbases[0]['n'], | 'vout': coinbases[0]['n'], | ||||
'amount': '0', | 'amount': '0', | ||||
'height': coinbases[0]['height'], | 'height': coinbases[0]['height'], | ||||
'iscoinbase': True, | 'iscoinbase': True, | ||||
'privatekey': addrkey0.key, | 'privatekey': addrkey0.key, | ||||
}]) | }]) | ||||
duplicate_stake = node.buildavalancheproof( | duplicate_stake = node.buildavalancheproof( | ||||
proof_sequence, proof_expiration, pubkey.get_bytes().hex(), | proof_sequence, proof_expiration, proof_master, | ||||
[{ | [{ | ||||
'txid': coinbases[0]['txid'], | 'txid': coinbases[0]['txid'], | ||||
'vout': coinbases[0]['n'], | 'vout': coinbases[0]['n'], | ||||
'amount': coinbases[0]['value'], | 'amount': coinbases[0]['value'], | ||||
'height': coinbases[0]['height'], | 'height': coinbases[0]['height'], | ||||
'iscoinbase': True, | 'iscoinbase': True, | ||||
'privatekey': addrkey0.key, | 'privatekey': addrkey0.key, | ||||
}] * 2) | }] * 2) | ||||
Show All 32 Lines |