Skip to content
Open
Show file tree
Hide file tree
Changes from 121 commits
Commits
Show all changes
124 commits
Select commit Hold shift + click to select a range
d0f320a
examples/revm_chain: scaffold alloy-evm sim harness
diegomrsantos Dec 13, 2025
c07f087
examples/revm_chain: add core types and deterministic state_root
diegomrsantos Dec 13, 2025
9834366
examples/revm_chain: execute txs with alloy-evm
diegomrsantos Dec 13, 2025
e374042
examples/revm_chain: add simplex chain skeleton
diegomrsantos Dec 13, 2025
802a7f8
examples/revm_chain: add block gossip + verification hook
diegomrsantos Dec 13, 2025
d41a554
examples/revm_chain: deterministic simplex+EVM smoke sim
diegomrsantos Dec 13, 2025
811ac5b
examples/revm_chain: split sim harness into modules
diegomrsantos Dec 13, 2025
2c55010
examples/revm_chain: split consensus wiring into modules
diegomrsantos Dec 13, 2025
d159173
examples/revm_chain: split simplex ingress and control plane
diegomrsantos Dec 13, 2025
61fec6a
examples/revm_chain: track threshold-simplex seed
diegomrsantos Dec 13, 2025
6814ddc
examples/revm_chain: add seed precompile
diegomrsantos Dec 13, 2025
fa5d643
examples/revm_chain: document seed + print outcome
diegomrsantos Dec 13, 2025
8a4a826
examples/revm_chain: rustfmt
diegomrsantos Dec 13, 2025
9a3e6fe
examples/revm_chain: clarify execution tests
diegomrsantos Dec 13, 2025
dd4b393
examples/revm_chain: refactor application actor
diegomrsantos Dec 13, 2025
e9955d2
examples/revm_chain: refactor sim node startup
diegomrsantos Dec 13, 2025
017c068
examples/revm_chain: rename application input enum
diegomrsantos Dec 13, 2025
c914463
examples/revm_chain: rename mailbox/control messages
diegomrsantos Dec 13, 2025
f7e66e0
examples/revm_chain: drop unused deps
diegomrsantos Dec 13, 2025
9bfaf8f
examples/revm_chain: expand README
diegomrsantos Dec 13, 2025
9f41ca4
examples/revm_chain: harden sim finalization tracking
diegomrsantos Dec 13, 2025
2cfd113
examples/revm_chain: drop verified blocks from cache
diegomrsantos Dec 13, 2025
1d09c05
examples/revm_chain: clarify tx modeling
diegomrsantos Dec 13, 2025
e43ad62
examples/revm_chain: document block and seed lifecycle
diegomrsantos Dec 13, 2025
2a7da94
cryptography: fix quorum import scoping
diegomrsantos Dec 14, 2025
c2d59a0
examples/revm_chain: fix DKG setup for minimal features
diegomrsantos Dec 14, 2025
6a9f9c7
examples/revm_chain: fix genesis tx lifecycle and clippy
diegomrsantos Dec 14, 2025
654d731
chore: update Cargo.lock
diegomrsantos Dec 14, 2025
9a35035
examples/revm_chain: extract block sync module
diegomrsantos Dec 15, 2025
e184194
examples/revm_chain: rename pending verify types
diegomrsantos Dec 15, 2025
6e12677
docs(examples/revm_chain): clarify module responsibilities
diegomrsantos Dec 15, 2025
d19c150
examples/revm_chain: clarify demo tx and caching
diegomrsantos Dec 15, 2025
f1b3331
examples/revm_chain: add tx ingress and mempool
diegomrsantos Dec 15, 2025
551dcf3
chore(examples/revm_chain): format Cargo.toml
diegomrsantos Dec 17, 2025
3825898
examples/revm_chain: verify stored blocks against context parent
diegomrsantos Dec 17, 2025
d895e1b
docs(examples/revm_chain): clarify contextual verify
diegomrsantos Dec 17, 2025
685802b
examples/revm_chain: implement consensus Block traits
diegomrsantos Dec 18, 2025
d01b9dc
revm_chain: add shared application state
diegomrsantos Dec 18, 2025
5793124
revm_chain: add marshaled RevmApplication
diegomrsantos Dec 18, 2025
f43df9d
revm_chain: add seed and finalization reporters
diegomrsantos Dec 18, 2025
bb4bf69
revm_chain: add marshal wiring dependencies
diegomrsantos Dec 18, 2025
6d45532
revm_chain: wire marshal into simulation
diegomrsantos Dec 18, 2025
f8f64f0
revm_chain: drop legacy mailbox-based plumbing
diegomrsantos Dec 18, 2025
97bc479
revm_chain: document marshal-based flow
diegomrsantos Dec 18, 2025
d8b0ca4
fmt(revm_chain): run rustfmt
diegomrsantos Dec 18, 2025
2e0b2b3
revm_chain: satisfy clippy lints
diegomrsantos Dec 18, 2025
abca1d5
fmt(revm_chain): sort Cargo.toml
diegomrsantos Dec 18, 2025
e6b4dd6
revm_chain: rename seed hash helper
diegomrsantos Dec 18, 2025
53136b2
revm_chain: rename handle to NodeHandle
diegomrsantos Dec 18, 2025
791ad0b
revm_chain: store execution snapshots only
diegomrsantos Dec 18, 2025
65c7dd7
revm_chain: execute finalized blocks before ack
diegomrsantos Dec 18, 2025
c7d0d0d
fmt(revm_chain): run rustfmt
diegomrsantos Dec 18, 2025
4655930
revm_chain: flatten consensus module
diegomrsantos Dec 18, 2025
54bdc8b
revm_chain: remove consensus module
diegomrsantos Dec 18, 2025
5ff1270
revm: rename example directory
diegomrsantos Dec 23, 2025
2be504e
revm: rename crate to commonware-revm
diegomrsantos Dec 23, 2025
e5bea61
revm: rename storage partitions and namespaces
diegomrsantos Dec 23, 2025
6cf0f15
docs(revm): update paths and components
diegomrsantos Dec 23, 2025
a6f0859
Add QMDB adapter module for REVM
diegomrsantos Jan 6, 2026
1f9716b
Track QMDB changes during execution
diegomrsantos Jan 6, 2026
2c02d5e
Persist finalized QMDB changes
diegomrsantos Jan 6, 2026
ede9dbe
Run REVM simulation on tokio runtime
diegomrsantos Jan 6, 2026
78d6b65
Docs: update REVM example notes for QMDB
diegomrsantos Jan 6, 2026
43db784
Fix QMDB state merge across transactions
diegomrsantos Jan 6, 2026
70b6410
Fix QMDB adapter build for asyncdb
diegomrsantos Jan 7, 2026
c574850
Allow tokio sim network to bind on localhost
diegomrsantos Jan 7, 2026
3386f56
Merge upstream/main
diegomrsantos Jan 7, 2026
3c741c4
Update revm example for updated consensus APIs
diegomrsantos Jan 7, 2026
81f45e2
Adapt revm qmdb adapter to new store api
diegomrsantos Jan 7, 2026
0e37243
Resolve clippy warnings in revm qmdb adapter
diegomrsantos Jan 7, 2026
f2e3c4a
Refactor qmdb adapter into submodules
diegomrsantos Jan 7, 2026
89c9b4f
Document QMDB adapter module
diegomrsantos Jan 7, 2026
83f86fd
Split QMDB store plumbing
diegomrsantos Jan 8, 2026
64f71f9
revm: isolate qmdb and expose root helpers
diegomrsantos Jan 12, 2026
66f0725
revm: run execution on blocking pool
diegomrsantos Jan 12, 2026
1c3d3d3
revm: remove qmdb actor and stabilize state
diegomrsantos Jan 12, 2026
77ace11
revm: raise open file limit for sim
diegomrsantos Jan 12, 2026
d2bfbe3
revm: fix clippy warnings
diegomrsantos Jan 12, 2026
d749d49
revm: relax simplex timeouts for sim
diegomrsantos Jan 12, 2026
e6e435d
storage/qmdb: copy snapshot locations
diegomrsantos Jan 12, 2026
bf17a24
Merge main into feat/revm-chain-example
diegomrsantos Jan 13, 2026
8964d72
Adjust revm example post-merge
diegomrsantos Jan 13, 2026
5a65e5d
Document REVM simulation structs
diegomrsantos Jan 13, 2026
d790d07
Document simulation config fields
diegomrsantos Jan 13, 2026
954544b
Document simulation constants
diegomrsantos Jan 13, 2026
1337bab
Add docs to network and DKG helpers
diegomrsantos Jan 13, 2026
59c0886
Document REVM sim helpers
diegomrsantos Jan 13, 2026
abb1569
docs: document revm example structs
diegomrsantos Jan 13, 2026
a1ba548
docs: describe revm architecture
diegomrsantos Jan 13, 2026
40a0a21
refactor: align revm ledger state
diegomrsantos Jan 13, 2026
2fb89e7
fix: remove param doc comment
diegomrsantos Jan 13, 2026
8a7e282
refactor: add ledger service layer
diegomrsantos Jan 13, 2026
18063ca
refactor(revm): document ledger domain model
diegomrsantos Jan 13, 2026
46da9d2
refactor(revm): expose ledger events through handle
diegomrsantos Jan 13, 2026
dad4f71
docs(revm): extend domain model reference
diegomrsantos Jan 13, 2026
a607ab0
refactor(revm): split reporters into contexts
diegomrsantos Jan 13, 2026
9dd6ff1
refactor(revm): extract domain event bus
diegomrsantos Jan 13, 2026
214b917
refactor(revm): split aggregates into modules
diegomrsantos Jan 13, 2026
109d894
refactor(revm): observe domain events
diegomrsantos Jan 13, 2026
6a55efa
refactor(revm): restructure example modules
diegomrsantos Jan 14, 2026
a6ca4f7
docs(revm): refresh architecture and domain model
diegomrsantos Jan 14, 2026
5f2b732
fix(revm): avoid transport control recursion
diegomrsantos Jan 14, 2026
3456868
fix(revm): move qmdb work off tokio workers
diegomrsantos Jan 14, 2026
e728e4b
fix(revm): only offload qmdb persist
diegomrsantos Jan 14, 2026
48ef9a8
Merge remote-tracking branch 'upstream/main' into feat/revm-chain-exa…
diegomrsantos Jan 14, 2026
b9f1d21
sync(storage): align with upstream/main
diegomrsantos Jan 14, 2026
dd7ba69
revert(revm): run execution and persistence inline
diegomrsantos Jan 15, 2026
e643aac
chore: update Cargo.lock
diegomrsantos Jan 15, 2026
6e0ad17
revm: remove rolling commitment docs and update diagram
diegomrsantos Jan 16, 2026
0543216
revm: rename changeset and compute_root
diegomrsantos Jan 18, 2026
29ec83b
revm: harden snapshot persistence ordering
diegomrsantos Jan 18, 2026
c74f4d0
docs: add revm persistence flow diagram
diegomrsantos Jan 18, 2026
550ab00
revm: fail on reverted transactions
diegomrsantos Jan 18, 2026
0389e29
docs(revm): clarify state root semantics
diegomrsantos Jan 19, 2026
127b5fb
revm: harden finalized reporting and update docs
diegomrsantos Jan 20, 2026
3415d03
docs(revm): revamp example documentation
diegomrsantos Jan 20, 2026
21f4aed
docs(revm): improve diagrams
diegomrsantos Jan 20, 2026
e6afca3
tests(revm): finalize evm in seed precompile test
diegomrsantos Jan 20, 2026
8b0d414
Merge remote-tracking branch 'upstream/main' into feat/revm-chain-exa…
diegomrsantos Jan 21, 2026
44ad788
revm: follow threshold vrf scheme path
diegomrsantos Jan 21, 2026
7f7d533
revm: run snapshot persistence on blocking pool
diegomrsantos Jan 21, 2026
b9c543b
revm: remove unused event subscription handle
diegomrsantos Jan 21, 2026
7202798
p2p: avoid port reuse in simulated network
diegomrsantos Jan 26, 2026
246c7f0
p2p: update simulated socket test
diegomrsantos Jan 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,479 changes: 2,340 additions & 139 deletions Cargo.lock

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ members = [
"examples/log",
"examples/sync",
"examples/reshare",
"examples/revm",

# Fuzz builds
"broadcast/fuzz",
Expand Down
41 changes: 41 additions & 0 deletions examples/revm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
[package]
name = "commonware-revm"
edition.workspace = true
publish = true
version.workspace = true
license.workspace = true
description = "REVM-based example chain running on threshold-simplex (simplex + threshold BLS signatures)."
readme = "README.md"
homepage.workspace = true
repository = "https://github.com/commonwarexyz/monorepo/tree/main/examples/revm"

[lints]
workspace = true

[dependencies]

# EVM execution
alloy-evm = { version = "=0.25.1", default-features = false, features = ["std"] }
anyhow.workspace = true
bytes.workspace = true
clap.workspace = true
commonware-broadcast.workspace = true
commonware-codec.workspace = true
commonware-consensus.workspace = true
commonware-cryptography.workspace = true
commonware-p2p.workspace = true
commonware-parallel.workspace = true
commonware-runtime.workspace = true
commonware-storage.workspace = true
commonware-utils.workspace = true
futures.workspace = true
governor.workspace = true
libc.workspace = true
rand.workspace = true
revm = { version = "33.1.0", default-features = false, features = ["std", "asyncdb"] }
thiserror.workspace = true
tracing.workspace = true

[[bin]]
name = "commonware-revm"
bench = false
91 changes: 91 additions & 0 deletions examples/revm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
# commonware-revm

[![Crates.io](https://img.shields.io/crates/v/commonware-revm.svg)](https://crates.io/crates/commonware-revm)

REVM-based example chain driven by threshold-simplex (`commonware_consensus::simplex`) and executed with `alloy-evm`.

## What This Demonstrates

- Threshold-simplex orders opaque 32-byte digests; full blocks are disseminated and backfilled by `commonware_consensus::marshal` over `commonware_p2p::simulated`.
- Blocks carry a batch of EVM transactions plus an advertised 32-byte `state_root` commitment.
- Validators re-execute proposed blocks with `alloy-evm` / `revm` and reject proposals whose `state_root` mismatches.
- State is persisted in QMDB and exposed to REVM via `WrapDatabaseAsync` + `CacheDB` (QMDB is the base store; CacheDB is the speculative overlay).
- The `state_root` is derived from authenticated QMDB partition roots (accounts, storage, code).
- Seed plumbing: threshold-simplex certificate seed signatures are hashed to 32 bytes and injected as `block.prevrandao` (EIP-4399).
- Bonus: a stateful precompile at `0x00000000000000000000000000000000000000ff` returns the current block's `prevrandao` (32 bytes).

## Components

- `src/domain/`: canonical block/tx types, commitment mapping, and deterministic state-change encoding.
- `src/application/`: proposal/verification logic (marshaled), shared state (mempool + DB snapshots), reporters, and query handle.
- `src/application/execution.rs`: EVM execution (`EthEvmBuilder`) and the seed precompile.
- `src/qmdb/`: QMDB-backed persistence and REVM database adapter.
- `src/simulation/`: tokio, single-process simulation harness (N nodes, simulated P2P).

## How It Works

This example is intentionally "digest-first":

- Simplex agrees on a `ConsensusDigest` for each height (32 bytes).
- The application maps `ConsensusDigest <-> Block` and ensures a digest is only accepted if the
corresponding block re-executes to the advertised `state_root`.

### Block Lifecycle (One Height)

1. Genesis: the application creates the genesis block and prefunds accounts in the EVM DB.
2. Propose: when Simplex asks a leader to propose, the application builds a child block, executes
its txs, stores the block + resulting DB snapshot locally, and returns the full block to the
`commonware_consensus::application::marshaled::Marshaled` wrapper (consensus still orders only
the block commitment digest).
3. Disseminate: marshal broadcasts the full block and serves backfill requests for missing ancestors.
4. Verify: validators re-execute the block on the parent snapshot and accept only if the computed
`state_root` matches the advertised `state_root` (the wrapper notifies marshal on success).
5. Finalize: marshal delivers finalized blocks to the node, the simulation records the digest, and stops after the configured
number of finalizations per node.

The main glue points are `src/application/node/start.rs` (wiring) and `src/application/` (application logic).

### Seed Lifecycle

- On notarization/finalization, threshold-simplex emits a seed signature.
- This example hashes that seed signature to 32 bytes and stores it alongside the finalized digest.
- The next block uses the parent digest's stored seed hash as `prevrandao` (EIP-4399).
- The seed precompile returns the current block's `prevrandao` so contracts can read it.

### State Root Semantics

- Block headers publish the pre-commit QMDB root computed after merkleization but before durability is enforced.
- QMDB commit operations append to the authenticated log, so the post-commit root can differ even when state does not.
- Treat the header `state_root` as the consensus commitment and do not compare it to the post-commit QMDB root.

## Run (Tokio Simulation)

```sh
cargo run -p commonware-revm --release -- --nodes 4 --blocks 5 --seed 1
```

Flags:

- `--nodes`: number of validators (default: 4)
- `--blocks`: number of finalized blocks to wait for per node (default: 3)
- `--seed`: seeded DKG + demo inputs (default: 1)

Expected output is consistent for a given `--seed` and includes:

- Finalized head digest (agreed by consensus)
- Final `state_root` commitment
- Final balances for the example accounts
- Latest tracked threshold seed (32 bytes) and the current block's `prevrandao`

## Test

```sh
cargo test -p commonware-revm
```

## Notes and Next Steps

- This is intentionally minimal and does not implement an Ethereum trie; `state_root` comes from authenticated QMDB partition roots.
- Transactions are built directly as EVM call environments (no signature/fee market modeling); gas price is set to 0.
- The demo block stream is minimal (a single transfer is injected early); extend `src/application/` to add more tx generation.
- The example now uses a QMDB-backed persistence layer with per-finalized-block batch commits.
137 changes: 137 additions & 0 deletions examples/revm/docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
# REVM Example Architecture

This document explains how the REVM example works end to end. It is written so a reader can choose
between a quick high-level scan and a deeper technical pass.

## Status and scope

- This is an example chain, not a production client.
- It demonstrates how Commonware consensus, marshal, and QMDB persistence can drive REVM execution.
- It intentionally omits signatures, fee markets, Ethereum MPT state roots, and many other features.

## How to read this

- Quick scan: read "System overview" and "Data flow by stage".
- Deep dive: also read "State and persistence semantics" and "Safety and invariants".
- If you want domain vocabulary, see DOMAIN_MODEL.md.

## System overview

At a high level, the example does this:

1. Consensus orders 32-byte digests, not full blocks.
2. Full blocks are disseminated and backfilled by marshal.
3. Each block is verified by re-executing its transactions in REVM.
4. The resulting state changes are translated into a QMDB change set.
5. Finalized blocks are persisted in QMDB in batch order.

The architecture diagram is in `revm_architecture.png` (source: `revm_architecture.dot`).

## Component map (what owns what)

| Component | Responsibility | Key files |
| --- | --- | --- |
| CLI | Parses flags, starts a simulation | `examples/revm/src/main.rs` |
| Simulation | Orchestrates N nodes, waits for finalization | `examples/revm/src/simulation/mod.rs` |
| Node wiring | Connects consensus, marshal, application, and storage | `examples/revm/src/application/node/` |
| Consensus (simplex) | Orders digests and emits notarization and finalization events | `commonware_consensus` |
| Marshal | Disseminates blocks and serves backfill requests | `examples/revm/src/application/node/marshal.rs` |
| Application | Propose and verify full blocks | `examples/revm/src/application/app.rs` |
| Execution | Runs REVM and extracts state changes | `examples/revm/src/application/execution.rs` |
| Ledger view | Mempool, snapshots, seeds, persistence coordination | `examples/revm/src/application/ledger/` |
| QMDB | Authenticated storage for accounts, storage, and code | `examples/revm/src/qmdb/` |
| Reporters | React to consensus and marshal events | `examples/revm/src/application/reporters/` |
| Observers | Log domain events (non-mutating) | `examples/revm/src/application/observers.rs` |

## Data flow by stage

### 1) Propose

- Simplex asks the application to propose a block.
- The application gathers transactions from the mempool, skipping any already included in pending
ancestors.
- REVM executes the batch using a parent snapshot and a prevrandao seed.
- The application computes a QMDB state root for the change set.
- The block is produced with the advertised `state_root` and cached as a local snapshot.

### 2) Verify

- Validators receive a full block and re-execute it against the parent snapshot.
- The computed `state_root` must match the block header.
- If it matches, the validator caches the snapshot. If it does not match, the block is rejected.

### 3) Finalize and persist

- Marshal delivers finalized blocks to `FinalizedReporter`.
- If the snapshot already exists, we reuse it. If not, we re-execute to rebuild it.
- We recompute the root and ensure it matches the block header.
- We commit the aggregated change set to QMDB and mark the digest as persisted.
- We prune the mempool and acknowledge marshal so delivery can continue.

The block lifecycle diagram is in `revm_block_lifecycle.png`.
The persistence flow diagram is in `revm_persistence_flow.png`.

## State and persistence semantics

### Digest and root definitions

- `BlockId` is `keccak256(Encode(Block))`.
- The consensus digest is `sha256(BlockId)`.
- `StateRoot` is a commitment over QMDB partition roots for accounts, storage, and code.

### Pre-commit vs post-commit root

- The block header uses a pre-commit root computed by merkleizing partition roots.
- QMDB commit operations append authenticated log entries, so the post-commit root can differ.
- Treat the header `state_root` as the consensus commitment.

### Snapshots

- Each executed block produces a `LedgerSnapshot` with:
- Parent digest
- REVM overlay database (`RevmDb`)
- `StateRoot`
- `QmdbChangeSet`
- Snapshots are cached to avoid re-executing on finalization.

## Runtime and determinism

- The example uses the tokio runtime because REVM requires a tokio runtime to bridge the async QMDB
adapter into REVM's sync database interface.
- Determinism is achieved by seeded key generation and a simulated network with fixed configuration.
- Runtime scheduling is not guaranteed deterministic. The tests focus on stable outcomes for fixed
seeds, not on exact message ordering.

## Safety and invariants

These are the main correctness checks and invariants:

- A block is only accepted if re-execution yields the advertised `state_root`.
- QMDB changes for a digest are merged in order, ancestor to child, before persistence.
- Persisting a digest is idempotent. Duplicate persist calls are a no-op.
- The mempool is pruned only after successful persistence of the finalized block.

## Failure handling

- If a finalized block arrives without a cached snapshot, we re-execute it to rebuild the snapshot.
- If re-execution or root computation fails, we log and acknowledge the update to avoid stalling
marshal delivery.
- Errors returned by mutable QMDB methods are treated as fatal for that database instance.
Callers must not use the database after such an error.

## Performance considerations

- Executing and committing per block is expensive. This example batches QMDB commits per finalized
block for simplicity.
- Snapshot caching avoids re-execution for proposers and validators.
- The simulated network uses fixed link latency and message size caps.

## Extension points

This example is intentionally minimal. Common extension points include:

- Adding transaction signatures and nonce validation.
- Implementing a fee market and gas price handling.
- Replacing `StateRoot` with an Ethereum-compatible trie.
- Adding richer transaction generation for the simulation.
- Introducing byzantine behavior in the simulated network to stress consensus.
Loading