Remora is a scale-out execution engine for blockchain validators. It uses an asymmetric architecture where a single primary (coordinator) node handles consensus and scheduling, while a pool of proxy nodes execute smart contracts in parallel with strict determinism guarantees.
Remora addresses the performance bottleneck in modern blockchain systems where validators must execute transactions sequentially. The system provides:
The implementation consists of ~13k lines of Rust code and supports multiple workload types including synthetic benchmarks (Fake), database benchmarks (TPC-C), and real blockchain transactions (Sui).
Remora implements the following key components:
Code: src/primary/, src/bin/remora.rs
The primary is the single point of coordination that interfaces with consensus. It contains:
src/primary/mock_consensus.rs): Receives ordered transaction batchessrc/primary/shared_obj_txn_forwarder.rs): Implements subgraph-first scheduling (SFS) and other policies (LSDS, Zeus, SDS, RSDS)src/primary/load_balancer.rs): Routes stateless work to proxiesThe primary assigns unique versions to each object access within a consensus batch, ensuring deterministic execution order across distributed proxies.
Code: src/proxy/, src/bin/remora.rs
Proxy nodes execute transactions assigned by the primary. Each proxy:
The runtime (src/proxy/core.rs) uses tokio::sync::Notify primitives to enforce version-based dependencies, allowing transactions to execute in parallel while respecting the consensus-established order.
Code: src/executor/
Remora supports three executor types:
src/executor/fake.rs): Simulates execution with configurable delays, no actual state changessrc/executor/tpcc/): Implements TPC-C NEW_ORDER and PAYMENT transactionssrc/executor/sui.rs): Executes real Sui Move smart contractsAll executors implement the Executor trait (src/executor/api.rs) which defines transaction generation, execution, and verification interfaces.
Code: src/client/, src/bin/load_generator.rs
The load generator submits transactions to the primary at a configured rate and measures end-to-end latency.
remora/
├── src/
│ ├── bin/
│ │ ├── remora.rs # Main binary (primary/proxies)
│ │ └── load_generator.rs # Client load generator
│ ├── primary/ # Primary implementation
│ │ ├── shared_obj_txn_forwarder.rs # Scheduling policies
│ │ ├── load_balancer.rs # Stateless routing
│ │ ├── mock_consensus.rs # Consensus module
│ │ └── node.rs # Primary node logic
│ ├── proxy/ # Proxy implementation
│ │ ├── core.rs # Proxy runtime and DAG execution
│ │ └── node.rs # Proxy node logic
│ ├── executor/ # Executor backends
│ │ ├── api.rs # Executor trait definition
│ │ ├── fake.rs # Fake executor
│ │ ├── tpcc/ # TPC-C executor
│ │ └── sui.rs # Sui executor
│ ├── client/ # Load generator
│ ├── networking/ # Network communication
│ ├── config.rs # Configuration structures
│ └── metrics.rs # Prometheus metrics
├── assets/ # Configuration examples
└── tests/ # Integration tests
Build the release version:
cargo build --release
The binaries will be in target/release/:
remora - primary/proxy nodeload_generator - ClientBuild for development (faster compilation, slower execution):
cargo build
Remora requires two configuration files: validator config (network/node setup) and benchmark config (workload parameters).
See assets/example-validator.yml:
# Primary network addresses
proxy_server_address: "127.0.0.1:8080" # primary listens for proxies
client_server_address: "127.0.0.1:8081" # primary listens for clients
metrics_address: "127.0.0.1:9090" # Prometheus metrics
# Proxy configurations
proxies:
- proxy_id: 0
listen_proxy_address: 127.0.0.1:19000 # Proxy-to-Proxy communication
listen_primary_address: 127.0.0.1:19002 # Proxy-to-Primary communication
metrics_address: 127.0.0.1:19090
- proxy_id: 1
listen_proxy_address: 127.0.0.1:19001
listen_primary_address: 127.0.0.1:19003
metrics_address: 127.0.0.1:19091
# System parameters
validator_parameters:
load_balancing_policy: !LSDS # Scheduling policy: LSDS, SDS, RSDS, Zeus
separation_mode: !NoSeparation # Stateless/stateful separation mode
Scheduling Policies (see src/primary/shared_obj_txn_forwarder.rs):
LSDS: Locality-aware Subgraph-first Scheduling (default, balances locality and load)SDS: Subgraph-first Scheduling (locality-only)RSDS: Random Subgraph Dispatch (load-only)Zeus: Send to proxy with most required objectsSeparation Modes:
NoSeparation: No stateless/stateful separationProxySeparation: proxies separate execution stagesPrimaryPreSeparation: primary separates before schedulingPrimaryPostSeparation: primary separates after schedulingSee assets/example-benchmark.yml:
load: 10000 # Transactions per second
duration:
secs: 10 # Benchmark duration
nanos: 0
workload: !FakeZipfian # Workload type
alpha: 0.5 # Zipfian skew (0.0 = uniform, higher = more skewed)
number_of_inputs: 5 # Objects per transaction
Workload Types:
FakeZipfian, FakeSolanaTransactions, FakeEthereumTransfersassets/example-tpcc.yml):
workload: !Tpcc
num_warehouses: 10
payment_ratio: 0.5 # 0.0 = all NEW_ORDER, 1.0 = all PAYMENT
num_nodes: 4 # Partitions for locality experiments
hotspot_percentage: 0.8 # Fraction of requests to hotspot
rotation_interval_secs: 20 # Hotspot rotation interval
Transfers, SharedObjects, UniswapNormalTerminal 1 - Start the primary:
RUST_LOG=info cargo run --release --bin remora -- \
--validator-config assets/example-validator.yml \
--benchmark-config assets/example-benchmark.yml \
primary
Terminal 2 - Start proxy 0:
RUST_LOG=info cargo run --release --bin remora -- \
--validator-config assets/example-validator.yml \
--benchmark-config assets/example-benchmark.yml \
proxy --proxy-id 0
Terminal 3 - Start proxy 1:
RUST_LOG=info cargo run --release --bin remora -- \
--validator-config assets/example-validator.yml \
--benchmark-config assets/example-benchmark.yml \
proxy --proxy-id 1
Terminal 4 - Run the load generator:
RUST_LOG=info cargo run --release --bin load_generator -- \
--validator-config assets/example-validator.yml \
--benchmark-config assets/example-benchmark.yml
The load generator will submit transactions for the configured duration and report throughput/latency metrics.
For distributed deployment:
127.0.0.1remora ... primaryremora ... proxy --proxy-id NUse --binding-address <IP> flag to override the binding address:
cargo run --release --bin remora -- \
--validator-config assets/example-validator.yml \
--binding-address 0.0.0.0 \
primary
Run the test suite:
cargo test
Run a specific test:
cargo test remote_proxy_sui
Integration tests (tests/common_case.rs) start a primary, multiple proxies, and a load generator to verify end-to-end functionality.
Each node exposes metrics on its configured metrics_address:
127.0.0.1:9090 (default)127.0.0.1:19090127.0.0.1:19091View metrics:
curl http://127.0.0.1:9090/metrics
See src/metrics.rs for all metrics. Important ones:
remora_latency_seconds: End-to-end transaction latency (histogram)remora_throughput_tps: Transactions per second (gauge)remora_proxy_load: Per-proxy load (gauge)remora_object_migrations: Object ownership transfers (counter)Import assets/grafana-dashboard.json into Grafana to visualize:
The primary also prints periodic metric summaries to stdout when run with RUST_LOG=info.
Key concepts and their code locations:
| Paper Concept | Code Location |
|---|---|
| Primary | src/primary/ |
| Proxy | src/proxy/ |
| Version assignment | src/primary/shared_obj_txn_forwarder.rs (assign_versions) |
| Subgraph-first scheduling (SFS) | src/primary/shared_obj_txn_forwarder.rs (PreConsensusSchedulingPolicy::LSDS) |
| DAG-based execution | src/proxy/core.rs (dependency tracking) |
| Object ownership tracking | src/primary/shared_obj_txn_forwarder.rs (metadata maps) |
| Stateless/stateful separation | src/executor/api.rs (PrimaryToProxyMessage enum) |
| Periodic snapshotting | src/proxy/core.rs (epoch-based state reporting) |
| Elasticity (scale-out/scale-in) | src/primary/load_balancer.rs |
Apache License 2.0. See source file headers for details.