Skip to content

Conversation

@0xMuang
Copy link
Collaborator

@0xMuang 0xMuang commented Dec 29, 2025

CipherBFT Mempool Implementation Review

This document summarizes the CipherBFT mempool components implemented so far.

Implemented Components

1. CipherBftPool Wrapper

CipherBftPool<P> – pool.rs

A thin wrapper over the Reth transaction pool, delegating core pool logic and configuration to Reth.

pub struct CipherBftPool<P: TransactionPool> {
    pool: P,
    config: MempoolConfig,
    state_provider: StateProviderBox,
}

// Concrete type alias for production use
pub type CipherBftRethPool<Client, S> = Pool<
    CipherBftValidator<EthTransactionValidator<Client, EthPooledTransaction>>,
    CoinbaseTipOrdering<EthPooledTransaction>,
    S,
>;

2. CipherBftValidator Wrapper

CipherBftValidator<V> – validator.rs

Wraps Reth's EthTransactionValidator to enable future CipherBFT-specific validation hooks.

pub struct CipherBftValidator<V: TransactionValidator> {
    inner: V,
    chain_id: u64,
}

Methods:

  • new(): Builds EthTransactionValidator internally and wraps it
  • wrap(): Wraps an existing validator instance

3. BFT Policy Validation

validate_bft_policy() – pool.rs (private method called by add_transaction())

Performs CipherBFT-specific checks (minimum gas price, nonce gap) before forwarding transactions to the Reth pool.

async fn validate_bft_policy(&self, tx: &TransactionSignedEcRecovered) -> Result<(), MempoolError>

BFT-specific policies:

  • Minimum gas price enforcement (spam prevention)
  • Maximum nonce gap enforcement (queue bloat prevention)

Delegated to Reth:

  • Nonce ordering (too low/duplicate)
  • Balance sufficiency
  • Gas limit validation
  • Transaction size limits
  • Replace-by-fee logic

4. Pool Configuration Mapping

MempoolConfigPoolConfig – config.rs

Maps CipherBFT's MempoolConfig to Reth's PoolConfig, exposing price bump and replacement settings.

impl From<MempoolConfig> for PoolConfig { /* ... */ }

5. Pool Creation Methods

Pool Instantiation – pool.rs

Provides two methods for pool creation:

CipherBftPool::new(): Creates Reth pool internally with all dependencies

  • Only available for CipherBftPool<CipherBftRethPool<Client, S>>
  • Requires: chain_spec, client (StateProviderFactory), blob_store, chain_id, mempool_config

CipherBftPool::wrap(): Wraps an existing Reth pool instance

  • Works with any P: TransactionPool
  • Requires: pool, mempool_config, state_provider
// Method 1: Create pool with all dependencies (recommended)
let pool = CipherBftPool::new(
    chain_spec,
    client,           // StateProviderFactory
    blob_store,
    chain_id,
    mempool_config,
)?;

// Method 2: Wrap existing Reth pool
let pool = CipherBftPool::wrap(reth_pool, mempool_config, state_provider);

6. Adapter: Pending/Queued Access

CipherBftPoolAdapter – pool.rs

Provides helper APIs for batch selection and pending/queued access.

let adapter = pool.adapter();
let pending = adapter.pending_transactions();
let queued = adapter.queued_transactions();
let batch = adapter.get_transactions_for_batch(limit, gas_limit);
let stats = adapter.stats();
adapter.remove_finalized(&tx_hashes);

Adapter methods:

  • get_transactions_for_batch(limit, gas_limit): Select transactions for Worker batch
  • pending_transactions(): Get executable transactions
  • queued_transactions(): Get nonce-gap transactions
  • stats(): Get pool statistics (pending/queued counts)
  • remove_finalized(tx_hashes): Remove finalized transactions

Architecture Overview

Component Status for CipherBFT Mempool

Component Status Location
CipherBftPool ✅ Complete pool.rs
CipherBftValidator ✅ Complete validator.rs
BFT Policy Validation ✅ Complete validate_bft_policy() in pool.rs
Config Mapping ✅ Complete config.rs
Pool Creation Methods ✅ Complete new() and wrap() in pool.rs
Adapter (pending/queued) ✅ Complete CipherBftPoolAdapter in pool.rs
Transaction Input Types ✅ Complete Multiple impl IntoPoolTransactionInput
Worker Integration ❌ Not implemented -

Usage Flow Examples

Option 1: Create pool with all dependencies (Recommended)

use cipherbft_mempool::{CipherBftPool, MempoolConfig};
use reth_chainspec::ChainSpec;
use reth_provider::StateProviderFactory;
use reth_transaction_pool::blobstore::InMemoryBlobStore;
use std::sync::Arc;

let chain_spec: Arc<ChainSpec> = Arc::new(/* ... */);
let client: impl StateProviderFactory = /* ... */;
let blob_store = InMemoryBlobStore::default();
let chain_id = 1; // Mainnet
let mempool_config = MempoolConfig::default();

let pool = CipherBftPool::new(
    chain_spec,
    client,
    blob_store,
    chain_id,
    mempool_config,
)?;

// Use adapter for batch selection
let adapter = pool.adapter();
let batch = adapter.get_transactions_for_batch(100, 30_000_000);
let pending = adapter.pending_transactions();
let stats = adapter.stats();

Option 2: Wrap existing Reth pool

use cipherbft_mempool::{CipherBftPool, CipherBftValidator, MempoolConfig};
use reth_transaction_pool::{Pool, CoinbaseTipOrdering};

// Get state provider first (client will be moved)
let state_provider = client.latest()?;

// Build validator
let validator = CipherBftValidator::new(chain_spec, client, blob_store.clone(), chain_id);

// Build Reth pool
let pool_config: PoolConfig = mempool_config.clone().into();
let reth_pool = Pool::new(
    validator,
    CoinbaseTipOrdering::default(),
    blob_store,
    pool_config,
);

// Wrap it
let pool = CipherBftPool::wrap(reth_pool, mempool_config, state_provider);

Transaction Insertion

use reth_transaction_pool::TransactionOrigin;

// Add transaction (multiple input types supported)
pool.add_transaction(TransactionOrigin::External, tx_signed).await?;
pool.add_transaction(TransactionOrigin::Local, tx_recovered).await?;
pool.add_transaction(TransactionOrigin::External, pooled_element).await?;

// Or add pooled transaction directly
pool.add_pooled_transaction(TransactionOrigin::Local, pooled_tx).await?;

Next Steps

1. Worker Integration

Implement actual worker wiring and lifecycle management

  • Wire mempool into DCL worker
  • Implement batch selection logic in worker
  • Handle transaction propagation

2. Test Coverage

Add integration and edge-case tests

  • End-to-end transaction flow tests
  • BFT policy violation tests
  • Pool ordering and replacement tests

3. Production Dependencies

Configure production-ready components

  • Wire DB-backed StateProvider (replace test provider)
  • Configure production blob storage (file-based or DB-backed)
  • Set up proper chain spec and network configuration

4. Monitoring

Add observability

  • Pool metrics (pending/queued counts)
  • Transaction latency tracking
  • Rejection reason logging

@0xMuang 0xMuang linked an issue Dec 29, 2025 that may be closed by this pull request
5 tasks
Copy link
Member

@qj0r9j0vc2 qj0r9j0vc2 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good approach - wrapping Reth instead of reimplementing. BFT policies (min gas price, nonce gap) make sense as the only CipherBFT-specific additions.

Issues

1. StateProvider gets stale
state_provider: StateProviderBox is a snapshot taken at pool creation. This becomes stale after every block, so balance/nonce checks will be wrong. You'll need a way to refresh it - either pass a provider factory and call latest() on each validation, or add a method to swap in a fresh provider after block commits.

2. Commented-out code in config.rs
Lines 57-70 have a bunch of commented config with "TODO: Customize" - either implement these or delete them. Leaving dead code around just adds noise.

3. Unused chain_id
validator.rs:49 stores chain_id but it's never used for anything. If there's a plan for it, add a TODO. Otherwise remove it.

4. Korean comments in error.rs
Mix of Korean and English comments. Pick one for consistency - probably English since the rest of the codebase is English.

Minor stuff

  • BftPoolPolicy could use #[derive(Default)] and implement reasonable defaults
  • Consider adding metrics (pool size, rejection rates) for monitoring
  • The 100 nonce gap limit is arbitrary - might want to make it configurable

Good stuff

  • Test coverage is solid
  • Error types are well-structured
  • Using Reth's battle-tested pool implementation is the right call

Fix the stale StateProvider issue and clean up the dead code, rest is minor.

@0xMuang 0xMuang requested a review from qj0r9j0vc2 January 11, 2026 16:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

MP-1: Mempool data structure design

3 participants