Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F13115681
D11048.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
14 KB
Subscribers
None
D11048.diff
View Options
diff --git a/test/functional/abc_p2p_avalanche_proof_voting.py b/test/functional/abc_p2p_avalanche_proof_voting.py
--- a/test/functional/abc_p2p_avalanche_proof_voting.py
+++ b/test/functional/abc_p2p_avalanche_proof_voting.py
@@ -13,13 +13,15 @@
)
from test_framework.key import ECPubKey
from test_framework.messages import (
+ MSG_AVA_PROOF,
+ AvalancheProofVoteResponse,
AvalancheVote,
AvalancheVoteError,
FromHex,
LegacyAvalancheProof,
)
from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_raises_rpc_error, try_rpc
+from test_framework.util import assert_equal, assert_raises_rpc_error, try_rpc
from test_framework.wallet_util import bytes_to_wif
QUORUM_NODE_COUNT = 16
@@ -108,6 +110,7 @@
self.poll_tests(node)
self.update_tests(node)
+ self.vote_tests(node)
def poll_tests(self, node):
proof_seq10 = self.build_conflicting_proof(node, 10)
@@ -280,6 +283,126 @@
node.getrawavalancheproof,
f"{proofid_seq50:0{64}x}")
+ def vote_tests(self, node):
+ self.restart_node(0, extra_args=['-enableavalanche=1',
+ '-avacooldown=0',
+ '-avalancheconflictingproofcooldown=0',
+ '-whitelist=noban@127.0.0.1', ])
+
+ ava_node = get_ava_p2p_interface(node)
+
+ # Generate coinbases to use for stakes
+ stakes_key = node.get_deterministic_priv_key()
+ blocks = node.generatetoaddress(4, stakes_key.address)
+
+ # Get the ava key so we can verify signatures.
+ ava_key = ECPubKey()
+ ava_key.set(bytes.fromhex(node.getavalanchekey()))
+
+ def create_proof(stakes):
+ proof = node.buildavalancheproof(11, 12, self.privkey_wif, stakes)
+ proof_id = FromHex(LegacyAvalancheProof(), proof).proofid
+ return proof, proof_id
+
+ # proof_0 is valid right now
+ stakes_0 = create_coinbase_stakes(node, [blocks[0]], stakes_key.key)
+ proof_0, proof_0_id = create_proof(stakes_0)
+
+ # proof_1 is valid right now, and from different stakes
+ stakes_1 = create_coinbase_stakes(node, [blocks[1]], stakes_key.key)
+ proof_1, proof_1_id = create_proof(stakes_1)
+
+ # proof_2 is an orphan because the stake UTXO is unknown
+ stakes_2 = create_coinbase_stakes(node, [blocks[2]], stakes_key.key)
+ stakes_2[0]['height'] = 5
+ proof_2, proof_2_id = create_proof(stakes_2)
+
+ # proof_3 conflicts with proof_0 and proof_1
+ stakes_3 = create_coinbase_stakes(
+ node, [blocks[0], blocks[1]], stakes_key.key)
+ proof_3, proof_3_id = create_proof(stakes_3)
+
+ # proof_4 is invalid and should be rejected
+ stakes_4 = create_coinbase_stakes(node, [blocks[3]], stakes_key.key)
+ stakes_4[0]['amount'] -= 100000
+ proof_4, proof_4_id = create_proof(stakes_4)
+
+ # Create a helper to issue a poll and validate the responses
+ def poll_assert_response(expected):
+ # Issue a poll for each proof
+ self.log.info("Trigger polling from the node...")
+ ava_node.send_poll(
+ [proof_0_id, proof_1_id, proof_2_id, proof_3_id, proof_4_id],
+ MSG_AVA_PROOF)
+ response = ava_node.wait_for_avaresponse()
+ r = response.response
+
+ # Verify signature
+ assert ava_key.verify_schnorr(response.sig, r.get_hash())
+
+ # Verify votes
+ votes = r.votes
+ assert_equal(len(votes), len(expected))
+ for i in range(0, len(votes)):
+ assert_equal(repr(votes[i]), repr(expected[i]))
+
+ # Check that all proofs start unknown
+ poll_assert_response([
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_0_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_1_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_2_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
+
+ # Send the first proof. Nodes should now respond that it's accepted
+ node.sendavalancheproof(proof_0)
+ poll_assert_response([
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_1_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_2_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
+
+ # Send and check the 2nd proof. Nodes should now respond that it's
+ # accepted
+ node.sendavalancheproof(proof_1)
+ poll_assert_response([
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_2_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
+
+ # The next proof should be rejected/put in the orphan pool
+ ava_node.send_proof(FromHex(LegacyAvalancheProof(), proof_2))
+ poll_assert_response([
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
+ AvalancheVote(AvalancheProofVoteResponse.ORPHAN, proof_2_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
+
+ # The next proof should be rejected and marked as a conflicting proof
+ assert_raises_rpc_error(-8,
+ "The proof has conflicting utxo with an existing proof",
+ node.sendavalancheproof, proof_3)
+ poll_assert_response([
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
+ AvalancheVote(AvalancheProofVoteResponse.ORPHAN, proof_2_id),
+ AvalancheVote(AvalancheProofVoteResponse.CONFLICT, proof_3_id),
+ AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
+
+ # The final proof should be permanently rejected for being completely
+ # invalid
+ ava_node.send_proof(FromHex(LegacyAvalancheProof(), proof_4))
+ poll_assert_response([
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
+ AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
+ AvalancheVote(AvalancheProofVoteResponse.ORPHAN, proof_2_id),
+ AvalancheVote(AvalancheProofVoteResponse.CONFLICT, proof_3_id),
+ AvalancheVote(AvalancheProofVoteResponse.REJECTED, proof_4_id)])
+
if __name__ == '__main__':
AvalancheProofVotingTest().main()
diff --git a/test/functional/abc_p2p_avalanche_voting_proofs.py b/test/functional/abc_p2p_avalanche_voting_proofs.py
deleted file mode 100755
--- a/test/functional/abc_p2p_avalanche_voting_proofs.py
+++ /dev/null
@@ -1,163 +0,0 @@
-#!/usr/bin/env python3
-# Copyright (c) 2020-2021 The Bitcoin developers
-# Distributed under the MIT software license, see the accompanying
-# file COPYING or http://www.opensource.org/licenses/mit-license.php.
-"""Test the polling of Avalanche stake proofs."""
-
-from test_framework.avatools import (
- create_coinbase_stakes,
- get_ava_p2p_interface,
-)
-from test_framework.key import ECKey, ECPubKey
-from test_framework.messages import (
- MSG_AVA_PROOF,
- AvalancheProofVoteResponse,
- AvalancheVote,
- FromHex,
- LegacyAvalancheProof,
-)
-from test_framework.test_framework import BitcoinTestFramework
-from test_framework.util import assert_equal, assert_raises_rpc_error
-from test_framework.wallet_util import bytes_to_wif
-
-
-class AvalancheTest(BitcoinTestFramework):
- def set_test_params(self):
- self.setup_clean_chain = True
- self.num_nodes = 1
- self.extra_args = [
- [
- '-enableavalanche=1',
- '-avacooldown=0',
- '-avalancheconflictingproofcooldown=0',
- '-whitelist=noban@127.0.0.1',
- ],
- ]
- self.supports_cli = False
-
- def run_test(self):
- node = self.nodes[0]
- ava_node = get_ava_p2p_interface(self.nodes[0])
-
- # Generate coinbases to use for stakes
- stakes_key = node.get_deterministic_priv_key()
- blocks = node.generatetoaddress(4, stakes_key.address)
-
- # Get the ava key so we can verify signatures.
- ava_key = ECPubKey()
- ava_key.set(bytes.fromhex(node.getavalanchekey()))
-
- # Get stakes key so we can sign stakes
- priv_key = ECKey()
- priv_key.set(bytes.fromhex(
- "12b004fff7f4b69ef8650e767f18f11ede158148b425660723b9f9a66e61f747"
- ), True)
- master_key = bytes_to_wif(priv_key.get_bytes())
-
- def create_proof(stakes):
- proof = node.buildavalancheproof(11, 12, master_key, stakes)
- proof_id = FromHex(LegacyAvalancheProof(), proof).proofid
- return proof, proof_id
-
- # proof_0 is valid right now
- stakes_0 = create_coinbase_stakes(node, [blocks[0]], stakes_key.key)
- proof_0, proof_0_id = create_proof(stakes_0)
-
- # proof_1 is valid right now, and from different stakes
- stakes_1 = create_coinbase_stakes(node, [blocks[1]], stakes_key.key)
- proof_1, proof_1_id = create_proof(stakes_1)
-
- # proof_2 is an orphan because the stake UTXO is unknown
- stakes_2 = create_coinbase_stakes(node, [blocks[2]], stakes_key.key)
- stakes_2[0]['height'] = 5
- proof_2, proof_2_id = create_proof(stakes_2)
-
- # proof_3 conflicts with proof_0 and proof_1
- stakes_3 = create_coinbase_stakes(
- node, [blocks[0], blocks[1]], stakes_key.key)
- proof_3, proof_3_id = create_proof(stakes_3)
-
- # proof_4 is invalid and should be rejected
- stakes_4 = create_coinbase_stakes(node, [blocks[3]], stakes_key.key)
- stakes_4[0]['amount'] -= 100000
- proof_4, proof_4_id = create_proof(stakes_4)
-
- # Create a helper to issue a poll and validate the responses
- def poll_assert_response(expected):
- # Issue a poll for each proof
- self.log.info("Trigger polling from the node...")
- ava_node.send_poll(
- [proof_0_id, proof_1_id, proof_2_id, proof_3_id, proof_4_id],
- MSG_AVA_PROOF)
- response = ava_node.wait_for_avaresponse()
- r = response.response
-
- # Verify signature
- assert ava_key.verify_schnorr(response.sig, r.get_hash())
-
- # Verify votes
- votes = r.votes
- assert_equal(len(votes), len(expected))
- for i in range(0, len(votes)):
- assert_equal(repr(votes[i]), repr(expected[i]))
-
- # Check that all proofs start unknown
- poll_assert_response([
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_0_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_1_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_2_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
-
- # Send the first proof. Nodes should now respond that it's accepted
- node.sendavalancheproof(proof_0)
- poll_assert_response([
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_1_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_2_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
-
- # Send and check the 2nd proof. Nodes should now respond that it's
- # accepted
- node.sendavalancheproof(proof_1)
- poll_assert_response([
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_2_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
-
- # The next proof should be rejected/put in the orphan pool
- ava_node.send_proof(FromHex(LegacyAvalancheProof(), proof_2))
- poll_assert_response([
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
- AvalancheVote(AvalancheProofVoteResponse.ORPHAN, proof_2_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_3_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
-
- # The next proof should be rejected and marked as a conflicting proof
- assert_raises_rpc_error(-8,
- "The proof has conflicting utxo with an existing proof",
- node.sendavalancheproof, proof_3)
- poll_assert_response([
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
- AvalancheVote(AvalancheProofVoteResponse.ORPHAN, proof_2_id),
- AvalancheVote(AvalancheProofVoteResponse.CONFLICT, proof_3_id),
- AvalancheVote(AvalancheProofVoteResponse.UNKNOWN, proof_4_id)])
-
- # The final proof should be permanently rejected for being completely
- # invalid
- ava_node.send_proof(FromHex(LegacyAvalancheProof(), proof_4))
- poll_assert_response([
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_0_id),
- AvalancheVote(AvalancheProofVoteResponse.ACTIVE, proof_1_id),
- AvalancheVote(AvalancheProofVoteResponse.ORPHAN, proof_2_id),
- AvalancheVote(AvalancheProofVoteResponse.CONFLICT, proof_3_id),
- AvalancheVote(AvalancheProofVoteResponse.REJECTED, proof_4_id)])
-
-
-if __name__ == '__main__':
- AvalancheTest().main()
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sat, Mar 1, 11:43 (6 h, 48 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5174967
Default Alt Text
D11048.diff (14 KB)
Attached To
D11048: [avalanche] Merge the avalanche voting tests
Event Timeline
Log In to Comment