Page Menu
Home
Phabricator
Search
Configure Global Search
Log In
Files
F12944871
D9364.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Subscribers
None
D9364.diff
View Options
diff --git a/src/net.h b/src/net.h
--- a/src/net.h
+++ b/src/net.h
@@ -1000,6 +1000,7 @@
AvalancheState() {}
avalanche::Delegation delegation;
+ SchnorrSig sig;
};
// m_avalanche_state == nullptr if we're not using avalanche with this peer
diff --git a/src/net_processing.cpp b/src/net_processing.cpp
--- a/src/net_processing.cpp
+++ b/src/net_processing.cpp
@@ -3979,11 +3979,30 @@
pfrom.m_avalanche_state = std::make_unique<CNode::AvalancheState>();
}
+ // Store the delegation and signature for later verification.
CHashVerifier<CDataStream> verifier(&vRecv);
- avalanche::Delegation &delegation = pfrom.m_avalanche_state->delegation;
- verifier >> delegation;
+ verifier >> pfrom.m_avalanche_state->delegation;
+ SchnorrSig &sig = pfrom.m_avalanche_state->sig;
+ verifier >> sig;
+ return;
+ }
+
+ if (msg_type == NetMsgType::AVAPROOF) {
+ if (!pfrom.m_avalanche_state) {
+ // We don't support the case of a AVAPROOF received before
+ // the AVAHELLO for now. Ideally we should store all the data
+ // received, and process it after both messages were received,
+ // no matter which order they reach us.
+ return;
+ }
+ // Read the proof.
avalanche::Proof proof;
+ vRecv >> proof;
+
+ // Verify the delegation
+ const avalanche::Delegation &delegation =
+ pfrom.m_avalanche_state->delegation;
avalanche::DelegationState state;
CPubKey pubkey;
if (!delegation.verify(state, proof, pubkey)) {
@@ -3991,8 +4010,20 @@
return;
}
- SchnorrSig sig;
- verifier >> sig;
+ // Use the delegated pubkey to verify the signature received
+ // in the avahello message.
+ const uint256 hash = g_avalanche->buildRemoteSighash(&pfrom);
+
+ if (!pubkey.VerifySchnorr(hash, pfrom.m_avalanche_state->sig)) {
+ Misbehaving(pfrom, 100, "invalid-avalanche-handshake");
+ return;
+ }
+
+ // TODO:
+ // - store the proof in a proofpool
+ // - if IBD is finished, add the node
+ // - if IBD, add the node later, when we can check its proof
+ return;
}
if (msg_type == NetMsgType::AVAPOLL) {
diff --git a/test/functional/abc_p2p_avalanche.py b/test/functional/abc_p2p_avalanche.py
--- a/test/functional/abc_p2p_avalanche.py
+++ b/test/functional/abc_p2p_avalanche.py
@@ -3,6 +3,7 @@
# Distributed under the MIT software license, see the accompanying
# file COPYING or http://www.opensource.org/licenses/mit-license.php.
"""Test the resolution of forks via avalanche."""
+from io import BytesIO
import random
from test_framework.avatools import get_stakes
@@ -12,10 +13,13 @@
)
from test_framework.mininode import P2PInterface, mininode_lock
from test_framework.messages import (
+ AvalancheProof,
AvalancheResponse,
AvalancheVote,
CInv,
+ msg_avahello,
msg_avapoll,
+ msg_avaproof,
msg_tcpavaresponse,
NODE_AVALANCHE,
NODE_NETWORK,
@@ -104,6 +108,11 @@
with mininode_lock:
return self.avapolls.pop(0) if len(self.avapolls) > 0 else None
+ def send_avahello(self, hello):
+ msg = msg_avahello()
+ msg.hello = hello
+ self.send_message(msg)
+
def wait_for_avahello(self, timeout=5):
wait_until(
lambda: self.avahello is not None,
@@ -113,6 +122,11 @@
with mininode_lock:
return self.avahello
+ def send_avaproof(self, proof):
+ msg = msg_avaproof()
+ msg.proof = proof
+ self.send_message(msg)
+
class AvalancheTest(BitcoinTestFramework):
def set_test_params(self):
@@ -350,8 +364,7 @@
])
self.log.info("Test the avahello signature")
- quorum = get_quorum()
- poll_node = quorum[0]
+ poll_node = get_node()
avahello = poll_node.wait_for_avahello().hello
@@ -359,6 +372,21 @@
assert avakey.verify_schnorr(
avahello.sig, avahello.get_sighash(poll_node))
+ self.log.info("Test banning behavior on invalid avahello signature")
+ poll_node = get_node()
+ with self.nodes[0].assert_debug_log(
+ ['Misbehaving',
+ '(0 -> 100) BAN THRESHOLD EXCEEDED: invalid-avalanche-handshake']):
+ # We use the same avahello that the node previously sent to
+ # another p2p interface. The signature will not correspond to
+ # the expected message for this peer.
+ poll_node.send_avahello(avahello)
+ # The signature is checked when the delegation can be checked,
+ # after receiving a proof.
+ proof_obj = AvalancheProof()
+ proof_obj.deserialize(BytesIO(bytes.fromhex(proof)))
+ poll_node.send_avaproof(proof_obj)
+
if __name__ == '__main__':
AvalancheTest().main()
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Thu, Feb 6, 15:44 (16 h, 41 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
5082635
Default Alt Text
D9364.diff (4 KB)
Attached To
D9364: [avalanche] start implementing reception of avaproof
Event Timeline
Log In to Comment