node.rs
Overview
This file defines the GossipPeer struct and associated functionality for representing and managing gossip protocol peers within a distributed system. A gossip peer encapsulates information about a network node such as its identity, network addresses, optional proxy addresses, API sockets, and cryptographic signatures used for authentication and integrity verification.
The primary responsibilities include:
Construction and initialization of
GossipPeerinstances.Serialization and deserialization of gossip peer data into key-value pairs.
Cryptographic signing and verification of gossip peer data using Ed25519 signatures.
Integration with a
NodeStateabstraction to persist and retrieve gossip peer state.Validation of data integrity through signature verification.
This file plays a critical role in secure peer discovery and communication within the gossip protocol layer of the system.
Entities
GossipPeer<PeerId>
Represents a peer in the gossip network identified by a generic PeerId. Holds network addresses, optional API sockets, and an optional cryptographic signature.
Properties
id: PeerId— Unique identifier of the peer.advertise_addr: SocketAddr— The main network address advertised for the peer.proxies: Vec<SocketAddr>— Optional list of proxy addresses associated with the peer.bm_api_socket: Option<SocketAddr>— Optional socket address for the "bm" API (possibly a backend or management interface).bk_api_socket: Option<SocketAddr>— Optional socket address for the "bk" API.pubkey_signature: Option<(transport_layer::VerifyingKey, transport_layer::Signature)>— Optional Ed25519 public key and signature pair used for verifying the authenticity of the peer's data.
Methods
pub fn new(...) -> anyhow::Result<Self>
Creates a new GossipPeer instance from the provided parameters. Optionally signs the peer's serialized data if signing keys are provided.
Parameters:
id: PeerId— The identifier of the peer.advertise_addr: SocketAddr— The advertised address.proxies: Vec<SocketAddr>— List of proxy addresses.bm_api_socket: Option<SocketAddr>— Optional bm API socket address.bk_api_socket: Option<SocketAddr>— Optional bk API socket address.signing_keys: &[transport_layer::SigningKey]— A slice of signing keys; if non-empty, the first key is used to sign the peer's values.
Returns:
anyhow::Result<Self>— The constructedGossipPeeror an error.Usage Example:
let signing_key = transport_layer::SigningKey::generate(&mut rand::rngs::OsRng); let peer = GossipPeer::new( "peer1".to_string(), "127.0.0.1:8080".parse().unwrap(), vec![], None, None, &[signing_key], )?;
fn values(&self) -> Vec<(&'static str, String)>
Serializes the peer's fields into a vector of key-value string pairs, suitable for storage or transmission.
Returns:
Vec<(&'static str, String)>— A vector of key-value pairs representing the peer's state.This method excludes the public key signature from signing.
pub fn try_from_values<'kv>(values: impl Iterator<Item = (&'kv str, &'kv str)>) -> Option<Self>
Attempts to reconstruct a GossipPeer instance from an iterator over key-value string pairs.
Parameters:
values— An iterator providing(key, value)string pairs.
Returns:
Option<Self>— ReturnsSome(GossipPeer)if parsing and signature verification succeed, otherwiseNone.Implementation Details:
Parses each key-value pair according to expected keys.
Deserializes JSON proxies list.
Parses and verifies the public key signature if present.
Ensures required fields (
idandadvertise_addr) are present.Verifies signature against the serialized data (excluding the signature itself).
pub fn try_get_from(node_state: &NodeState) -> Option<Self>
Utility to attempt constructing a GossipPeer directly from a NodeState instance by extracting its key-value pairs.
Parameters:
node_state: &NodeState— Reference to aNodeState.
Returns:
Option<Self>— The reconstructed peer if successful.
pub fn set_to(&self, node_state: &mut NodeState)
Writes the peer's key-value pairs into a mutable NodeState instance.
Parameters:
node_state: &mut NodeState— Mutable reference to aNodeState.
This persists the peer's current state for storage or dissemination.
impl<PeerId: Display> Display for GossipPeer<PeerId>
Implements the standard Display trait, enabling formatted string representation of GossipPeer.
Example output:
GossipPeer { id: peer1, advertise_addr: 127.0.0.1:8080, proxies: [], bm_api_socket: None, bk_api_socket: None }
Free Functions
fn bytes_to_sign<'kv>(key_values: impl Iterator<Item = (&'kv str, &'kv str)>) -> Vec<u8>
Constructs the canonical byte sequence used for signing or verifying a peer's state.
Parameters:
key_values— Iterator over(key, value)pairs.
Returns:
Vec<u8>— Byte vector representing sorted key-value pairs concatenated with null separators, excluding the signature key.Implementation Detail:
Sorts keys alphabetically.
Concatenates
key\0value\0sequences for each key-value pair, skipping the signature key.
pub fn sign_gossip_node(node_state: &mut NodeState, key: transport_layer::SigningKey)
Signs the key-value pairs stored in a NodeState and writes the signature back into the state.
Parameters:
node_state: &mut NodeState— The node state to sign.key: transport_layer::SigningKey— The signing key used to generate the signature.
Behavior:
Computes the signature over the serialized key-values.
Stores the encoded public key and signature string under the
pubkey_signaturekey.
fn parse_value<T: FromStr>(name: &str, value: &str) -> Option<T>
Attempts to parse a value string into the specified type, logging a warning on failure.
Parameters:
name: &str— The name of the value (used for logging).value: &str— The string value to parse.
Returns:
Option<T>— The parsed value orNoneif parsing fails.
fn pubkey_signature_to_string(pubkey: &transport_layer::VerifyingKey, signature: &transport_layer::Signature) -> String
Encodes the public key and signature bytes into a Base64 string.
Parameters:
pubkey: &transport_layer::VerifyingKey— The Ed25519 public key.signature: &transport_layer::Signature— The Ed25519 signature.
Returns:
String— Base64-encoded concatenation of public key and signature bytes.
fn parse_pubkey_signature(s: &str) -> anyhow::Result<(transport_layer::VerifyingKey, transport_layer::Signature)>
Decodes a Base64-encoded public key and signature string back into their binary forms.
Parameters:
s: &str— Base64-encoded string.
Returns:
anyhow::Result<(VerifyingKey, Signature)>— The decoded public key and signature or an error if invalid.
Implementation Details and Algorithms
Signature Generation and Verification:
The peer's key-value pairs are serialized into a canonical form by sorting keys alphabetically and concatenating keys and values with null separators.
The signature covers all fields except the signature itself, preventing tampering.
Ed25519 algorithms (via
ed25519_dalek) are used for signing and verifying.The public key and signature are stored together in Base64 encoding.
Serialization:
Proxies are serialized as JSON strings.
Addresses are serialized using
SocketAddr'sto_string()method.Optional values are included conditionally.
Parsing uses Rust's
FromStrtrait for address and ID deserialization.
Robustness:
The
try_from_valuesmethod logs warnings on invalid values.Signature verification failure causes deserialization to fail, ensuring integrity.
Generic Peer ID:
The
PeerIdtype is generic but must implementFromStrandDisplaytraits, allowing flexible peer identification.
Interaction with Other Parts of the System
NodeStateIntegration:The
GossipPeerinteracts closely with aNodeStateabstraction, which manages key-value storage of node metadata.Methods
try_get_fromandset_toread from and write toNodeStateinstances.
Cryptographic Components:
Relies on
transport_layer::SigningKey,VerifyingKey, andSignaturetypes for Ed25519 signing.Uses
ed25519_dalekfor cryptographic signing and verification.
Base64 Encoding:
Uses
base64crate with standard engine for encoding/decoding public key signatures.
Logging and Error Handling:
Uses the
tracingcrate to log warnings and errors encountered during parsing.
Visual Diagram
classDiagram
class GossipPeer {
+id: PeerId
+advertise_addr: SocketAddr
+proxies: Vec<SocketAddr>
+bm_api_socket: Option<SocketAddr>
+bk_api_socket: Option<SocketAddr>
+pubkey_signature: Option<(VerifyingKey, Signature)>
+new()
+values()
+try_from_values()
+try_get_from()
+set_to()
+fmt()
}
class NodeState {
<<external>>
+key_values()
+set()
}
class transport_layer::SigningKey {
<<external>>
+sign()
+verifying_key()
}
class transport_layer::VerifyingKey {
<<external>>
+verify()
+as_bytes()
}
class transport_layer::Signature {
<<external>>
+to_bytes()
}
GossipPeer ..> "1" NodeState : reads/writes
GossipPeer ..> transport_layer::SigningKey : uses for signing
GossipPeer ..> transport_layer::VerifyingKey : verifies signatures
GossipPeer ..> transport_layer::Signature : holds signature
Testing
The included unit test test_signature verifies:
Creation of a
GossipPeerwithout signing keys.Round-trip serialization and deserialization via
values()andtry_from_values().Creation and verification of a signed
GossipPeer.Detection of invalid or tampered signatures leading to
Noneresult on deserialization.
Key Constants
Constant | Description |
|---|---|
| Key for advertised address ("node_advertise_addr") |
| Key for bk API socket address |
| Key for bm API socket address |
| Key for peer ID ("node_id") |
| Key for proxy addresses ("node_proxies") |
Key for public key signature ("pubkey_signature") |
References
For details on the cryptographic signing algorithms and Ed25519 usage, see
ed25519_dalek.For the gossip protocol state management, refer to
NodeState.For Base64 encoding/decoding, refer to
base64.For address and string parsing, see Rust's
FromStrtrait andSocketAddr.For logging, see
tracing.