Cluster

Struct Cluster 

Source
pub struct Cluster {
Show 14 fields pub config: ClusterConfig, scenario: ClusterScenarioRun, available_ports: Box<dyn Iterator<Item = u16> + Send>, account_sec_keys: BTreeMap<AccountPublicKey, AccountSecretKey>, nodes: Vec<Node>, ocaml_nodes: Vec<Option<OcamlNode>>, initial_time: Option<Timestamp>, rpc_counter: usize, ocaml_libp2p_keypair_i: usize, verifier_srs: Arc<VerifierSRS>, block_verifier_index: BlockVerifier, work_verifier_index: TransactionVerifier, debugger: Option<Debugger>, invariants_state: Arc<Mutex<InvariantsState>>,
}
Expand description

Manages a cluster of Mina nodes for testing scenarios.

The Cluster struct coordinates multiple node instances, handling resource allocation, configuration, and lifecycle management. It supports both Rust and OCaml node implementations for comprehensive testing.

§Default Behaviors

  • Port allocation: Automatically assigns available ports from the configured range, testing availability before assignment
  • Keypair management: Uses deterministic keypairs for Rust nodes and rotates through predefined keypairs for OCaml nodes
  • Resource isolation: Each node gets isolated temporary directories
  • Verifier indices: Shared verifier SRS and indices across all nodes
  • Network debugging: Optional debugger integration for CI environments

§Node Addition

The cluster provides specialized methods for adding different node types:

Fields§

§config: ClusterConfig

Cluster-wide configuration settings

§scenario: ClusterScenarioRun

Current scenario execution state

§available_ports: Box<dyn Iterator<Item = u16> + Send>

Iterator over available ports for node allocation

§account_sec_keys: BTreeMap<AccountPublicKey, AccountSecretKey>

Registry of account secret keys for deterministic testing

§nodes: Vec<Node>

Collection of active Rust nodes

§ocaml_nodes: Vec<Option<OcamlNode>>

Collection of active OCaml nodes (Option for lifecycle management)

§initial_time: Option<Timestamp>

Genesis timestamp for deterministic time progression

§rpc_counter: usize

Counter for generating unique RPC request IDs

§ocaml_libp2p_keypair_i: usize

Index for rotating OCaml LibP2P keypairs

§verifier_srs: Arc<VerifierSRS>

Shared verifier SRS for proof verification

§block_verifier_index: BlockVerifier

Block verifier index for consensus validation

§work_verifier_index: TransactionVerifier

Transaction verifier index for transaction validation

§debugger: Option<Debugger>

Optional network traffic debugger

§invariants_state: Arc<Mutex<InvariantsState>>

Shared state for invariant checking across nodes

Implementations§

Source§

impl Cluster

Source

pub fn new(config: ClusterConfig) -> Self

Source

pub fn available_port(&mut self) -> Option<u16>

Source

pub fn add_account_sec_key(&mut self, sec_key: AccountSecretKey)

Source

pub fn get_account_sec_key( &self, pub_key: &AccountPublicKey, ) -> Option<&AccountSecretKey>

Source

pub fn set_initial_time(&mut self, initial_time: Timestamp)

Source

pub fn get_initial_time(&self) -> Option<Timestamp>

Source

pub fn add_rust_node( &mut self, testing_config: RustNodeTestingConfig, ) -> ClusterNodeId

Add a new Rust implementation node to the cluster.

Creates and configures a Rust Mina node with the specified testing configuration. This method handles all aspects of node initialization including port allocation, key generation, service setup, and state initialization.

§Default Behaviors
  • Port allocation: HTTP and LibP2P ports automatically assigned from available port range
  • Peer identity: Deterministic LibP2P keypair based on node index
  • Work directory: Isolated temporary directory per node
  • Invariants: Automatic invariant checking enabled
  • HTTP server: Spawned on separate thread for API access
  • Proof verification: Shared verifier indices and SRS
§Configuration Options
  • peer_id: Deterministic or custom LibP2P identity
  • libp2p_port: Custom P2P port (auto-assigned if None)
  • initial_peers: Peer connection targets (supports node references)
  • block_producer: Optional block production configuration
  • genesis: Genesis ledger and protocol constants
  • snark_worker: SNARK work generation settings
§Returns

Returns a ClusterNodeId that can be used to reference this node in scenarios and for inter-node connections.

§Panics

Panics if:

  • No available ports in the configured range
  • Node service initialization fails
  • Invalid genesis configuration
Source

pub fn add_ocaml_node( &mut self, testing_config: OcamlNodeTestingConfig, ) -> ClusterOcamlNodeId

Add a new OCaml implementation node to the cluster.

Creates and spawns an OCaml Mina daemon process with the specified configuration. This method handles process spawning, port allocation, directory setup, and daemon configuration.

§Default Behaviors
  • Executable selection: Automatically detects local binary or falls back to default Docker image
  • Port allocation: LibP2P, GraphQL, and client ports automatically assigned from available range
  • Keypair rotation: Uses predefined LibP2P keypairs, rotating through the set for each new node
  • Process management: Spawns daemon with proper environment variables and argument configuration
  • Logging: Stdout/stderr forwarded with port-based prefixes
  • Docker support: Automatic container management when using Docker
§Configuration Options
  • initial_peers: List of peer connection targets
  • daemon_json: Genesis configuration (file path or in-memory JSON)
  • block_producer: Optional block production key
§Docker vs Local Execution

The method automatically determines execution mode:

  1. Attempts to use locally installed mina binary
  2. Falls back to Docker with default image if binary not found
  3. Custom Docker images supported via configuration
§Returns

Returns a ClusterOcamlNodeId for referencing this OCaml node in scenarios and peer connections.

§Panics

Panics if:

  • No available ports in the configured range
  • Temporary directory creation fails
  • OCaml daemon process spawn fails
Source

pub async fn start(&mut self, scenario: Scenario) -> Result<(), Error>

Source

pub async fn reload_scenarios(&mut self) -> Result<(), Error>

Source

pub fn next_scenario_and_step(&self) -> Option<(&ScenarioId, usize)>

Source

pub fn target_scenario(&self) -> Option<&ScenarioId>

Source

pub fn nodes_iter(&self) -> impl Iterator<Item = (ClusterNodeId, &Node)>

Source

pub fn ocaml_nodes_iter( &self, ) -> impl Iterator<Item = (ClusterOcamlNodeId, &OcamlNode)>

Source

pub fn node(&self, node_id: ClusterNodeId) -> Option<&Node>

Source

pub fn node_by_peer_id(&self, peer_id: PeerId) -> Option<&Node>

Source

pub fn node_mut(&mut self, node_id: ClusterNodeId) -> Option<&mut Node>

Source

pub fn ocaml_node(&self, node_id: ClusterOcamlNodeId) -> Option<&OcamlNode>

Source

pub fn ocaml_node_by_peer_id(&self, peer_id: PeerId) -> Option<&OcamlNode>

Source

pub fn pending_events( &mut self, poll: bool, ) -> impl Iterator<Item = (ClusterNodeId, &State, impl Iterator<Item = (PendingEventId, &Event)>)>

Source

pub fn node_pending_events( &mut self, node_id: ClusterNodeId, poll: bool, ) -> Result<(&State, impl Iterator<Item = (PendingEventId, &Event)>), Error>

Source

pub async fn wait_for_pending_events(&mut self)

Source

pub async fn wait_for_pending_events_with_timeout( &mut self, timeout: Duration, ) -> bool

Source

pub async fn wait_for_pending_event( &mut self, node_id: ClusterNodeId, event_pattern: &str, ) -> Result<PendingEventId>

Source

pub async fn wait_for_event_and_dispatch( &mut self, node_id: ClusterNodeId, event_pattern: &str, ) -> Result<bool>

Source

pub async fn add_steps_and_save( &mut self, steps: impl IntoIterator<Item = ScenarioStep>, )

Source

pub async fn exec_to_end(&mut self) -> Result<(), Error>

Source

pub async fn exec_until( &mut self, target_scenario: ScenarioId, step_i: Option<usize>, ) -> Result<(), Error>

Source

pub async fn exec_next(&mut self) -> Result<bool, Error>

Source

pub async fn exec_step(&mut self, step: ScenarioStep) -> Result<bool>

Source

pub fn debugger(&self) -> Option<&Debugger>

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

§

impl<'a, T, E> AsTaggedExplicit<'a, E> for T
where T: 'a,

§

fn explicit(self, class: Class, tag: u32) -> TaggedParser<'a, Explicit, Self, E>

§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

§

impl<'a, T, E> AsTaggedImplicit<'a, E> for T
where T: 'a,

§

fn implicit( self, class: Class, constructed: bool, tag: u32, ) -> TaggedParser<'a, Implicit, Self, E>

Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<T> Conv for T

§

fn conv<T>(self) -> T
where Self: Into<T>,

Converts self into T using Into<T>. Read more
§

impl<T> FmtForward for T

§

fn fmt_binary(self) -> FmtBinary<Self>
where Self: Binary,

Causes self to use its Binary implementation when Debug-formatted.
§

fn fmt_display(self) -> FmtDisplay<Self>
where Self: Display,

Causes self to use its Display implementation when Debug-formatted.
§

fn fmt_lower_exp(self) -> FmtLowerExp<Self>
where Self: LowerExp,

Causes self to use its LowerExp implementation when Debug-formatted.
§

fn fmt_lower_hex(self) -> FmtLowerHex<Self>
where Self: LowerHex,

Causes self to use its LowerHex implementation when Debug-formatted.
§

fn fmt_octal(self) -> FmtOctal<Self>
where Self: Octal,

Causes self to use its Octal implementation when Debug-formatted.
§

fn fmt_pointer(self) -> FmtPointer<Self>
where Self: Pointer,

Causes self to use its Pointer implementation when Debug-formatted.
§

fn fmt_upper_exp(self) -> FmtUpperExp<Self>
where Self: UpperExp,

Causes self to use its UpperExp implementation when Debug-formatted.
§

fn fmt_upper_hex(self) -> FmtUpperHex<Self>
where Self: UpperHex,

Causes self to use its UpperHex implementation when Debug-formatted.
§

fn fmt_list(self) -> FmtList<Self>
where &'a Self: for<'a> IntoIterator,

Formats each item in a sequence. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

§

impl<Unshared, Shared> IntoShared<Shared> for Unshared
where Shared: FromUnshared<Unshared>,

§

fn into_shared(self) -> Shared

Creates a shared type from an unshared type.
§

impl<T> Pipe for T
where T: ?Sized,

§

fn pipe<R>(self, func: impl FnOnce(Self) -> R) -> R
where Self: Sized,

Pipes by value. This is generally the method you want to use. Read more
§

fn pipe_ref<'a, R>(&'a self, func: impl FnOnce(&'a Self) -> R) -> R
where R: 'a,

Borrows 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) -> R
where R: 'a,

Mutably borrows 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
where Self: Borrow<B>, B: 'a + ?Sized, R: 'a,

Borrows self, then passes self.borrow() into the pipe function. Read more
§

fn pipe_borrow_mut<'a, B, R>( &'a mut self, func: impl FnOnce(&'a mut B) -> R, ) -> R
where Self: BorrowMut<B>, B: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.borrow_mut() into the pipe function. Read more
§

fn pipe_as_ref<'a, U, R>(&'a self, func: impl FnOnce(&'a U) -> R) -> R
where Self: AsRef<U>, U: 'a + ?Sized, R: 'a,

Borrows 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
where Self: AsMut<U>, U: 'a + ?Sized, R: 'a,

Mutably borrows 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
where Self: Deref<Target = T>, T: 'a + ?Sized, R: 'a,

Borrows self, then passes self.deref() into the pipe function.
§

fn pipe_deref_mut<'a, T, R>( &'a mut self, func: impl FnOnce(&'a mut T) -> R, ) -> R
where Self: DerefMut<Target = T> + Deref, T: 'a + ?Sized, R: 'a,

Mutably borrows self, then passes self.deref_mut() into the pipe function.
§

impl<T> Pointable for T

§

const ALIGN: usize

The alignment of pointer.
§

type Init = T

The type for initializers.
§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
§

impl<T> Tap for T

§

fn tap(self, func: impl FnOnce(&Self)) -> Self

Immutable access to a value. Read more
§

fn tap_mut(self, func: impl FnOnce(&mut Self)) -> Self

Mutable access to a value. Read more
§

fn tap_borrow<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Immutable access to the Borrow<B> of a value. Read more
§

fn tap_borrow_mut<B>(self, func: impl FnOnce(&mut B)) -> Self
where Self: BorrowMut<B>, B: ?Sized,

Mutable access to the BorrowMut<B> of a value. Read more
§

fn tap_ref<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Immutable access to the AsRef<R> view of a value. Read more
§

fn tap_ref_mut<R>(self, func: impl FnOnce(&mut R)) -> Self
where Self: AsMut<R>, R: ?Sized,

Mutable access to the AsMut<R> view of a value. Read more
§

fn tap_deref<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Immutable access to the Deref::Target of a value. Read more
§

fn tap_deref_mut<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Mutable access to the Deref::Target of a value. Read more
§

fn tap_dbg(self, func: impl FnOnce(&Self)) -> Self

Calls .tap() only in debug builds, and is erased in release builds.
§

fn tap_mut_dbg(self, func: impl FnOnce(&mut Self)) -> Self

Calls .tap_mut() only in debug builds, and is erased in release builds.
§

fn tap_borrow_dbg<B>(self, func: impl FnOnce(&B)) -> Self
where Self: Borrow<B>, B: ?Sized,

Calls .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
where Self: BorrowMut<B>, B: ?Sized,

Calls .tap_borrow_mut() only in debug builds, and is erased in release builds.
§

fn tap_ref_dbg<R>(self, func: impl FnOnce(&R)) -> Self
where Self: AsRef<R>, R: ?Sized,

Calls .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
where Self: AsMut<R>, R: ?Sized,

Calls .tap_ref_mut() only in debug builds, and is erased in release builds.
§

fn tap_deref_dbg<T>(self, func: impl FnOnce(&T)) -> Self
where Self: Deref<Target = T>, T: ?Sized,

Calls .tap_deref() only in debug builds, and is erased in release builds.
§

fn tap_deref_mut_dbg<T>(self, func: impl FnOnce(&mut T)) -> Self
where Self: DerefMut<Target = T> + Deref, T: ?Sized,

Calls .tap_deref_mut() only in debug builds, and is erased in release builds.
§

impl<T> TryConv for T

§

fn try_conv<T>(self) -> Result<T, Self::Error>
where Self: TryInto<T>,

Attempts to convert self into T using TryInto<T>. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

impl<T> ErasedDestructor for T
where T: 'static,

§

impl<T> MaybeSendSync for T