6.9 KiB
Raw Blame History

e2e_bench

End-to-end LEZ scenarios driven through the wallet against an in-process sequencer + indexer wired to an external Bedrock node. Times each step and records borsh sizes per block, split by tx variant.

Machine

Field Value
Chip Apple M2 Pro (8P+4E)
RAM 16 GB
OS macOS 15.5
Rust 1.94.0
Risc0 zkVM 3.0.5
Profile release

Scenarios

Scenario Description
token Sequential public token Send + one shielded recipient setup.
amm Pool create, add liquidity, swap, remove liquidity. All public.
fanout One sender → N recipients, sequential. All public.
private Shielded, deshielded, private→private chained private flow.
parallel N senders submit concurrently into one block. All public.

Dev-mode vs real-proving

RISC0_DEV_MODE=1 makes the prover emit stub receipts instead of running the recursive STARK pipeline. The table compares each quantity in dev mode vs real proving for the two classes of scenarios:

Quantity Public-only scenarios (dev → real) PPE-bearing scenarios (dev → real)
Wall time per step same in both modes real adds ~100 s per PPE step
public_tx_bytes same in both modes same in both modes
ppe_tx_bytes n/a dev ≈ 2 KB stub → real ≈ 225 KB (matches S_agg from cycle_bench)
block_bytes same in both modes real adds ~225 KB per PPE tx in the block
bedrock_finality_ms same in both modes same in both modes (L1 cadence, not LEZ prover)
Blocks captured similar in both modes real captures more empty clock-only ticks that fill prove wall-time

Tables below report dev-mode for all five scenarios. Real-proving numbers are included for amm_swap_flow (representative all-public) and private_chained_flow (representative chained-private flow); the public-only scenarios converge between modes within run-to-run jitter, so a full real-proving sweep is not run here.

Step latencies — dev mode (RISC0_DEV_MODE=1)

Per-scenario wall time and Bedrock L1-finality latency for the closing tip.

Scenario total_ms total_s bedrock_finality_ms bedrock_finality_s
token_onboarding 60,808 60.81 24,593 24.59
amm_swap_flow 162,058 162.06 19,210 19.21
multi_recipient_fanout 222,206 222.21 16,020 16.02
private_chained_flow 80,700 80.70 23,963 23.96
parallel_fanout 244,387 244.39 23,770 23.77

Total dev-mode wall time across all five: 912.9 s.

Step latencies — real proving (selected scenarios)

Scenario total_ms total_s bedrock_finality_ms bedrock_finality_s Δ vs dev
amm_swap_flow 162,437 162.44 ~19,210 ~19.21 ~0 (all-public)
private_chained_flow 354,843 354.84 23,778 23.78 +274.14 s (≈ 91 s per PPE step × 3)

Per-step breakdown for private_chained_flow in real proving:

Step submit_ms inclusion_ms total_ms total_s
token_new_fungible (public) 1.1 20,276.0 20,291.2 20.29
shielded_transfer (PPE) 111,683.3 1.0 111,730.4 111.73
deshielded_transfer (PPE) 111,454.7 1.1 111,511.2 111.51
private_to_private (PPE) 111,237.0 1.1 111,293.0 111.29

PPE steps move the cost from inclusion_ms (waiting for the next sealed block) to submit_ms (the wallet itself proving the PPE circuit before sending). Each PPE prove is ≈ 111 s on this CPU.

Block + tx sizes (borsh) — dev mode

Per scenario, every produced block is fetched via getBlock(BlockId) and serialized with borsh::to_vec(&Block). Each transaction is serialized individually and counted by variant. The empty clock-only ticks at min give the per-block fixed-cost baseline (≈ 334 bytes across all scenarios).

Scenario blocks block_bytes (mean) block_bytes (min..max) public_tx (mean / n) ppe_tx (mean / n)
token_onboarding 6 881 334..2,890 206 / 8 2,556 / 1
amm_swap_flow 16 553 334..1,011 248 / 24 n/a
multi_recipient_fanout 22 513 334..707 221 / 33 n/a
private_chained_flow 8 1,399 334..3,565 177 / 9 2,715 / 3
parallel_fanout 24 646 334..3,904 248 / 45 n/a

Block + tx sizes (borsh) — real proving

Scenario blocks block_bytes (mean) block_bytes (min..max) public_tx (mean / n) ppe_tx (mean / n)
amm_swap_flow 16 553 334..1,011 248 / 24 n/a
private_chained_flow 35 19,692 334..226,578 159 / 36 225,728 / 3

amm_swap_flow is byte-identical between dev and real (no proof payload). private_chained_flow's ppe_tx_bytes matches the cycle_bench S_agg measurement (≈ 225 KB borsh InnerReceipt). The block_bytes max (226,578) is the block containing the largest PPE transaction.

Findings

  • Public-only scenarios converge between dev mode and real proving in both latency and byte counts. Either mode is suitable to characterize them.
  • PPE transactions are ≈ 225 KB on the wire in real proving, dominated by the outer succinct proof. Dev mode emits a ≈ 2 KB stub that does not represent the L1 payload — fee-model storage gas inputs must come from a real-proving run.
  • Per-PPE-step prove cost on M2 Pro CPU is ≈ 110-120 s, paid on the wallet side at submit time (not on the sequencer). For a single-program chained flow the cost stacks linearly.
  • Empty clock-only ticks set the per-block fixed-cost baseline at ≈ 334 bytes across all scenarios and both modes.
  • Bedrock L1 finality stays around 20 s regardless of proving mode, because finality is paced by L1 cadence, not the LEZ prover.

Reproduce

export LEZ_BEDROCK_BIN=/path/to/logos-blockchain/target/release/logos-blockchain-node
export LEZ_BEDROCK_CONFIG_DIR=/path/to/bedrock/configs

# Dev-mode sweep (fast, ~16 min for all five scenarios)
RISC0_DEV_MODE=1 cargo run --release -p e2e_bench -- --scenario all

# Real-proving for representative private flow (~6 min on M2 Pro CPU)
cargo run --release -p e2e_bench -- --scenario private

# Real-proving for representative public flow (~3 min)
cargo run --release -p e2e_bench -- --scenario amm

JSON output: target/e2e_bench_dev.json / target/e2e_bench_prove.json (suffix toggled by RISC0_DEV_MODE).

Caveats

  • Dev-mode ppe_tx_bytes and PPE-step latencies are not representative of production; use real-proving numbers for any fee-model input that touches the storage or prover-cost components.
  • Single-host run, no GPU acceleration. Real-proving on production prover hardware will move per-step latencies by orders of magnitude; byte counts will not change.
  • Bedrock running locally; no real network latency between sequencer and Bedrock.
  • Some scenarios share account state via the same wallet; this is intentional (mirrors integration_tests::TestContext) and not a realistic multi-wallet workload.