GhostPool is an admission-layer protocol for encrypted mempools. Encrypted mempools can hide transaction contents, but admission still needs dynamic checks such as authorization, nonce validity, and solvency. If sender and nonce remain public, the mempool leaks account-level activity; if they are hidden without a replacement, admission becomes blind and vulnerable to DoS.
GhostPool replaces public (sender, nonce) checks with a root-bound
zero-knowledge admission proof plus a nullifier for the hidden nonce slot.
Because the proof is tied to a specific state root, a pending encrypted
transaction would otherwise go stale as the chain advances. The nullifier turns
that stale-proof problem into slot tracking: the proof remains usable while its
anchor is fresh and the slot has not been consumed, and plaintext Ethereum
transactions can join the same slot namespace through a lightweight DLEQ
certificate.
Run the reproducible script:
bash scripts/reproduce.shThe script rebuilds target/sp1/ghostpool-sp1-leaf, runs the committed
configs/harness/sp1-reproducible-measurements.toml harness config, and prints
the output directory when it finishes. By default the outputs are written under
target/sp1-measurements/repro-<commit>-<utc>/:
rendered-figures/size.png
rendered-figures/sp1-proof-cost.png
rendered-figures/verifier-throughput.png
sp1-measurements-summary.md
sp1-measurements-summary.json
environment.txt
The default config generates one real SP1 compressed proof so the command
remains a practical reproduction check, but it can still take a few minutes
because it runs the real SP1 compressed prover. Increase samples and users
in a copied config for a larger run.
The run renders three PNG figures for the local synthetic SP1 compressed PoC
path: size.png, sp1-proof-cost.png, and verifier-throughput.png. The
summary reports the four headline measurements:
- size:
envelope_bytes,proof_bytes,baseline_signed_tx_bytes - proving time:
prove_time_per_sample_ms,prove_p50_ms,prove_p95_ms,prove_p99_ms - verification time:
verify_time_per_sample_ms,verify_p50_ms,verify_p95_ms,verify_p99_ms - throughput:
verifier_throughput_per_sec
Timings are host-dependent; the script records the git commit, dirty state, tool
versions, config, and SP1 ELF SHA-256 in environment.txt.
Useful overrides:
SP1_MEASURE_OUT=target/sp1-measurements/my-run bash scripts/reproduce.sh
BUILD_SP1_ELF=never bash scripts/reproduce.sh
GHOSTPOOL_SP1_LEAF_ELF=/path/to/ghostpool-sp1-leaf bash scripts/reproduce.shflowchart LR
Enc[Encrypted transaction]
Proof[Root-bound ZK proof]
Nullifier[Hidden-slot nullifier]
PrivateAdmission[Private admission]
Plain[Plaintext transaction]
DLEQ[DLEQ certificate]
Shared[Shared nullifier namespace]
Pool[Mempool]
Builder[Builder]
Enc --> Proof
Enc --> Nullifier
Proof --> PrivateAdmission
Nullifier --> PrivateAdmission
PrivateAdmission --> Shared
Plain --> DLEQ
DLEQ --> Shared
Shared --> Pool
Pool --> Builder
crates/primitives: protocol data types, suite IDs, digest newtypes, and canonical encodingcrates/commitments: GhostPool-owned public commitment suite implementationscrates/crypto: secp256k1 hash-to-curve, Gamma derivation, signing scalar handling, DLEQ primitives, and the production ECIES encryption-binding suitecrates/statement: deterministic native leaf statement checkercrates/proof-types: proof backend manifests, journal schemas, proof envelopes, and protocol-binding metadatacrates/verifier: backend-neutral leaf verifier trait, errors, and reportscrates/verifier-backends: fixture, native reference, SP1, and RISC Zero verifier adapterscrates/prover: backend-neutral prover trait and witness input boundarycrates/prover-backends: concrete prover host adapters and zkVM guest programscrates/client: user-side witness, proving, encryption, and submission boundariescrates/chain: public chain provider traits, mock/Reth adapters, and Ethereum plaintext DLEQ adapterscrates/opening: scheme-neutral payload opening and transcript verificationcrates/mempool: admission checks, nullifier lifecycle, opening application, and builder-safe handoffcrates/validator: sidecar node assembly, config, verifier backend selection, and HTTP RPC servercrates/harness: provider-injected production-like integration harness and artifact generator
ghostpool-chain/reth: read public anchor data from a Reth MDBX databaseghostpool-chain/ethereum-plaintext: verify visible Ethereum transactions with plaintext DLEQ certificatesghostpool-verifier-backends/native-reference: execute the native statement checker as a non-ZK reference backendghostpool-verifier-backends/sp1: enable SP1 Groth16/PLONK verifier adaptersghostpool-verifier-backends/risc0: enable RISC Zero verifier adaptersghostpool-validator/mock: run the validator with mock chain and fixture verifier supportghostpool-validator/verifier-sp1: wire the SP1 verifier backend into validator startupghostpool-validator/verifier-risc0: wire the RISC Zero verifier backend into validator startupghostpool-validator/reth: enable the validator's Reth chain provider pathghostpool-client/json-rpc: enable HTTPS JSON-RPC witness access through reqwest/rustls
cargo fmt --check
cargo check --workspace --all-targets
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace --all-targetsBuilding anything that pulls sp1-sdk (the sp1 feature of
ghostpool-prover-backends, and therefore of ghostpool-harness) additionally
needs protoc, because the SDK compiles protobuf definitions for its network
prover:
sudo apt-get install -y protobuf-compiler # Debian/UbuntuVerification does not: ghostpool-verifier-backends's sp1 feature pulls only
sp1-verifier. That is what lets the committed proof fixtures
(crates/verifier-backends/tests/fixtures/) be checked in CI without a guest
ELF, a proving key, or Docker. See
docs/design/ci-and-proof-fixtures.md.
The lean harness expands a TOML config into an explicit run plan, executes it through the real protocol stack (client preparation, prover/verifier backends, mempool admission, local builder) against a local synthetic chain, and reduces the recorded runtime trace into datasets, reports, and figure inputs:
cargo run --release -p ghostpool-harness -- plan configs/harness/admission-load.toml --out target/harness/admission-load/plan.json
cargo run --release -p ghostpool-harness -- run target/harness/admission-load/plan.json --out target/harness/admission-load/run
cargo run --release -p ghostpool-harness -- report target/harness/admission-load/run --out target/harness/admission-load/report.md
cargo run --release -p ghostpool-harness -- figure-inputs target/harness/admission-load/run --out target/harness/admission-load/figures
python3 scripts/render_harness_figures.py target/harness/admission-load/figures --out target/harness/admission-load/renderedCommitted configs under configs/harness/ cover admission load, the
invalid-workload rejection matrix, nullifier-conflict and mixed plaintext-DLEQ
namespace traces, retention/reorg traces, opening lifecycle, and the SP1
proof-corpus measurements (sp1-* configs; the sp1 feature and a built guest
ELF are required, and sp1-groth16 additionally needs a running Docker daemon
for the GNARK wrap). Metric reducers operate only on the recorded runtime
trace. The harness does not claim live Ethereum performance, real builder or
Reth txpool integration, full EVM execution, or exact gas accounting.
Scripts for the archived paper-evaluation suite live in scripts/archive/
(see scripts/archive/README.md); they target crates/harness-archive and do
not run against the current harness.