pub struct ChainId([u8; 32]);
Expand description
Unique identifier for a Mina blockchain network.
ChainId
is a 32-byte cryptographic hash that uniquely identifies a
specific Mina blockchain network. It ensures network isolation by preventing
nodes from different chains (mainnet, devnet, custom testnets) from
connecting to each other.
§Security Properties
The chain ID provides several security guarantees:
- Deterministic: Always produces the same ID for identical protocol parameters
- Collision Resistant: Uses Blake2b hashing to prevent ID conflicts
- Tamper Evident: Any change to protocol parameters changes the chain ID
- Network Isolation: Incompatible networks cannot connect accidentally
§Computation Method
Chain IDs are computed using ChainId::compute()
from these inputs:
- Constraint System Digests: MD5 hashes of SNARK constraint systems
- Genesis State Hash: Hash of the initial blockchain state
- Genesis Constants: Protocol timing and consensus parameters
- Protocol Versions: Transaction and network protocol versions
- Transaction Pool Size: Maximum mempool configuration
The computation uses Blake2b-256 to hash these components in a specific order, ensuring reproducible results across different implementations.
§Network Usage
Chain IDs are used throughout the networking stack:
- Peer Discovery: Nodes broadcast their chain ID during discovery
- Connection Handshakes: WebRTC offers include chain ID for validation
- Private Networks:
preshared_key()
generates libp2p private network keys - Protocol Compatibility: Ensures all peers use compatible protocol versions
§Serialization Formats
Chain IDs support multiple serialization formats:
- Hex String: Human-readable format for configuration files
- Binary: 32-byte array for network transmission
- JSON: String representation for APIs and debugging
§Example Usage
use openmina_core::{ChainId, MAINNET_CHAIN_ID};
// Use predefined mainnet ID
let mainnet = MAINNET_CHAIN_ID;
println!("Mainnet: {}", mainnet.to_hex());
// Parse from configuration
let custom_id = ChainId::from_hex("29936104443aaf264a7f0192ac64b1c7173198c1ed404c1bcff5e562e05eb7f6")?;
// Generate private network key
let psk = mainnet.preshared_key();
Tuple Fields§
§0: [u8; 32]
Implementations§
Source§impl ChainId
impl ChainId
Sourcepub fn compute(
constraint_system_digests: &[[u8; 16]],
genesis_state_hash: &StateHash,
genesis_constants: &MinaBaseProtocolConstantsCheckedValueStableV1,
protocol_transaction_version: u8,
protocol_network_version: u8,
tx_max_pool_size: &UnsignedExtendedUInt32StableV1,
) -> ChainId
pub fn compute( constraint_system_digests: &[[u8; 16]], genesis_state_hash: &StateHash, genesis_constants: &MinaBaseProtocolConstantsCheckedValueStableV1, protocol_transaction_version: u8, protocol_network_version: u8, tx_max_pool_size: &UnsignedExtendedUInt32StableV1, ) -> ChainId
Computes a chain ID from protocol parameters and network configuration.
This method creates a deterministic 32-byte chain identifier by hashing all the fundamental parameters that define a Mina blockchain network. Any change to these parameters will result in a different chain ID, ensuring network isolation and protocol compatibility.
§Parameters
constraint_system_digests
- MD5 hashes of the SNARK constraint systems used for transaction and block verificationgenesis_state_hash
- Hash of the initial blockchain stategenesis_constants
- Protocol constants including timing parameters, consensus settings, and economic parametersprotocol_transaction_version
- Version number of the transaction protocolprotocol_network_version
- Version number of the network protocoltx_max_pool_size
- Maximum number of transactions in the mempool
§Returns
A new ChainId
representing the unique identifier for this network
configuration.
§Algorithm
The computation process:
- Hash all constraint system digests into a combined string
- Hash the genesis constants with transaction pool size
- Create Blake2b-256 hash of:
- Genesis state hash (as string)
- Combined constraint system hash
- Genesis constants hash (as hex)
- Protocol transaction version (as MD5 hash)
- Protocol network version (as MD5 hash)
§Example
use openmina_core::ChainId;
use mina_p2p_messages::v2::UnsignedExtendedUInt32StableV1;
let chain_id = ChainId::compute(
&constraint_digests,
&genesis_hash,
&protocol_constants,
1, // transaction version
1, // network version
&UnsignedExtendedUInt32StableV1::from(3000),
);
Generates a preshared key for libp2p private networking.
This method creates a cryptographic key used by libp2p’s private network (Pnet) protocol to ensure only nodes with the same chain ID can connect. The preshared key provides an additional layer of network isolation beyond basic chain ID validation.
§Algorithm
The preshared key is computed as:
Blake2b-256("/coda/0.0.1/" + chain_id_hex)
The “/coda/0.0.1/” prefix is a protocol identifier that ensures the preshared key is unique to the Mina protocol and not accidentally compatible with other systems.
§Returns
A 32-byte array containing the preshared key for this chain ID.
§Usage
This key is used to configure libp2p’s private network transport, which encrypts all network traffic and prevents unauthorized nodes from joining the network even if they know peer addresses.
§Example
use openmina_core::MAINNET_CHAIN_ID;
let psk = MAINNET_CHAIN_ID.preshared_key();
// Use psk to configure libp2p Pnet transport
Sourcepub fn to_hex(&self) -> String
pub fn to_hex(&self) -> String
Converts the chain ID to a hexadecimal string representation.
This method creates a lowercase hex string of the 32-byte chain ID, suitable for display, logging, configuration files, and JSON serialization.
§Returns
A 64-character hexadecimal string representing the chain ID.
§Example
use openmina_core::MAINNET_CHAIN_ID;
let hex_id = MAINNET_CHAIN_ID.to_hex();
assert_eq!(hex_id.len(), 64);
println!("Mainnet ID: {}", hex_id);
Sourcepub fn from_hex(s: &str) -> Result<ChainId, FromHexError>
pub fn from_hex(s: &str) -> Result<ChainId, FromHexError>
Parses a chain ID from a hexadecimal string.
This method converts a hex string back into a ChainId
instance.
The input string must represent exactly 32 bytes (64 hex characters).
Case-insensitive parsing is supported.
§Parameters
s
- A hexadecimal string representing the chain ID
§Returns
Ok(ChainId)
if the string is valid 64-character hexErr(hex::FromHexError)
if the string is invalid or wrong length
§Errors
This method returns an error if:
- The string contains non-hexadecimal characters
- The string length is not exactly 64 characters
- The string represents fewer than 32 bytes
§Example
use openmina_core::ChainId;
let chain_id = ChainId::from_hex(
"a7351abc7ddf2ea92d1b38cc8e636c271c1dfd2c081c637f62ebc2af34eb7cc1"
)?;
Sourcepub fn from_bytes(bytes: &[u8]) -> ChainId
pub fn from_bytes(bytes: &[u8]) -> ChainId
Creates a chain ID from raw bytes.
This method constructs a ChainId
from a byte slice, taking the first
32 bytes as the chain identifier. If the input has fewer than 32 bytes,
the remaining bytes are zero-padded.
§Parameters
bytes
- A byte slice containing at least 32 bytes
§Returns
A new ChainId
instance created from the input bytes.
§Panics
This method will panic if the input slice has fewer than 32 bytes.
§Example
use openmina_core::ChainId;
let bytes = [0u8; 32]; // All zeros for testing
let chain_id = ChainId::from_bytes(&bytes);
Trait Implementations§
Source§impl<'de> Deserialize<'de> for ChainId
impl<'de> Deserialize<'de> for ChainId
Source§fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error>
impl Eq for ChainId
impl StructuralPartialEq for ChainId
Auto Trait Implementations§
impl Freeze for ChainId
impl RefUnwindSafe for ChainId
impl Send for ChainId
impl Sync for ChainId
impl Unpin for ChainId
impl UnwindSafe for ChainId
Blanket Implementations§
§impl<A, T> AsBits<T> for A
impl<A, T> AsBits<T> for A
§impl<T> BinProtSize for Twhere
T: BinProtWrite,
impl<T> BinProtSize for Twhere
T: BinProtWrite,
fn binprot_size(&self) -> usize
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Conv for T
impl<T> Conv for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.§impl<T> FmtForward for T
impl<T> FmtForward for T
§fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
fn fmt_binary(self) -> FmtBinary<Self>where
Self: Binary,
self
to use its Binary
implementation when Debug
-formatted.§fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
fn fmt_display(self) -> FmtDisplay<Self>where
Self: Display,
self
to use its Display
implementation when
Debug
-formatted.§fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
fn fmt_lower_exp(self) -> FmtLowerExp<Self>where
Self: LowerExp,
self
to use its LowerExp
implementation when
Debug
-formatted.§fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
fn fmt_lower_hex(self) -> FmtLowerHex<Self>where
Self: LowerHex,
self
to use its LowerHex
implementation when
Debug
-formatted.§fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
fn fmt_octal(self) -> FmtOctal<Self>where
Self: Octal,
self
to use its Octal
implementation when Debug
-formatted.§fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
fn fmt_pointer(self) -> FmtPointer<Self>where
Self: Pointer,
self
to use its Pointer
implementation when
Debug
-formatted.§fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
fn fmt_upper_exp(self) -> FmtUpperExp<Self>where
Self: UpperExp,
self
to use its UpperExp
implementation when
Debug
-formatted.§fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
fn fmt_upper_hex(self) -> FmtUpperHex<Self>where
Self: UpperHex,
self
to use its UpperHex
implementation when
Debug
-formatted.§fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
fn fmt_list(self) -> FmtList<Self>where
&'a Self: for<'a> IntoIterator,
Source§impl<T> FromBinProtStream for Twhere
T: BinProtRead,
impl<T> FromBinProtStream for Twhere
T: BinProtRead,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
§impl<T> Pipe for Twhere
T: ?Sized,
impl<T> Pipe for Twhere
T: ?Sized,
§fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> Rwhere
Self: Sized,
§fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
fn pipe_ref_mut<'a, R>(&'a mut self, func: impl FnOnce(&'a mut Self) -> R) -> Rwhere
R: 'a,
self
and passes that borrow into the pipe function. Read more§fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
fn pipe_borrow<'a, B, R>(&'a self, func: impl FnOnce(&'a B) -> R) -> R
§fn pipe_borrow_mut<'a, B, R>(
&'a mut self,
func: impl FnOnce(&'a mut B) -> R,
) -> R
fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
§fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
self
, then passes self.as_ref()
into the pipe function.§fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
fn pipe_as_mut<'a, U, R>(&'a mut self, func: impl FnOnce(&'a mut U) -> R) -> R
self
, then passes self.as_mut()
into the pipe
function.§fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
fn pipe_deref<'a, T, R>(&'a self, func: impl FnOnce(&'a T) -> R) -> R
self
, then passes self.deref()
into the pipe function.§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> Tap for T
impl<T> Tap for T
§fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
Borrow<B>
of a value. Read more§fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
BorrowMut<B>
of a value. Read more§fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
AsRef<R>
view of a value. Read more§fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
AsMut<R>
view of a value. Read more§fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
Deref::Target
of a value. Read more§fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
Deref::Target
of a value. Read more§fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self
.tap()
only in debug builds, and is erased in release builds.§fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self
.tap_mut()
only in debug builds, and is erased in release
builds.§fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
.tap_borrow()
only in debug builds, and is erased in release
builds.§fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
fn tap_borrow_mut_dbg<B>(self, func: impl FnOnce(&mut B)) -> Self
.tap_borrow_mut()
only in debug builds, and is erased in release
builds.§fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
.tap_ref()
only in debug builds, and is erased in release
builds.§fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
fn tap_ref_mut_dbg<R>(self, func: impl FnOnce(&mut R)) -> Self
.tap_ref_mut()
only in debug builds, and is erased in release
builds.§fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
.tap_deref()
only in debug builds, and is erased in release
builds.Source§impl<T> ToHex for T
impl<T> ToHex for T
Source§fn encode_hex<U>(&self) -> Uwhere
U: FromIterator<char>,
fn encode_hex<U>(&self) -> Uwhere
U: FromIterator<char>,
self
into the result. Lower case
letters are used (e.g. f9b4ca
)Source§fn encode_hex_upper<U>(&self) -> Uwhere
U: FromIterator<char>,
fn encode_hex_upper<U>(&self) -> Uwhere
U: FromIterator<char>,
self
into the result. Upper case
letters are used (e.g. F9B4CA
)