[Fix/Feat] Asymmetrical Noise-XX handshake for the validators - #4354
Conversation
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
|
Can you enable the |
There was a problem hiding this comment.
Looks amazing!
It would be great if we can truly consider the issues closed with one PR (ignoring the pruning of dead code). Therefore:
- should we also adjust the gateway handshake done by the bootstrap nodes?
- either we:
- keep
NOISE_HANDSHAKE_ACTIVATION_HEIGHT=V19and introduce a newNOISE_HANDSHAKE_DEACTIVATION_HEIGHT=V20. - replace
NOISE_HANDSHAKE_ACTIVATION_HEIGHT=V19to aNOISE_HANDSHAKE_DEACTIVATION_HEIGHT=V19. As soon as a validator has upgraded, they attempt a noise handshake. If it fails, they retry with the legacy handshake. AtNOISE_HANDSHAKE_DEACTIVATION_HEIGHT==V19we assume all nodes upgraded and everyone is using noise.
- keep
…y for now) Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
1456434 to
9838234
Compare
done in 5fbacba
I introduced 2 |
|
In the latest changes, the handshake message size was further restricted down to 1KiB, minimizing DoS exposure while still leaving ample room if we need to add any more fields in the future; extending it is backward-compatible, too. |
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
9838234 to
e56706a
Compare
|
It seems like that CI failure is just a re-insertion of a known cert into the DAG, which I believe could safely be downgraded in terms of its log level. |
cbeck88
left a comment
There was a problem hiding this comment.
looks good to me, thank you for doing this
There was a problem hiding this comment.
Pull request overview
This PR introduces an optional Noise-XX-based handshake for validator gateway connections, binding each side’s Aleo identity to the session by signing the running Noise handshake hash, while keeping the legacy handshake for rolling upgrades. It also includes a drive-by hardening to EventCodec’s encoder behavior.
Changes:
- Add shared Noise-XX handshake plumbing (
node/network::noise) and integrate it into gateway and bootstrap-client handshake paths with legacy fallback. - Add end-to-end tests for gateway and bootstrap-client Noise handshakes (including relay resistance and “drop-before-reply” cheap checks).
- Harden
EventCodecencoding to avoid accidentally merging multiple buffered frames into one.
Reviewed changes
Copilot reviewed 14 out of 15 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| node/tests/bootstrap_handshake.rs | New integration tests driving the bootstrap client’s Noise handshake path. |
| node/src/bootstrap_client/handshake.rs | Adds protocol detection + Noise responder handshake for bootstrap clients; legacy path now receives consumed prefix. |
| node/router/messages/src/lib.rs | Extends protocol version mapping to include ConsensusVersion::V19 and V20. |
| node/network/src/peer.rs | Makes ConnectionMode explicitly u8-serialized to allow embedding in handshake hints. |
| node/network/src/noise.rs | New Noise-XX session implementation (magic prefix, framing, PendingSession pre-DH payload access, tests). |
| node/network/src/lib.rs | Exposes the new noise module. |
| node/network/Cargo.toml | Adds dependencies needed for Noise plumbing (snow, bytes, extra tokio features, etc.). |
| node/bft/tests/gateway_noise.rs | New end-to-end tests for gateway Noise handshake, legacy fallback, and relay prevention. |
| node/bft/src/gateway.rs | Integrates Noise handshake (initiator + responder), protocol detection, activation/expiry gating, and stream handoff behavior. |
| node/bft/events/src/helpers/mod.rs | Exposes new handshake payload types/helpers. |
| node/bft/events/src/helpers/handshake.rs | Defines Noise handshake payload types (hint/info/proof), domain separator, and payload encode/decode helpers. |
| node/bft/events/src/helpers/codec.rs | Fixes EventCodec encoder to frame only newly-appended bytes; adds regression test. |
| node/bft/events/Cargo.toml | Adds dependency on snarkos-node-network (for ConnectionMode in handshake hint encoding). |
| Cargo.toml | Switches snarkvm workspace dependency to a git revision; adds workspace dependency on snow. |
| Cargo.lock | Updates lockfile for new deps and the snarkvm git source. |
Suppressed comments (1)
node/bft/src/gateway.rs:163
- If mainnet is not meant to enforce the Noise handshake yet, expiring the legacy handshake at
ConsensusVersion::V20will eventually disconnect still-legacy validators at the V20 height. Consider leaving the expiry unset (None) until the network-wide migration plan is finalized and the router handshake is also converted (as noted in the comment above this constant).
/// validator that has not yet reached the activation still dials with the legacy handshake and would
/// be shut out. Note also that the same relay is reachable through the router's handshake, which
/// signs a byte-identical message with the same account key, so the gateway cannot be the last part
/// of this to be converted.
const LEGACY_HANDSHAKE_EXPIRY: Option<ConsensusVersion> = Some(ConsensusVersion::V20);
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
|
The |
|
Some Opus 5 findings I think are worth to close: 3. Medium — the initiator never checks it reached the validator it dialedgateway.rs This is pre-existing in the legacy handshake, but identity binding makes it cheap to close: the gateway generally knows the address it expects (Peer::last_known_aleo_addr, plus the validator set it dials from), so compare it to peer_info.address. 5. Low — the "no elliptic curve operations" claim is overstatedParsing the hint decodes an Address. noise.rs:104 and gateway.rs:1918 shouldn't say "no elliptic curve operations at all". |
Signed-off-by: ljedrz <ljedrz@users.noreply.github.com>
Replaces the gateway's challenge-response handshake with one built on the Noise XX pattern, where each side binds its Aleo identity to the session by signing the running Noise handshake hash. Identity is still the Aleo account key - the Noise static keys are per-connection and exist only to give the pattern a channel to bind to. The post-handshake traffic remains unencrypted.
The legacy handshake is still accepted, so validators can be upgraded one at a time. Guarded by
NOISE_HANDSHAKE_ACTIVATION_HEIGHT.Over 50% of the new code is tests, and much of the new plumbing can be reused if we want to utilize this handshake pattern with other node types as well.
Benefits:
As a small drive-by, there's also a hardening for the
EventCodec's encoder, in its own commit.CC #4140