pathfinder-consensus

Crates.iopathfinder-consensus
lib.rspathfinder-consensus
version0.20.0
created_at2025-08-18 10:21:20.514366+00
updated_at2025-08-26 11:26:31.182366+00
descriptionPathfinder Consensus
homepage
repository
max_upload_size
id1800231
size190,974
Abel E (t00ts)

documentation

README

Pathfinder Consensus

A Byzantine Fault Tolerant (BFT) consensus engine for Starknet nodes, built on top of the Malachite consensus engine.

Documentation

Overview

Pathfinder Consensus provides a robust consensus engine for Starknet nodes that wraps the Malachite implementation of the Tendermint BFT consensus algorithm. It's designed to be generic over validator addresses and consensus values, making it suitable for Starknet's consensus requirements.

Quick Start

use pathfinder_consensus::*;
use serde::{Deserialize, Serialize};

// Define your validator address type
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
struct MyAddress(String);

impl std::fmt::Display for MyAddress {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

impl From<MyAddress> for Vec<u8> {
    fn from(addr: MyAddress) -> Self {
        addr.0.into_bytes()
    }
}

// Define your consensus value type
#[derive(Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
struct BlockData(String);

impl std::fmt::Display for BlockData {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        write!(f, "{}", self.0)
    }
}

#[tokio::main]
async fn main() {
    // Create configuration
    let my_address = MyAddress("validator_1".to_string());
    let config = Config::new(my_address.clone());
    
    // Create consensus engine
    let mut consensus = Consensus::new(config);
    
    // Start consensus at height 1
    let validator_set = ValidatorSet::new(vec![
        Validator::new(my_address.clone(), PublicKey::from_bytes([0; 32]))
    ]);
    
    consensus.handle_command(ConsensusCommand::StartHeight(1, validator_set));
    
    // Poll for events
    while let Some(event) = consensus.next_event().await {
        match event {
            ConsensusEvent::RequestProposal { height, round } => {
                println!("Need to propose at height {}, round {}", height, round);
            }
            ConsensusEvent::Decision { height, value } => {
                println!("Consensus reached at height {}: {:?}", height, value);
            }
            ConsensusEvent::Gossip(message) => {
                println!("Need to gossip: {:?}", message);
            }
            ConsensusEvent::Error(error) => {
                eprintln!("Consensus error: {}", error);
            }
        }
    }
}

Core Concepts

ValidatorAddress Trait

Your validator address type must implement the ValidatorAddress trait:

pub trait ValidatorAddress:
    Sync + Send + Ord + Display + Debug + Default + Clone + Into<Vec<u8>> + Serialize + DeserializeOwned
{
}

ValuePayload Trait

Your consensus value type must implement the ValuePayload trait:

pub trait ValuePayload:
    Sync + Send + Ord + Display + Debug + Default + Clone + Serialize + DeserializeOwned
{
}

Consensus Engine

The main Consensus<V, A> struct is generic over:

  • V: Your consensus value type (must implement ValuePayload)
  • A: Your validator address type (must implement ValidatorAddress)

Commands and Events

The consensus engine operates on a command/event model:

  • Commands: Send commands to the consensus engine via handle_command()
  • Events: Poll for events from the consensus engine via next_event().await

Configuration

The Config struct allows you to customize:

  • History Depth: How many completed heights to keep in memory
  • WAL Directory: Where to store write-ahead logs for crash recovery
  • Timeouts: Customize consensus round timeouts

Crash Recovery

The consensus engine supports crash recovery through write-ahead logging:

// Recover from a previous crash
let validator_sets = Arc::new(StaticValidatorSetProvider::new(validator_set));
let mut consensus = Consensus::recover(config, validator_sets);
Commit count: 0

cargo fmt