diff --git a/snark/src/block_verify/mod.rs b/snark/src/block_verify/mod.rs index ab620ebb63..9e2f1ffbdd 100644 --- a/snark/src/block_verify/mod.rs +++ b/snark/src/block_verify/mod.rs @@ -1,3 +1,25 @@ +//! # Block Verification State Machine +//! +//! This module implements the state machine for verifying blockchain block proofs +//! within the Mina protocol. It manages the lifecycle of block verification +//! requests and maintains verification state. +//! +//! ## Overview +//! +//! Block verification ensures that: +//! - Block proofs are cryptographically valid +//! - Block headers contain correct consensus information +//! - Blockchain state transitions are legitimate +//! +//! ## Usage +//! +//! Block verification is typically initiated by: +//! - Consensus mechanisms validating incoming blocks +//! - Fork resolution comparing competing chains +//! +//! The verification process runs asynchronously in service threads to avoid +//! blocking the main state machine. + mod snark_block_verify_state; pub use snark_block_verify_state::*; diff --git a/snark/src/block_verify_effectful/mod.rs b/snark/src/block_verify_effectful/mod.rs index 03431838a1..afb1c65e9c 100644 --- a/snark/src/block_verify_effectful/mod.rs +++ b/snark/src/block_verify_effectful/mod.rs @@ -1,3 +1,8 @@ +//! # Block Verification Service Layer +//! +//! This module provides the effectful (side-effect) operations for block +//! verification, separating the computations from the main state machine logic. + mod snark_block_verify_effectful_actions; pub use snark_block_verify_effectful_actions::*; diff --git a/snark/src/lib.rs b/snark/src/lib.rs index 79082982ba..20c3e2bada 100644 --- a/snark/src/lib.rs +++ b/snark/src/lib.rs @@ -1,3 +1,81 @@ +//! # SNARK Verification Orchestration +//! +//! The SNARK crate provides zero-knowledge proof verification capabilities for +//! the Mina Rust node, orchestrating the verification of blocks, transactions, +//! and SNARK work through a Redux-style state machine architecture. +//! +//! ## Overview +//! +//! This crate handles three main types of proof verification: +//! - **Block Verification**: Validates blockchain blocks and their proofs +//! - **Transaction Verification**: Verifies user commands and zkApp +//! transactions +//! - **Work Verification**: Validates SNARK work proofs from workers +//! +//! ## Architecture +//! +//! The crate follows the Mina node's Redux architecture pattern with: +//! - **State**: [`SnarkState`] - Centralized verification state +//! - **Actions**: [`SnarkAction`] - Events triggering verification operations +//! - **Enabling Conditions**: [`redux::EnablingCondition`] - Guards preventing +//! invalid state transitions +//! - **Reducers**: Pure functions managing state transitions +//! - **Effects**: Service interactions for actual proof verification +//! +//! You can find more information regarding the Redux pattern in the +//! documentation at +//! . +//! +//! ## Core Components +//! +//! ### Verification State Machine +//! +//! Each verification type maintains its own state machine: +//! - [`block_verify`] - Block proof verification state machine +//! - [`user_command_verify`] - User command verification state machine +//! - [`work_verify`] - SNARK work verification state machine +//! +//! ### Effectful Operations +//! +//! Operations run in separate service threads: +//! - [`block_verify_effectful`] - Block verification services +//! - [`user_command_verify_effectful`] - Transaction verification services +//! - [`work_verify_effectful`] - Work verification services +//! +//! ## Configuration +//! +//! The [`SnarkConfig`] contains verifier indices and SRS parameters required +//! for proof verification. These are network-specific and loaded during +//! initialization. +//! +//! ## Integration +//! +//! The SNARK crate integrates with: +//! - **Ledger**: Uses cryptographic primitives from the ledger crate +//! - **Kimchi**: Leverages the Kimchi proving system for verification, used +//! since Berkeley. +//! - **Node**: Provides verification services to the main node +//! +//! ## Example Usage +//! +//! ```rust,no_run +//! use snark::{SnarkConfig, SnarkState}; +//! +//! // Initialize SNARK state with configuration +//! let config = SnarkConfig { /* ... */ }; +//! let state = SnarkState::new(config); +//! +//! // The state machine handles verification requests through actions +//! // dispatched by the main node's Redux store +//! ``` +//! +//! ## Performance Considerations +//! +//! - Verifier indices and SRS parameters are cached for reuse +//! - Multiple verification operations can run concurrently +//! +//! For detailed API documentation, see the individual module documentation. + use kimchi::mina_curves::pasta::Vesta; mod merkle_path; diff --git a/snark/src/merkle_path/mod.rs b/snark/src/merkle_path/mod.rs index 837d8e7302..8cef150771 100644 --- a/snark/src/merkle_path/mod.rs +++ b/snark/src/merkle_path/mod.rs @@ -1,3 +1,14 @@ +//! # Merkle Path Verification Utilities +//! +//! This module provides utilities for computing and verifying Merkle tree paths, +//! which are essential for account existence proofs in the Mina ledger. +//! +//! [`calc_merkle_root_hash`] computes the root hash from an account and its +//! Merkle path, allowing verification that the account is part of a specific +//! ledger state. +//! This is commonly used in transaction verification (ensuring account exists). +//! It uses the Poseidon hash function, as specified in the Mina protocol. + use ark_ff::fields::arithmetic::InvalidBigInt; use mina_p2p_messages::{bigint::BigInt, v2::MerkleTreeNode}; use poseidon::hash::params::get_merkle_param_for_height; diff --git a/snark/src/user_command_verify/mod.rs b/snark/src/user_command_verify/mod.rs index 118f20da8b..933deb7939 100644 --- a/snark/src/user_command_verify/mod.rs +++ b/snark/src/user_command_verify/mod.rs @@ -1,3 +1,24 @@ +//! # User Command Verification State Machine +//! +//! This module handles the verification of user commands and zkApp transactions +//! within the Mina protocol. It manages SNARK validation for transactions +//! before they are included in blocks. +//! +//! ## Overview +//! +//! User command verification validates: +//! - **Payment transactions**: Simple value transfers between accounts +//! - **Delegation commands**: Stake delegation operations +//! - **zkApp transactions** +//! +//! ## Verification Process +//! +//! The verification process includes: +//! - Signature validation for transaction authorization +//! - Proof verification for zkApp transactions +//! - Account state consistency checks +//! - Fee and nonce validation + mod snark_user_command_verify_state; pub use snark_user_command_verify_state::*; diff --git a/snark/src/work_verify/mod.rs b/snark/src/work_verify/mod.rs index a18b7fe163..b11c349ca8 100644 --- a/snark/src/work_verify/mod.rs +++ b/snark/src/work_verify/mod.rs @@ -1,3 +1,15 @@ +//! # SNARK Work Verification State Machine +//! +//! This module manages the verification of SNARK work proofs submitted by +//! external SNARK workers. It validates computational work that helps maintain +//! the blockchain's security and scalability. +//! +//! ## Overview +//! +//! SNARK work verification handles: +//! - **Transaction SNARK proofs**: Proofs for transaction validity +//! - **Merge proofs**: Proofs combining multiple transaction proofs + mod snark_work_verify_state; pub use snark_work_verify_state::*; diff --git a/website/docs/developers/architecture.md b/website/docs/developers/architecture.md index 8eaf0b35ba..983c788903 100644 --- a/website/docs/developers/architecture.md +++ b/website/docs/developers/architecture.md @@ -7,123 +7,986 @@ description: slug: /developers/architecture --- -# Mina Rust Node Architecture +# Mina Rust Node Architecture & Code Walk-through -The Mina Rust Node follows a Redux-style state machine architecture for -predictable, debuggable behavior. This design ensures that all state changes are -traceable and the system behavior is deterministic. +## Table of Contents -## Core Principles +1. [Introduction](#introduction) +2. [Architecture Philosophy](#architecture-philosophy) +3. [State Machine Architecture](#state-machine-architecture) +4. [Core Components Overview](#core-components-overview) +5. [Network Configuration System](#network-configuration-system) +6. [Code Organization Patterns](#code-organization-patterns) +7. [Testing & Debugging](#testing--debugging) +8. [Development Guidelines](#development-guidelines) +9. [Communication Patterns](#communication-patterns) -### State Machine Pattern +## Introduction -The Mina Rust Node implements Redux principles adapted for a blockchain node: +The Mina Rust node uses a Redux-inspired architecture pattern where application +state is centralized and all state changes flow through a predictable action +dispatch system. The system is designed as one large state machine composed of +smaller, domain-specific state machines (P2P networking, block production, +consensus, etc.) that work together. -- **State** - Centralized, immutable data structure representing the entire node - state -- **Actions** - Events that trigger state changes throughout the system -- **Enabling Conditions** - Guards that prevent invalid state transitions -- **Reducers** - Pure functions that update state and dispatch new actions -- **Effects** - Thin wrappers for service calls and side effects -- **Services** - Separate threads handling I/O and heavy computation +All CPU-intensive operations, I/O, and non-deterministic operations are moved to +services - separate components that interact with the outside world and run in +their own threads. This separation ensures the core state machine remains +deterministic, making the system predictable, testable, and debuggable. -### Predictable State Management +> **Next Steps**: After this overview, explore the +> [Rust API documentation](https://o1-labs.github.io/mina-rust/api-docs/) for +> detailed implementation information. -Every state change in the Mina Rust Node follows the same pattern: +### Key Design Principles + +- **Deterministic execution** - Given same inputs, behavior is always identical +- **Pure state management** - State changes only through reducers +- **Effect isolation** - Side effects separated from business logic +- **Component decoupling** - Clear boundaries between subsystems + +## Architecture Philosophy + +The architecture distinguishes between two fundamental types of components: + +### State Machine Components (Stateful Actions) + +- Manage core application state through pure functions +- Business logic resides in reducers with controlled state access +- Designed for determinism and predictability +- Interact with services only via effectful actions + +### Service Components (Effectful Actions) + +- Handle "outside world" interactions (network, disk, heavy computation) +- Run asynchronously to keep state machine responsive +- Minimal internal state - decision-making stays in state machine +- Communicate back via Events wrapped in actions + +This separation ensures the core state management remains deterministic and +testable while side effects are handled in a controlled manner. + +## State Machine Architecture + +### Core Concepts + +#### State + +State is the central concept in the architecture - it represents the entire +application's data at any point in time. The global state is composed of smaller +domain-specific states: ```rust -// 1. Action is dispatched -dispatch(SomeAction { data }); +pub struct State { + pub p2p: P2pState, + pub transition_frontier: TransitionFrontierState, + pub snark_pool: SnarkPoolState, + pub transaction_pool: TransactionPoolState, + pub block_producer: BlockProducerState, + // ... etc +} +``` + +_See: +[`State`](https://o1-labs.github.io/mina-rust/api-docs/node/struct.State.html), +[`P2pState`](https://o1-labs.github.io/mina-rust/api-docs/node/state/struct.P2pState.html), +[`TransitionFrontierState`](https://o1-labs.github.io/mina-rust/api-docs/node/transition_frontier/struct.TransitionFrontierState.html), +[`SnarkPoolState`](https://o1-labs.github.io/mina-rust/api-docs/node/snark_pool/struct.SnarkPoolState.html), +[`TransactionPoolState`](https://o1-labs.github.io/mina-rust/api-docs/node/transaction_pool/struct.TransactionPoolState.html), +[`BlockProducerState`](https://o1-labs.github.io/mina-rust/api-docs/node/block_producer/struct.BlockProducerState.html)_ + +Each component manages its own state structure, often using enums to represent +different stages of operations: + +```rust +pub enum ConnectionState { + Disconnected, + Connecting { attempt: u32, started_at: Timestamp }, + Connected { peer_info: PeerInfo }, + Error { reason: String }, +} +``` + +State is directly mutable by reducers as an optimization - rather than returning +new state, reducers modify the existing state in place. + +#### Actions + +Actions represent state transitions in the system. They are nested +hierarchically by context: + +```rust +pub enum Action { + CheckTimeouts(CheckTimeoutsAction), + P2p(P2pAction), + Ledger(LedgerAction), + TransitionFrontier(TransitionFrontierAction), + // ... etc +} +``` + +_See: +[`Action`](https://o1-labs.github.io/mina-rust/api-docs/node/enum.Action.html), +[`CheckTimeoutsAction`](https://o1-labs.github.io/mina-rust/api-docs/node/struct.CheckTimeoutsAction.html), +[`P2pAction`](https://o1-labs.github.io/mina-rust/api-docs/node/enum.P2pAction.html), +[`LedgerAction`](https://o1-labs.github.io/mina-rust/api-docs/node/ledger/enum.LedgerAction.html), +[`TransitionFrontierAction`](https://o1-labs.github.io/mina-rust/api-docs/node/transition_frontier/enum.TransitionFrontierAction.html)_ + +Actions are divided into two categories: + +- **Stateful Actions**: Update state and dispatch other actions (handled by + reducers) +- **Effectful Actions**: Thin wrappers for service interactions (handled by + effects) + +#### Enabling Conditions + +Every action must implement +[`EnablingCondition`](https://github.com/o1-labs/redux-rs/blob/master/src/action/enabling_condition.rs) +to prevent invalid state transitions: + +```rust +pub trait EnablingCondition { + fn is_enabled(&self, state: &State, time: Timestamp) -> bool; +} +``` + +_This trait is implemented by all actions in the system to control state +transitions._ + +Reducers, after performing a state update, will attempt to advance the state +machine in all directions that make sense from that point by dispatching +multiple potential next actions. However, it is the enabling conditions that +ultimately decide which of these transitions actually proceed. This creates a +natural flow where reducers propose all possible next steps, and enabling +conditions act as gates that filter out invalid paths based on the current +state. + +For example, a reducer might dispatch actions to send messages to all connected +peers, but enabling conditions will filter out actions for peers that have since +disconnected. + +#### Reducers (New Style) + +In the new architecture, reducers handle both state updates and action +dispatching: + +```rust +impl ComponentState { + pub fn reducer( + mut state_context: crate::Substate, + action: ComponentActionWithMetaRef<'_>, + ) { + let Ok(state) = state_context.get_substate_mut() else { return }; + + match action { + ComponentAction::SomeAction { data } => { + // Phase 1: State updates + state.field = data.clone(); + + // Phase 2: Dispatch follow-up actions + let dispatcher = state_context.into_dispatcher(); + // Or use into_dispatcher_and_state() for global state access + // let (dispatcher, global_state) = state_context.into_dispatcher_and_state(); + dispatcher.push(ComponentAction::NextAction { ... }); + } + } + } +} +``` + +_See: +[`Substate`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/struct.Substate.html), +[`SubstateAccess` trait](https://o1-labs.github.io/mina-rust/api-docs/mina_core/trait.SubstateAccess.html)_ + +The `Substate` context enforces separation between state mutation and action +dispatching phases. + +#### Effects (New Style) + +Effects are now thin wrappers that call service methods: + +```rust +impl EffectfulAction { + pub fn effects(&self, _: &ActionMeta, store: &mut Store) { + match self { + EffectfulAction::LoadData { id } => { + store.service.load_data(id.clone()); + } + EffectfulAction::ComputeProof { input } => { + store.service.compute_proof(input.clone()); + } + } + } +} +``` -// 2. Enabling condition is checked -if enabling_condition_met(&state, &action) { - // 3. Reducer processes the action - let new_state = reducer(state, action); +Effects do NOT dispatch actions - they only interact with services. Services +communicate results back via Events. - // 4. Effects may be triggered - trigger_effects(&new_state, &action); +### Execution Model + +#### Single-Threaded Concurrent State Machines + +A critical architectural principle: **all state machines run in a single thread +but operate concurrently**. + +**Concurrent, Not Parallel:** + +- Multiple state machines can be in different phases of their lifecycles + simultaneously +- A connection may be `Pending` while VRF evaluation is `InProgress` and block + production is `Idle` +- Only one action processes at a time - no race conditions or synchronization + needed + +**Single-Threaded Benefits:** + +- **Deterministic execution** - Actions process in a predictable order +- **Simplified debugging** - No thread synchronization issues +- **State consistency** - No locks or atomic operations needed +- **Replay capability** - Exact reproduction of execution sequences + +**Example Flow:** + +``` +Time 1: P2pConnectionAction::Initialize → P2P state becomes Connecting +Time 2: VrfEvaluatorAction::BeginEpoch → VRF state becomes Evaluating +Time 3: P2pConnectionAction::Success → P2P state becomes Ready +Time 4: VrfEvaluatorAction::Continue → VRF continues evaluation +``` + +_See: +[`P2pConnectionAction`](https://o1-labs.github.io/mina-rust/api-docs/p2p/connection/enum.P2pConnectionAction.html) +for connection management actions_ + +Each action executes atomically, but multiple state machines progress +independently. + +**Services and Threading:** While the state machine is single-threaded, +CPU-intensive work runs in dedicated service threads: + +- Main thread: Redux store, all state transitions +- Service threads: Proof generation, cryptographic operations, I/O +- Communication: Services send events back via channels + +This design keeps the state machine responsive while isolating non-deterministic +operations. + +### Defensive Programming with `bug_condition!` + +The codebase uses a `bug_condition!` macro for defensive programming and +invariant checking: + +```rust +P2pChannelsRpcAction::RequestSend { .. } => { + let Self::Ready { local, .. } = rpc_state else { + bug_condition!( + "Invalid state for `P2pChannelsRpcAction::RequestSend`, state: {:?}", + rpc_state + ); + return Ok(()); + }; + // Continue processing... } ``` -## Architecture Styles +_See: +[`P2pChannelsRpcAction`](https://o1-labs.github.io/mina-rust/api-docs/p2p/channels/rpc/enum.P2pChannelsRpcAction.html), +[`bug_condition!` macro](https://o1-labs.github.io/mina-rust/api-docs/mina_core/macro.bug_condition.html)_ + +**Purpose**: `bug_condition!` marks code paths that should be unreachable if +enabling conditions work correctly. It provides a safety net for catching +programming logic errors. + +**Behavior**: + +- **Development** (`MINA_PANIC_ON_BUG=true`): Panics immediately to catch bugs + early +- **Production** (default): Logs error and continues execution gracefully + +**Relationship to Enabling Conditions**: + +1. Enabling conditions prevent invalid actions from reaching reducers +2. `bug_condition!` double-checks the same invariants in reducers +3. If `bug_condition!` triggers, it indicates a mismatch between enabling + condition logic and reducer assumptions + +This is **not error handling** - it's invariant checking for scenarios that +should never occur in correct code. + +### State Machine Inputs + +The state machine has three types of inputs ensuring deterministic behavior: -The codebase contains two architectural styles: +1. **Events** - External data from services wrapped in + [`EventSource::NewEvent`](https://o1-labs.github.io/mina-rust/api-docs/node/action/enum.EventSource.html#variant.NewEvent) +2. **Time** - Attached to every action via + [`ActionMeta`](https://github.com/o1-labs/redux-rs/blob/master/src/action/action_meta.rs) +3. **Synchronous service returns** - Avoided when possible -### New Style (Recommended) +This determinism enables recording and replay for debugging. -- **Unified reducers** that handle both state updates and action dispatch -- Single file per component containing all logic -- Cleaner separation of concerns +## Core Components Overview -### Old Style (Being Migrated) +### Node ([`node/`](https://o1-labs.github.io/mina-rust/api-docs/node/) | [crate docs](https://o1-labs.github.io/mina-rust/api-docs/node/index.html)) -- Separate reducer and effects files -- Split between `*_reducer.rs` and `*_effects.rs` -- Gradually being converted to new style +The main orchestrator containing: -## Component Structure +**State Machine Components:** -### Core Components +- Core state/reducer/action management +- Block producer scheduling +- Transaction/SNARK pools +- Transition frontier (blockchain state) - _Note: Still uses old-style + architecture_ +- RPC request handling +- Fork resolution logic (with core consensus rules in `core/src/consensus.rs`) -**Node** - Main node logic +**Service Components:** -- Block production and validation -- Transaction pool management -- Consensus and blockchain state -- RPC interface +- Block production service (prover interactions) +- Ledger service (database operations) +- External SNARK worker coordination +- Event source (aggregates external events) -**P2P** - Networking layer +### P2P Networking ([`p2p/`](https://o1-labs.github.io/mina-rust/api-docs/p2p/) | [crate docs](https://o1-labs.github.io/mina-rust/api-docs/p2p/index.html)) -- Dual transport: libp2p and WebRTC -- Peer discovery and connection management -- Message routing and validation +Manages peer connections and communication through two distinct network layers: -**Ledger** - Blockchain state +**State Machine Components:** + +- Connection lifecycle management +- Channel state machines that abstract over the differences between the two + networks +- Channel management (RPC, streaming) +- Peer discovery (Kademlia DHT) +- Message routing (Gossipsub) + +**Dual Network Architecture:** + +_libp2p-based Network:_ + +- Used by native node implementations +- Transport protocols (TCP, custom WebRTC) +- Security (Noise handshake) +- Multiplexing (Yamux) +- Protocol negotiation + +_WebRTC-based Network:_ + +- Used by webnode (browser-based node) +- Direct WebRTC transport implementation +- Different design pattern from libp2p +- Optimized for browser constraints + +### SNARK Verification ([`snark/`](https://o1-labs.github.io/mina-rust/api-docs/snark/) | [crate docs](https://o1-labs.github.io/mina-rust/api-docs/snark/index.html)) + +Handles zero-knowledge proof verification: + +**State Machine Components:** + +- Block verification state +- SNARK work verification +- Transaction proof verification + +**Service Components:** + +- Async proof verification services +- Batching for efficiency + +### Ledger ([`ledger/`](https://o1-labs.github.io/mina-rust/api-docs/mina_tree/) | [crate docs](https://o1-labs.github.io/mina-rust/api-docs/mina_tree/index.html)) + +A comprehensive Rust port of the OCaml Mina ledger with identical business +logic: + +**Core Components:** + +- **BaseLedger trait** - Fundamental ledger interface for account management and + Merkle operations +- **Mask system** - Layered ledger views with copy-on-write semantics for + efficient state management +- **Database** - In-memory account storage and Merkle tree management + +**Transaction Processing:** + +- **Transaction Pool** - Fee-based ordering, sender queue management, nonce + tracking +- **Staged Ledger** - Transaction application and block validation +- **Scan State** - Parallel scan tree for SNARK work coordination + +**Advanced Features:** + +- **Proof System Integration** - Transaction, block, and zkApp proof + verification using Kimchi +- **zkApp Support** - Full zkApp transaction processing with account updates and + permissions +- **Sparse Ledger** - Efficient partial ledger representation for SNARK proof + generation + +**OCaml Compatibility:** + +- Direct port maintaining same Merkle tree structure, transaction validation + rules, and account model +- Memory-only implementation adapted to Rust idioms (Result types, ownership + model) + +_For detailed documentation, see the +[Ledger API documentation](https://o1-labs.github.io/mina-rust/api-docs/mina_tree/)_ + +### Supporting Components + +- **Core Types** + ([`core/`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/) | + [crate docs](https://o1-labs.github.io/mina-rust/api-docs/mina_core/index.html)) - + Shared data structures +- **Cryptography** ([`vrf/`](https://o1-labs.github.io/mina-rust/api-docs/vrf/) + | [crate docs](https://o1-labs.github.io/mina-rust/api-docs/vrf/index.html), + [`poseidon/`](https://o1-labs.github.io/mina-rust/api-docs/poseidon/) | + [crate docs](https://o1-labs.github.io/mina-rust/api-docs/poseidon/index.html)) - + Crypto primitives +- **Serialization** + ([`mina-p2p-messages/`](https://o1-labs.github.io/mina-rust/api-docs/mina_p2p_messages/) + | + [crate docs](https://o1-labs.github.io/mina-rust/api-docs/mina_p2p_messages/index.html)) - + Network messages + +## Network Configuration System + +The Mina Rust node supports multiple networks through a centralized +configuration system defined in +[`core/src/network.rs`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/): + +### Network Types + +- **Devnet** + ([`NetworkId::TESTNET`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/devnet/constant.NETWORK_ID.html)) - + Development and testing network +- **Mainnet** + ([`NetworkId::MAINNET`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/mainnet/constant.NETWORK_ID.html)) - + Production Mina network + +### Configuration Components + +Each network configuration includes: + +- **Cryptographic Parameters**: Network-specific signature prefixes and hash + parameters + - [`SIGNATURE_PREFIX`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/devnet/constant.SIGNATURE_PREFIX.html) + (devnet) / + [`SIGNATURE_PREFIX`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/mainnet/constant.SIGNATURE_PREFIX.html) + (mainnet) + - [`ACCOUNT_UPDATE_HASH_PARAM`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/devnet/constant.ACCOUNT_UPDATE_HASH_PARAM.html) + (devnet) / + [`ACCOUNT_UPDATE_HASH_PARAM`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/mainnet/constant.ACCOUNT_UPDATE_HASH_PARAM.html) + (mainnet) +- **Circuit Configuration**: Directory names and circuit blob identifiers for + each proof type + - [`CIRCUITS_CONFIG`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/devnet/constant.CIRCUITS_CONFIG.html) + (devnet) / + [`CIRCUITS_CONFIG`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/mainnet/constant.CIRCUITS_CONFIG.html) + (mainnet) +- **Default Peers**: Bootstrap peers for initial P2P connection + - [`default_peers()`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/devnet/fn.default_peers.html) + (devnet) / + [`default_peers()`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/mainnet/fn.default_peers.html) + (mainnet) +- **Constraint Constants**: Consensus parameters like ledger depth, work delay, + block timing + - [`CONSTRAINT_CONSTANTS`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/devnet/constant.CONSTRAINT_CONSTANTS.html) + (devnet) / + [`CONSTRAINT_CONSTANTS`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/mainnet/constant.CONSTRAINT_CONSTANTS.html) + (mainnet) +- **Fork Configuration**: Hard fork parameters including state hash and + blockchain length + +### Configuration Initialization + +1. **Global Access**: + [`NetworkConfig::global()`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/struct.NetworkConfig.html#method.global) + provides access to the active configuration +2. **Network Selection**: + [`NetworkConfig::init(network_name)`](https://o1-labs.github.io/mina-rust/api-docs/mina_core/network/struct.NetworkConfig.html#method.init) + sets the global config once +3. **Service Integration**: All services access network parameters through the + global config + +This design ensures the Mina Rust node can operate on different Mina networks +while maintaining protocol compatibility. + +## Code Organization Patterns + +### New Architecture Style + +Most state machine components follow the new pattern with: + +1. **Substate Access** - Fine-grained state control +2. **Unified Reducers** - Handle both state updates and action dispatching in + two enforced phases +3. **Thin Effects** - Only wrap service calls +4. **Callbacks** - Enable decoupled component communication +5. **Clear Separation** - Stateful vs Effectful actions + +Example structure: + +```rust +// Stateful action with reducer +impl WatchedAccountsState { + pub fn reducer( + mut state_context: crate::Substate, + action: WatchedAccountsActionWithMetaRef<'_>, + ) { + let Ok(state) = state_context.get_substate_mut() else { return }; + + match action { + WatchedAccountsAction::Add { pub_key } => { + // Update state + state.insert(pub_key.clone(), WatchedAccountState { ... }); + + // Dispatch follow-up + let dispatcher = state_context.into_dispatcher(); + dispatcher.push(WatchedAccountsAction::LedgerInitialStateGetInit { + pub_key: pub_key.clone() + }); + } + } + } +} + +// Effectful action with service interaction +impl LedgerEffectfulAction { + pub fn effects(&self, _: &ActionMeta, store: &mut Store) { + match self { + LedgerEffectfulAction::Write { request } => { + store.service.write_ledger(request.clone()); + } + } + } +} +``` -- Account state and transactions -- Proof verification -- Scan state management +_See: +[`WatchedAccountsState`](https://o1-labs.github.io/mina-rust/api-docs/node/watched_accounts/struct.WatchedAccountsState.html), +[`WatchedAccountsAction`](https://o1-labs.github.io/mina-rust/api-docs/node/watched_accounts/enum.WatchedAccountsAction.html), +[`LedgerEffectfulAction`](https://o1-labs.github.io/mina-rust/api-docs/node/ledger_effectful/enum.LedgerEffectfulAction.html), +[`LedgerService`](https://o1-labs.github.io/mina-rust/api-docs/node/ledger/trait.LedgerService.html), +[`Store`](https://o1-labs.github.io/mina-rust/api-docs/node/type.Store.html)_ -**Core** - Shared utilities +### Old Architecture Style (Transition Frontier) -- Common types and data structures -- Cryptographic primitives -- Configuration management +The transition frontier still uses the original Redux pattern: -### File Organization +- **Reducers** only update state (no action dispatching) +- **Effects** handle all follow-up action dispatching after state changes +- Separate reducer and effects functions -Each component follows consistent patterns: +This pattern matches traditional Redux but creates challenges in following the +flow since state updates and the resulting next actions are separated across +different files. The new style was introduced to improve code locality and make +the execution flow easier to follow. -- `*_state.rs` - State definitions and data structures -- `*_actions.rs` - Action types and event definitions -- `*_reducer.rs` - State transition logic -- `*_effects.rs` - Service interaction wrappers -- `*_service.rs` - Service interface definitions -- `summary.md` - Component documentation +### Callbacks Pattern -## Data Flow +Callbacks enable dynamic action composition, allowing callers to specify +different flows after completion of the same underlying action. This pattern +solves several architectural problems: -1. **External Events** (network messages, user commands) create actions -2. **Actions** flow through the dispatch system -3. **Enabling Conditions** validate whether actions can be processed -4. **Reducers** compute new state based on current state and action -5. **Effects** trigger service calls when state changes require external - interaction -6. **Services** handle async operations and generate new events +**Before Callbacks:** -## Key Benefits +- All action flows were static and hardcoded +- Same actions needed to be duplicated for different completion flows +- Components were tightly coupled since actions had fixed next steps +- Adding new use cases required modifying existing actions -- **Debuggability** - Complete state history and action replay -- **Testability** - Pure functions and predictable state changes -- **Maintainability** - Clear separation of concerns and data flow -- **Performance** - Efficient state updates and selective processing +**With Callbacks:** + +- Callers can reuse the same action with different completion behaviors +- Reduces component coupling by making actions more generic +- Eliminates action duplication across different contexts +- Easy to extend with new flows without modifying existing code + +```rust +// Same action, different completion flows based on caller context +dispatcher.push(SnarkBlockVerifyAction::Init { + req_id, + block: block.clone(), + on_success: redux::callback!( + on_verify_success(hash: BlockHash) -> Action { + ConsensusAction::BlockVerifySuccess { hash } // Flow for consensus + } + ), + on_error: redux::callback!( + on_verify_error((hash: BlockHash, error: Error)) -> Action { + ConsensusAction::BlockVerifyError { hash, error } + } + ), +}); + +// Same verification action, but different completion flow for RPC context +dispatcher.push(SnarkBlockVerifyAction::Init { + req_id, + block: block.clone(), + on_success: redux::callback!( + on_rpc_verify_success(hash: BlockHash) -> Action { + RpcAction::BlockVerifyResponse { hash, success: true } // Flow for RPC + } + ), + on_error: redux::callback!( + on_rpc_verify_error((hash: BlockHash, error: Error)) -> Action { + RpcAction::BlockVerifyResponse { hash, success: false, error } + } + ), +}); +``` + +### Directory Structure + +Each major component follows a consistent pattern: + +``` +component/ +├── component_state.rs # State definition +├── component_actions.rs # Stateful action types +├── component_reducer.rs # State transitions + dispatching +└── component_effectful/ # Effectful actions + ├── component_effectful_actions.rs + ├── component_effectful_effects.rs + └── component_service.rs # Service interface +``` + +## Testing & Debugging + +Testing benefits from the deterministic execution model: + +### Testing Approaches + +1. **Scenarios** - Specific network setups testing behaviors +2. **Simulator** - Multi-node controlled environments +3. **Fuzz Testing** - Random inputs finding edge cases +4. **Differential Fuzz Testing** - Comparing ledger implementation against the + original OCaml version +5. **Invariant Checking** - Ensuring state consistency + +### Debugging Features + +1. **State Recording** - All inputs can be recorded +2. **Replay Capability** - Reproduce exact execution +3. **State Inspection** - Direct state examination in tests +4. **Deterministic Behavior** - Same inputs = same outputs + +### Key Testing Properties + +- **Determinism** - Predictable state transitions +- **Isolation** - State logic testable without services +- **Composability** - Complex scenarios from simple actions +- **Observability** - Full state visibility ## Development Guidelines -- Use `bug_condition!` macro for theoretically unreachable code paths -- Extract complex logic into state methods rather than bloating reducers -- Prefer enabling conditions over error handling in reducers -- Document component responsibilities in `summary.md` files +### Understanding the Codebase + +1. **Start with State** - State definitions reveal the flow +2. **Follow Actions** - Stateful vs effectful distinction +3. **Check Enabling Conditions** - Understand validity rules +4. **Trace Callbacks** - See component interactions + +### Adding New Features + +1. **Design State First** - State should represent the flow +2. **Categorize Actions** - Stateful or effectful? +3. **Strict Enabling Conditions** - Prevent invalid states +4. **Use Callbacks** - For decoupled responses +5. **Keep Effects Thin** - Only service calls + +### Best Practices + +1. **State Represents Flow** - Make state self-documenting +2. **Actions Match Transitions** - Consistent naming conventions +3. **Reducers Handle Logic** - State updates + dispatching +4. **Effects Only Call Services** - No business logic +5. **Services Stay Minimal** - I/O and computation only + +### Common Patterns + +1. **Async Operations** - Effectful action → Service → Event → New action + dispatch +2. **State Machines** - Enum variants representing stages +3. **Timeouts** - CheckTimeouts action triggers checks +4. **Error States** - Explicit error variants in state + +### Architecture Evolution + +The state machine components have been transitioning from old to new style: + +- **New Style**: Unified reducers, thin effects, callbacks - most components + have been migrated +- **Old Style**: Separate reducers/effects - transition frontier still uses this + pattern +- **Migration Path**: State machine components updated incrementally + +For detailed migration instructions, see +[ARCHITECTURE.md](https://github.com/o1-labs/openmina/blob/develop/ARCHITECTURE.md). + +## Communication Patterns + +The architecture provides several patterns for components to communicate while +maintaining decoupling and predictability. + +### Direct Action Dispatching + +Components can dispatch actions to trigger behavior in other components. This is +the primary pattern for synchronous communication. + +**Example: Ledger to Block Producer Communication** + +```rust +// From node/src/ledger/read/ledger_read_reducer.rs +// After receiving delegator table, notify block producer +match table { + None => { + dispatcher.push( + BlockProducerVrfEvaluatorAction::FinalizeDelegatorTableConstruction { + delegator_table: Default::default(), + }, + ); + } + Some(table) => { + dispatcher.push( + BlockProducerVrfEvaluatorAction::FinalizeDelegatorTableConstruction { + delegator_table: table.into(), + }, + ); + } +} +``` + +_See: +[`BlockProducerVrfEvaluatorAction`](https://o1-labs.github.io/mina-rust/api-docs/node/block_producer/vrf_evaluator/enum.BlockProducerVrfEvaluatorAction.html)_ + +**Example: P2P Best Tip Propagation** + +```rust +// From p2p/src/channels/best_tip/p2p_channels_best_tip_reducer.rs +// When best tip is received, update peer state +dispatcher.push(P2pPeerAction::BestTipUpdate { peer_id, best_tip }); +``` + +_See: +[`P2pPeerAction`](https://o1-labs.github.io/mina-rust/api-docs/p2p/peer/enum.P2pPeerAction.html)_ + +### Callback Pattern + +Components can register callbacks that get invoked when asynchronous operations +complete. This enables loose coupling between components. + +**Example: P2P Channel Initialization** + +```rust +// From p2p/src/channels/best_tip/p2p_channels_best_tip_reducer.rs +dispatcher.push(P2pChannelsEffectfulAction::InitChannel { + peer_id, + id: ChannelId::BestTipPropagation, + on_success: redux::callback!( + on_best_tip_channel_init(peer_id: PeerId) -> crate::P2pAction { + P2pChannelsBestTipAction::Pending { peer_id } + } + ), +}); +``` + +**Example: Transaction Pool Account Fetching** + +```rust +// From node/src/transaction_pool/transaction_pool_reducer.rs +dispatcher.push(TransactionPoolEffectfulAction::FetchAccounts { + account_ids, + ledger_hash: best_tip_hash.clone(), + on_result: callback!( + fetch_to_verify((accounts: BTreeMap, id: Option, from_source: TransactionPoolMessageSource)) + -> crate::Action { + TransactionPoolAction::StartVerifyWithAccounts { accounts, pending_id: id.unwrap(), from_source } + } + ), + pending_id: Some(pending_id), + from_source: *from_source, +}); +``` + +### Event Source Pattern + +Services communicate results back through events that get converted to actions. +The event source acts as the bridge between the async service world and the +synchronous state machine. + +**Note:** Currently, all event handling is centralized in +`node/src/event_source/`. The architectural intention is to eventually +distribute this logic across the individual effectful state machines that care +about specific events, making the system more modular and maintainable. + +**Example: Service Event Processing** + +```rust +// From node/src/event_source/event_source_effects.rs +Event::Ledger(event) => match event { + LedgerEvent::Write(response) => { + store.dispatch(LedgerWriteAction::Success { response }); + } + LedgerEvent::Read(id, response) => { + store.dispatch(LedgerReadAction::Success { id, response }); + } +}, +Event::Snark(event) => match event { + SnarkEvent::BlockVerify(req_id, result) => match result { + Err(error) => { + store.dispatch(SnarkBlockVerifyAction::Error { req_id, error }); + } + Ok(()) => { + store.dispatch(SnarkBlockVerifyAction::Success { req_id }); + } + }, +} +``` + +### State Callbacks Pattern + +Components can expose callbacks in their state that other components can +register to. This enables dynamic subscription to events. + +**Example: P2P RPC Response Handling** + +```rust +// From p2p/src/channels/rpc/p2p_channels_rpc_reducer.rs +let (dispatcher, state) = state_context.into_dispatcher_and_state(); +let p2p_state: &P2pState = state.substate()?; + +// Notify interested components about RPC response +if let Some(callback) = &p2p_state.callbacks.on_p2p_channels_rpc_response_received { + dispatcher.push_callback(callback.clone(), (peer_id, rpc_id, response)); +} + +// Handle timeout notifications +if let Some(callback) = &p2p_state.callbacks.on_p2p_channels_rpc_timeout { + dispatcher.push_callback(callback.clone(), (peer_id, id)); +} +``` + +### Service Request with Callbacks + +Components can make service requests and provide callbacks for handling both +success and error cases. + +**Example: SNARK Verification Request** + +```rust +// From node/src/transaction_pool/transaction_pool_reducer.rs +dispatcher.push(SnarkUserCommandVerifyAction::Init { + req_id, + commands: verifiable, + from_source: *from_source, + on_success: callback!( + on_snark_user_command_verify_success( + (req_id: SnarkUserCommandVerifyId, valids: Vec, from_source: TransactionPoolMessageSource) + ) -> crate::Action { + TransactionPoolAction::VerifySuccess { + valids, + from_source, + } + } + ), + on_error: callback!( + on_snark_user_command_verify_error( + (req_id: SnarkUserCommandVerifyId, errors: Vec) + ) -> crate::Action { + TransactionPoolAction::VerifyError { errors } + } + ) +}); +``` + +### State Machine Lifecycle + +#### Initialization + +``` +Main Node Init ──> Subsystem Creation ──> Service Spawning ──> Ready State +``` + +#### Action Processing + +``` +Event ──> Action Queue ──> Next Action ──> Enabling Check ──┐ + ▲ │ │ + │ │ ▼ + │ │ Rejected + │ ▼ + │ Reducer + │ │ + │ ┌───────────┴───────────┐ + │ │ │ + │ ▼ ▼ + │ State Update 0+ Effectful Actions + │ │ │ + │ ▼ ▼ + └──────── 0+ Stateful Actions Service Calls + │ + ▼ + Queue Empty ──> Listen for Events <─── Result Events +``` + +#### Effect Handling + +``` +Effectful Action ──> Service Call ──> Service Thread ──> Processing ──> Event + │ + ▼ + Action Queue +``` + +### Mental Model + +When working with this architecture, shift from imperative to declarative +thinking: + +**State-First Design:** + +- State enums represent the flow: `Idle → Pending → Success/Error` +- Actions represent transitions: "what event happened?" not "what should I do?" +- Reducers answer two questions: + 1. "Given this state and event, what's the new state?" + 2. "What are all possible next steps from here?" + +**Reducer Orchestration:** + +- Reducers update state AND dispatch multiple potential next actions +- Enabling conditions act as gates - only actions valid for the current state + proceed +- This creates a branching execution where reducers propose paths and conditions + filter them + +**Action Classification:** + +- **Stateful**: Updates state, dispatches other actions (business logic) +- **Effectful**: Calls services, never updates state directly (I/O boundary) +- **Events**: External inputs wrapped in actions (deterministic replay) + +**Async Operations Pattern:** + +``` +1. Dispatch Effectful Action → 2. Service processes → 3. Event generated → 4. Action dispatched +``` + +**Debugging Mental Model:** + +- Logs show the exact sequence of actions - trace execution flow +- State inspection reveals current system state at any moment +- Actions can be recorded for deterministic replay (when enabled) +- Common bugs: missing enabling conditions, incorrect state transitions + +**Common Mental Shift:** Instead of "call API then update state", think +"dispatch action, let reducer update state and propose next actions, enabling +conditions filter valid paths based on current state, services report back via +events that trigger new actions". -For detailed implementation examples, see the component-specific documentation -in the codebase. +The architecture may feel unusual initially, but its benefits in correctness, +testability, and debuggability make it powerful for building reliable +distributed systems.