Changeset View
Changeset View
Standalone View
Standalone View
test/functional/abc_rpc_getavalancheinfo.py
#!/usr/bin/env python3 | #!/usr/bin/env python3 | ||||
# Copyright (c) 2022 The Bitcoin developers | # Copyright (c) 2022 The Bitcoin developers | ||||
# Distributed under the MIT software license, see the accompanying | # Distributed under the MIT software license, see the accompanying | ||||
# file COPYING or http://www.opensource.org/licenses/mit-license.php. | # file COPYING or http://www.opensource.org/licenses/mit-license.php. | ||||
"""Test the getavalancheinfo RPC.""" | """Test the getavalancheinfo RPC.""" | ||||
import time | |||||
from decimal import Decimal | from decimal import Decimal | ||||
from test_framework.address import ADDRESS_ECREG_UNSPENDABLE | from test_framework.address import ADDRESS_ECREG_UNSPENDABLE | ||||
from test_framework.avatools import gen_proof, get_ava_p2p_interface | from test_framework.avatools import ( | ||||
avalanche_proof_from_hex, | |||||
create_coinbase_stakes, | |||||
gen_proof, | |||||
get_ava_p2p_interface, | |||||
) | |||||
from test_framework.key import ECKey | from test_framework.key import ECKey | ||||
from test_framework.messages import LegacyAvalancheProof | from test_framework.messages import LegacyAvalancheProof | ||||
from test_framework.test_framework import BitcoinTestFramework | from test_framework.test_framework import BitcoinTestFramework | ||||
from test_framework.util import assert_equal | from test_framework.util import assert_equal | ||||
from test_framework.wallet_util import bytes_to_wif | from test_framework.wallet_util import bytes_to_wif | ||||
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.extra_args = [[ | self.extra_args = [[ | ||||
'-enableavalanche=1', | '-enableavalanche=1', | ||||
'-enableavalancheproofreplacement=1', | |||||
f'-avalancheconflictingproofcooldown={self.conflicting_proof_cooldown}', | |||||
'-avaproofstakeutxoconfirmations=1', | '-avaproofstakeutxoconfirmations=1', | ||||
'-avacooldown=', | '-avacooldown=', | ||||
'-avatimeout=100', | '-avatimeout=100', | ||||
'-enableavalanchepeerdiscovery=1', | '-enableavalanchepeerdiscovery=1', | ||||
'-avaminquorumstake=250000000', | '-avaminquorumstake=250000000', | ||||
'-avaminquorumconnectedstakeratio=0.9', | '-avaminquorumconnectedstakeratio=0.9', | ||||
]] | ]] | ||||
Show All 21 Lines | def run_test(self): | ||||
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, | |||||
"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 11 Lines | def run_test(self): | ||||
"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, | |||||
"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, | |||||
"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()) | |||||
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 | |||||
stakes = create_coinbase_stakes( | |||||
node, [node.getbestblockhash()], node.get_deterministic_priv_key().key) | |||||
conflicting_proof = node.buildavalancheproof( | |||||
10, 9999, bytes_to_wif(_privkey.get_bytes()), stakes) | |||||
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 | ||||
assert_avalancheinfo({ | mock_time += self.conflicting_proof_cooldown | ||||
node.setmocktime(mock_time) | |||||
n.send_avaproof(avalanche_proof_from_hex(conflicting_proof)) | |||||
self.wait_until( | |||||
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, | |||||
"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, | ||||
} | } | ||||
}) | }) | ||||
) | |||||
self.log.info("Disconnect some nodes") | self.log.info("Disconnect some nodes") | ||||
D = 3 | D = 3 | ||||
for _ in range(D): | for _ in range(D): | ||||
n = node.p2ps.pop() | n = node.p2ps.pop() | ||||
n.peer_disconnect() | n.peer_disconnect() | ||||
n.wait_for_disconnect() | n.wait_for_disconnect() | ||||
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 - D, | "connected_proof_count": N - D, | ||||
"conflicting_proof_count": N, | |||||
"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) | ||||
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) | ||||
Show All 9 Lines | def run_test(self): | ||||
"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 - D, | "connected_proof_count": N - D, | ||||
"conflicting_proof_count": N, | |||||
"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 + P, | "node_count": N - D + P, | ||||
"connected_node_count": N - D, | "connected_node_count": N - D, | ||||
"pending_node_count": P, | "pending_node_count": P, | ||||
} | } | ||||
}) | }) | ||||
Show All 10 Lines | def run_test(self): | ||||
"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": 0, | "connected_proof_count": 0, | ||||
"conflicting_proof_count": N, | |||||
"total_stake_amount": coinbase_amount * N, | "total_stake_amount": coinbase_amount * N, | ||||
"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() |