Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_rpc_getavalancheinfo.py
Show All 22 Lines | |||||
class GetAvalancheInfoTest(BitcoinTestFramework): | class GetAvalancheInfoTest(BitcoinTestFramework): | ||||
def set_test_params(self): | def set_test_params(self): | ||||
self.num_nodes = 1 | self.num_nodes = 1 | ||||
self.conflicting_proof_cooldown = 100 | self.conflicting_proof_cooldown = 100 | ||||
self.extra_args = [[ | self.extra_args = [[ | ||||
'-enableavalanche=1', | '-enableavalanche=1', | ||||
'-enableavalancheproofreplacement=1', | '-enableavalancheproofreplacement=1', | ||||
f'-avalancheconflictingproofcooldown={self.conflicting_proof_cooldown}', | f'-avalancheconflictingproofcooldown={self.conflicting_proof_cooldown}', | ||||
'-avaproofstakeutxoconfirmations=1', | '-avaproofstakeutxoconfirmations=2', | ||||
'-avacooldown=', | '-avacooldown=', | ||||
'-avatimeout=100', | '-avatimeout=100', | ||||
'-enableavalanchepeerdiscovery=1', | '-enableavalanchepeerdiscovery=1', | ||||
'-avaminquorumstake=250000000', | '-avaminquorumstake=250000000', | ||||
'-avaminquorumconnectedstakeratio=0.9', | '-avaminquorumconnectedstakeratio=0.9', | ||||
]] | ]] | ||||
def run_test(self): | def run_test(self): | ||||
node = self.nodes[0] | node = self.nodes[0] | ||||
privkey, proof = gen_proof(node) | privkey, proof = gen_proof(node) | ||||
is_legacy = isinstance(proof, LegacyAvalancheProof) | is_legacy = isinstance(proof, LegacyAvalancheProof) | ||||
# Make the proof mature | |||||
node.generate(1) | |||||
def handle_legacy_format(expected): | def handle_legacy_format(expected): | ||||
# Add the payout address to the expected output if the legacy format | # Add the payout address to the expected output if the legacy format | ||||
# is diabled | # is diabled | ||||
if not is_legacy and "local" in expected.keys(): | if not is_legacy and "local" in expected.keys(): | ||||
expected["local"]["payout_address"] = ADDRESS_ECREG_UNSPENDABLE | expected["local"]["payout_address"] = ADDRESS_ECREG_UNSPENDABLE | ||||
return expected | return expected | ||||
def assert_avalancheinfo(expected): | def assert_avalancheinfo(expected): | ||||
assert_equal( | assert_equal( | ||||
node.getavalancheinfo(), | node.getavalancheinfo(), | ||||
handle_legacy_format(expected) | handle_legacy_format(expected) | ||||
) | ) | ||||
coinbase_amount = Decimal('25000000.00') | coinbase_amount = Decimal('25000000.00') | ||||
self.log.info("The test node has no proof") | self.log.info("The test node has no proof") | ||||
assert_avalancheinfo({ | assert_avalancheinfo({ | ||||
"active": False, | "active": False, | ||||
"network": { | "network": { | ||||
"proof_count": 0, | "proof_count": 0, | ||||
"connected_proof_count": 0, | "connected_proof_count": 0, | ||||
"conflicting_proof_count": 0, | "conflicting_proof_count": 0, | ||||
"orphan_proof_count": 0, | |||||
"total_stake_amount": Decimal('0.00'), | "total_stake_amount": Decimal('0.00'), | ||||
"connected_stake_amount": Decimal('0.00'), | "connected_stake_amount": Decimal('0.00'), | ||||
"node_count": 0, | "node_count": 0, | ||||
"connected_node_count": 0, | "connected_node_count": 0, | ||||
"pending_node_count": 0, | "pending_node_count": 0, | ||||
} | } | ||||
}) | }) | ||||
Show All 12 Lines | def run_test(self): | ||||
"limited_proofid": f"{proof.limited_proofid:0{64}x}", | "limited_proofid": f"{proof.limited_proofid:0{64}x}", | ||||
"master": privkey.get_pubkey().get_bytes().hex(), | "master": privkey.get_pubkey().get_bytes().hex(), | ||||
"stake_amount": coinbase_amount, | "stake_amount": coinbase_amount, | ||||
}, | }, | ||||
"network": { | "network": { | ||||
"proof_count": 0, | "proof_count": 0, | ||||
"connected_proof_count": 0, | "connected_proof_count": 0, | ||||
"conflicting_proof_count": 0, | "conflicting_proof_count": 0, | ||||
"orphan_proof_count": 0, | |||||
"total_stake_amount": Decimal('0.00'), | "total_stake_amount": Decimal('0.00'), | ||||
"connected_stake_amount": Decimal('0.00'), | "connected_stake_amount": Decimal('0.00'), | ||||
"node_count": 0, | "node_count": 0, | ||||
"connected_node_count": 0, | "connected_node_count": 0, | ||||
"pending_node_count": 0, | "pending_node_count": 0, | ||||
} | } | ||||
}) | }) | ||||
# Mine a block to trigger proof validation | # Mine a block to trigger proof validation | ||||
node.generate(1) | node.generate(1) | ||||
self.wait_until( | self.wait_until( | ||||
lambda: node.getavalancheinfo() == handle_legacy_format({ | lambda: node.getavalancheinfo() == handle_legacy_format({ | ||||
"active": False, | "active": False, | ||||
"local": { | "local": { | ||||
"live": True, | "live": True, | ||||
"proofid": f"{proof.proofid:0{64}x}", | "proofid": f"{proof.proofid:0{64}x}", | ||||
"limited_proofid": f"{proof.limited_proofid:0{64}x}", | "limited_proofid": f"{proof.limited_proofid:0{64}x}", | ||||
"master": privkey.get_pubkey().get_bytes().hex(), | "master": privkey.get_pubkey().get_bytes().hex(), | ||||
"stake_amount": coinbase_amount, | "stake_amount": coinbase_amount, | ||||
}, | }, | ||||
"network": { | "network": { | ||||
"proof_count": 0, | "proof_count": 0, | ||||
"connected_proof_count": 0, | "connected_proof_count": 0, | ||||
"conflicting_proof_count": 0, | "conflicting_proof_count": 0, | ||||
"orphan_proof_count": 0, | |||||
"total_stake_amount": Decimal('0.00'), | "total_stake_amount": Decimal('0.00'), | ||||
"connected_stake_amount": Decimal('0.00'), | "connected_stake_amount": Decimal('0.00'), | ||||
"node_count": 0, | "node_count": 0, | ||||
"connected_node_count": 0, | "connected_node_count": 0, | ||||
"pending_node_count": 0, | "pending_node_count": 0, | ||||
} | } | ||||
}) | }) | ||||
) | ) | ||||
self.log.info("Connect a bunch of peers and nodes") | self.log.info("Connect a bunch of peers and nodes") | ||||
mock_time = int(time.time()) | mock_time = int(time.time()) | ||||
node.setmocktime(mock_time) | node.setmocktime(mock_time) | ||||
N = 10 | N = 10 | ||||
for _ in range(N): | for _ in range(N): | ||||
_privkey, _proof = gen_proof(node) | _privkey, _proof = gen_proof(node) | ||||
# For each proof, also make a conflicting one | # For each proof, also make a conflicting one | ||||
stakes = create_coinbase_stakes( | stakes = create_coinbase_stakes( | ||||
node, [node.getbestblockhash()], node.get_deterministic_priv_key().key) | node, [node.getbestblockhash()], node.get_deterministic_priv_key().key) | ||||
conflicting_proof = node.buildavalancheproof( | conflicting_proof = node.buildavalancheproof( | ||||
10, 9999, bytes_to_wif(_privkey.get_bytes()), stakes) | 10, 9999, bytes_to_wif(_privkey.get_bytes()), stakes) | ||||
# Make the proof and its conflicting proof mature | |||||
node.generate(1) | |||||
n = get_ava_p2p_interface(node) | n = get_ava_p2p_interface(node) | ||||
success = node.addavalanchenode( | success = node.addavalanchenode( | ||||
n.nodeid, _privkey.get_pubkey().get_bytes().hex(), _proof.serialize().hex()) | n.nodeid, _privkey.get_pubkey().get_bytes().hex(), _proof.serialize().hex()) | ||||
assert success is True | assert success is True | ||||
mock_time += self.conflicting_proof_cooldown | mock_time += self.conflicting_proof_cooldown | ||||
node.setmocktime(mock_time) | node.setmocktime(mock_time) | ||||
n.send_avaproof(avalanche_proof_from_hex(conflicting_proof)) | n.send_avaproof(avalanche_proof_from_hex(conflicting_proof)) | ||||
# Generate an orphan (immature) proof | |||||
_, orphan_proof = gen_proof(node) | |||||
n.send_avaproof(orphan_proof) | |||||
self.wait_until( | self.wait_until( | ||||
lambda: node.getavalancheinfo() == handle_legacy_format({ | lambda: node.getavalancheinfo() == handle_legacy_format({ | ||||
"active": True, | "active": True, | ||||
"local": { | "local": { | ||||
"live": True, | "live": True, | ||||
"proofid": f"{proof.proofid:0{64}x}", | "proofid": f"{proof.proofid:0{64}x}", | ||||
"limited_proofid": f"{proof.limited_proofid:0{64}x}", | "limited_proofid": f"{proof.limited_proofid:0{64}x}", | ||||
"master": privkey.get_pubkey().get_bytes().hex(), | "master": privkey.get_pubkey().get_bytes().hex(), | ||||
"stake_amount": coinbase_amount, | "stake_amount": coinbase_amount, | ||||
}, | }, | ||||
"network": { | "network": { | ||||
"proof_count": N, | "proof_count": N, | ||||
"connected_proof_count": N, | "connected_proof_count": N, | ||||
"conflicting_proof_count": N, | "conflicting_proof_count": N, | ||||
"orphan_proof_count": 1, | |||||
"total_stake_amount": coinbase_amount * N, | "total_stake_amount": coinbase_amount * N, | ||||
"connected_stake_amount": coinbase_amount * N, | "connected_stake_amount": coinbase_amount * N, | ||||
"node_count": N, | "node_count": N, | ||||
"connected_node_count": N, | "connected_node_count": N, | ||||
"pending_node_count": 0, | "pending_node_count": 0, | ||||
} | } | ||||
}) | }) | ||||
) | ) | ||||
Show All 15 Lines | def run_test(self): | ||||
"limited_proofid": f"{proof.limited_proofid:0{64}x}", | "limited_proofid": f"{proof.limited_proofid:0{64}x}", | ||||
"master": privkey.get_pubkey().get_bytes().hex(), | "master": privkey.get_pubkey().get_bytes().hex(), | ||||
"stake_amount": coinbase_amount, | "stake_amount": coinbase_amount, | ||||
}, | }, | ||||
"network": { | "network": { | ||||
"proof_count": N, | "proof_count": N, | ||||
"connected_proof_count": N - D, | "connected_proof_count": N - D, | ||||
"conflicting_proof_count": N, | "conflicting_proof_count": N, | ||||
"orphan_proof_count": 1, | |||||
"total_stake_amount": coinbase_amount * N, | "total_stake_amount": coinbase_amount * N, | ||||
"connected_stake_amount": coinbase_amount * (N - D), | "connected_stake_amount": coinbase_amount * (N - D), | ||||
"node_count": N - D, | "node_count": N - D, | ||||
"connected_node_count": N - D, | "connected_node_count": N - D, | ||||
"pending_node_count": 0, | "pending_node_count": 0, | ||||
} | } | ||||
}) | }) | ||||
) | ) | ||||
self.log.info("Add some pending nodes") | self.log.info("Add some pending nodes") | ||||
P = 3 | P = 3 | ||||
for _ in range(P): | for _ in range(P): | ||||
dg_priv = ECKey() | dg_priv = ECKey() | ||||
dg_priv.generate() | dg_priv.generate() | ||||
dg_pub = dg_priv.get_pubkey().get_bytes().hex() | dg_pub = dg_priv.get_pubkey().get_bytes().hex() | ||||
_privkey, _proof = gen_proof(node) | _privkey, _proof = gen_proof(node) | ||||
# Make the proof mature | |||||
node.generate(1) | |||||
delegation = node.delegateavalancheproof( | delegation = node.delegateavalancheproof( | ||||
f"{_proof.limited_proofid:0{64}x}", | f"{_proof.limited_proofid:0{64}x}", | ||||
bytes_to_wif(_privkey.get_bytes()), | bytes_to_wif(_privkey.get_bytes()), | ||||
dg_pub, | dg_pub, | ||||
None | None | ||||
) | ) | ||||
n = get_ava_p2p_interface(node) | n = get_ava_p2p_interface(node) | ||||
n.send_avahello(delegation, dg_priv) | n.send_avahello(delegation, dg_priv) | ||||
# Make sure we completed at least one time the ProcessMessage or we | # Make sure we completed at least one time the ProcessMessage or we | ||||
# might miss the last pending node for the following assert | # might miss the last pending node for the following assert | ||||
n.sync_with_ping() | n.sync_with_ping() | ||||
assert_avalancheinfo({ | assert_avalancheinfo({ | ||||
"active": True, | "active": True, | ||||
"local": { | "local": { | ||||
"live": True, | "live": True, | ||||
"proofid": f"{proof.proofid:0{64}x}", | "proofid": f"{proof.proofid:0{64}x}", | ||||
"limited_proofid": f"{proof.limited_proofid:0{64}x}", | "limited_proofid": f"{proof.limited_proofid:0{64}x}", | ||||
"master": privkey.get_pubkey().get_bytes().hex(), | "master": privkey.get_pubkey().get_bytes().hex(), | ||||
"stake_amount": coinbase_amount, | "stake_amount": coinbase_amount, | ||||
}, | }, | ||||
"network": { | "network": { | ||||
"proof_count": N, | # Orphan became mature | ||||
"proof_count": N + 1, | |||||
"connected_proof_count": N - D, | "connected_proof_count": N - D, | ||||
"conflicting_proof_count": N, | "conflicting_proof_count": N, | ||||
"total_stake_amount": coinbase_amount * N, | "orphan_proof_count": 0, | ||||
"total_stake_amount": coinbase_amount * (N + 1), | |||||
"connected_stake_amount": coinbase_amount * (N - D), | "connected_stake_amount": coinbase_amount * (N - D), | ||||
"node_count": N - D + P, | "node_count": N - D + P, | ||||
"connected_node_count": N - D, | "connected_node_count": N - D, | ||||
"pending_node_count": P, | "pending_node_count": P, | ||||
} | } | ||||
}) | }) | ||||
self.log.info("Disconnect all the nodes") | self.log.info("Disconnect all the nodes") | ||||
for n in node.p2ps: | for n in node.p2ps: | ||||
n.peer_disconnect() | n.peer_disconnect() | ||||
n.wait_for_disconnect() | n.wait_for_disconnect() | ||||
assert_avalancheinfo({ | assert_avalancheinfo({ | ||||
"active": True, | "active": True, | ||||
"local": { | "local": { | ||||
"live": True, | "live": True, | ||||
"proofid": f"{proof.proofid:0{64}x}", | "proofid": f"{proof.proofid:0{64}x}", | ||||
"limited_proofid": f"{proof.limited_proofid:0{64}x}", | "limited_proofid": f"{proof.limited_proofid:0{64}x}", | ||||
"master": privkey.get_pubkey().get_bytes().hex(), | "master": privkey.get_pubkey().get_bytes().hex(), | ||||
"stake_amount": coinbase_amount, | "stake_amount": coinbase_amount, | ||||
}, | }, | ||||
"network": { | "network": { | ||||
"proof_count": N, | "proof_count": N + 1, | ||||
"connected_proof_count": 0, | "connected_proof_count": 0, | ||||
"conflicting_proof_count": N, | "conflicting_proof_count": N, | ||||
"total_stake_amount": coinbase_amount * N, | "orphan_proof_count": 0, | ||||
"total_stake_amount": coinbase_amount * (N + 1), | |||||
"connected_stake_amount": 0, | "connected_stake_amount": 0, | ||||
"node_count": 0, | "node_count": 0, | ||||
"connected_node_count": 0, | "connected_node_count": 0, | ||||
"pending_node_count": 0, | "pending_node_count": 0, | ||||
} | } | ||||
}) | }) | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
GetAvalancheInfoTest().main() | GetAvalancheInfoTest().main() |