Aere Network public source. Everything here can be checked against the live chain (chain id 2800, https://rpc.aere.network). Scope note, stated up front rather than buried: consensus on chain 2800 is classical secp256k1 ECDSA QBFT. The post-quantum work in this repository is at the signature, precompile, account and transport layers. Nothing here makes the consensus post-quantum, and no document in it should be read as claiming so.
326 lines
16 KiB
Markdown
326 lines
16 KiB
Markdown
# Block-STM end-to-end block-production throughput (measured)
|
|
|
|
**Date:** 2026-07-13
|
|
**Module:** `parallel-executor/` (the from-scratch Rust Block-STM executor)
|
|
**Scope:** ISOLATED benchmark on a throwaway cloud box. Nothing here touches live
|
|
chain 2800, its validators, or any production node.
|
|
This does **not** make Block-STM mainnet-active; that remains a founder-supervised
|
|
fork activation. The site's honest framing ("testnet demonstration, not
|
|
mainnet-active; execution-phase win") stays intact. This report only **adds a
|
|
real, measured end-to-end number** to that framing.
|
|
|
|
---
|
|
|
|
## 0. Why this exists (the gap being closed)
|
|
|
|
The existing `bench` command times **only** the Block-STM execution phase and
|
|
reports the documented near-linear execution-phase scaling
|
|
(~1.94x / 3.61x / 6.19x / 9.38x at 2/4/8/16 workers). That is an honest
|
|
execution-phase number, but it is **not** an end-to-end block-throughput number.
|
|
A block is not finished when execution finishes; it is finished when the state is
|
|
**committed** and a **state root** is produced. Those tail phases are serial, so
|
|
by Amdahl's law the end-to-end speedup must be **lower** than the execution-phase
|
|
speedup. The site states exactly this gap:
|
|
|
|
> "this is an execution-phase win; an end-to-end throughput win still needs real
|
|
> execution-heavy load plus a parallel commit."
|
|
|
|
This report closes that gap with a real measurement: the **full pipeline**
|
|
(parallel execution + commit + state-root), parallel vs sequential, at 1/2/4/8/16
|
|
workers, across conflict ratios, with serial-equivalence checked on every run.
|
|
|
|
New reproducible harness: `aere-block-stm endtoend [gas] [ntx] [reps]`
|
|
(added to `src/main.rs`; phase timing exposed via the additive
|
|
`execute_block_parallel_split` in `src/parallel.rs`).
|
|
|
|
---
|
|
|
|
## 1. Environment (honest)
|
|
|
|
| | |
|
|
|---|---|
|
|
| Box | Throwaway cloud VM, 16 vCPU, 32 GB, Ubuntu 24.04, US region |
|
|
| CPU | AMD EPYC-Rome, 16 cores, **Thread(s)/core = 1** (no in-guest SMT), 2.0 GHz |
|
|
| Kernel / toolchain | Linux 6.8.0, rustc 1.97.0, release build (`lto=true`, `codegen-units=1`) |
|
|
| Firewall | dedicated scratch firewall, SSH restricted to operator addresses |
|
|
| Lifecycle | provisioned for this benchmark, **DELETED at end** (see §9) |
|
|
|
|
**Caveat, stated up front:** this is a **shared-vCPU** cloud box, not the
|
|
dedicated-core infra machine the original 9.38x figure was taken on. Shared vCPU
|
|
adds run-to-run variance to **absolute** timings. Mitigations: 16 single-threaded
|
|
vCPUs (so worker count maps to real cores with no hyperthread muddying), median of
|
|
7 runs, and the fact that the **headline deliverable is a ratio** (end-to-end vs
|
|
execution-phase speedup, and the serial fraction) in which shared-vCPU noise
|
|
affects numerator and denominator together and largely cancels.
|
|
|
|
---
|
|
|
|
## 2. Methodology
|
|
|
|
**Pipeline, timed in three phases** (see `endtoend()` in `src/main.rs`):
|
|
|
|
1. **exec** - Block-STM parallel execution + validation + re-execution. PARALLEL;
|
|
this is the part that scales with worker count. Timed inside
|
|
`execute_block_parallel_split` between thread spawn and join.
|
|
2. **commit** - `MvMemory::snapshot_final`: materialize the multi-version memory
|
|
into the flat committed `StateMap`. SERIAL (single-threaded, after join).
|
|
3. **root** - `keccak::state_root`: keccak256 over the sorted committed state, the
|
|
on-chain rollup commitment. SERIAL.
|
|
|
|
`end-to-end = exec + commit + root`. The **sequential baseline** is
|
|
`execute_block_sequential` (which produces the live map directly, so it has no
|
|
separate commit step) `+ state_root`. The state-root cost is identical serial work
|
|
in both numerator and denominator, i.e. a pure Amdahl serial tail.
|
|
|
|
**Workload (execution-heavy, not empty blocks).** The deterministic SplitMix64
|
|
generator emits a realistic EVM-style mix per batch: **60% ERC-20 transfers**
|
|
(two balance touches), **15% sweeps** (value-dependent), **15% shared-counter
|
|
increments** (the serializability stressor), **10% AMM swaps** (two-slot pool
|
|
conflict). Each transaction also pays a deterministic simulated EVM cost of `gas`
|
|
keccak-rounds (a stand-in for opcode/keccak/ecrecover interpreter time), so the
|
|
executor is timed doing real per-tx work rather than pure scheduling overhead.
|
|
|
|
**Conflict ratios.** `conflict_ppm` tunes how often a transaction touches the
|
|
shared hot set. Four points span the spectrum: **0%** (disjoint accounts, 64
|
|
contracts), **10%**, **50%**, and a **pathological ~100%** single-hot-slot floor.
|
|
The labelled % is the *designed* hot-touch rate; the honest *realized* conflict
|
|
indicator is the **measured abort%** in each table.
|
|
|
|
**Defaults:** `gas=80`, `ntx=20000`, median of 7 (chosen to match the regime the
|
|
documented ~9.38x execution-phase figure was taken in, so the two are directly
|
|
comparable). A gas sweep (§6) shows sensitivity.
|
|
|
|
**Serial-equivalence, checked every run.** On every single parallel run the harness
|
|
asserts the committed state equals the sequential oracle **and** the two keccak
|
|
state roots are bit-identical. A single mismatch aborts the whole run. This is the
|
|
property that makes the parallel root a valid commitment.
|
|
|
|
---
|
|
|
|
## 3. Serial-equivalence confirmation (the non-negotiable gate)
|
|
|
|
| Check | Result |
|
|
|---|---|
|
|
| `cargo test --release` (7 tests incl. shared-counter serialization, 40-seed random equivalence, keccak KAT) | **7/7 PASS** |
|
|
| Correctness harness: 6 profiles x 200 batches x {1,2,4,8,16} threads | **6000 comparisons, 0 mismatches** |
|
|
| End-to-end harness inline check (state == oracle AND roots identical), every run | **140 checks, 0 mismatches** |
|
|
|
|
`RESULT: PASS -- every parallel run committed the exact sequential state + root.`
|
|
The `04-endtoend.stderr` log is empty (zero mismatch lines). Raw logs in
|
|
`endtoend-logs-2026-07-13/`.
|
|
|
|
---
|
|
|
|
## 4. Execution-phase baseline on THIS box (for comparison)
|
|
|
|
Running the existing `bench` (execution-phase only) on the same box reproduces the
|
|
documented range, confirming the box is a faithful stand-in:
|
|
|
|
| Workload | 2 | 4 | 8 | **16** (vs sequential) |
|
|
|---|---|---|---|---|
|
|
| Low-conflict (~2%) | 1.74x | 3.24x | 5.68x | **8.30x** |
|
|
| Medium-conflict (~15%) | 1.82x | 3.48x | 6.18x | **9.62x** |
|
|
| High-conflict (~80%) | 1.74x | 3.10x | 4.96x | **5.13x** |
|
|
| Pathological (all one slot) | 0.93x | 0.86x | 0.82x | **0.76x** |
|
|
|
|
(Medium-conflict vs-1-thread: 1.94x / 3.71x / 6.59x / 10.26x, matching the
|
|
documented 1.94x/3.61x/6.19x/9.38x.) These are **execution-phase** numbers.
|
|
|
|
---
|
|
|
|
## 5. END-TO-END RESULTS (the deliverable)
|
|
|
|
`gas=80`, `ntx=20000`, median of 7. `execSpd` = execution-phase speedup;
|
|
`e2eSpd` = **end-to-end** speedup (exec+commit+root) vs the sequential end-to-end
|
|
baseline. TPS is real transactions/second of the full pipeline. All rows PASS
|
|
serial-equivalence.
|
|
|
|
### 0% designed conflict - 49,637 committed state keys (largest state)
|
|
Sequential end-to-end: 672.84 ms (root-share 1.4%), 29,725 TPS.
|
|
|
|
| W | exec ms | commit ms | root ms | e2e ms | execSpd | **e2eSpd** | **TPS** | abort% | (commit+root)/e2e |
|
|
|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
|
|
| 1 | 705.51 | 9.01 | 12.52 | 727.04 | 0.94x | 0.93x | 27,509 | 0.0% | 3.0% |
|
|
| 2 | 354.89 | 9.56 | 11.41 | 375.85 | 1.87x | 1.79x | 53,212 | 0.0% | 5.6% |
|
|
| 4 | 184.02 | 9.72 | 12.37 | 206.11 | 3.60x | 3.26x | 97,037 | 0.1% | 10.7% |
|
|
| 8 | 97.99 | 8.52 | 8.31 | 114.82 | 6.77x | 5.86x | 174,191 | 0.1% | 14.7% |
|
|
| **16** | 64.23 | 8.08 | 8.51 | 80.83 | **10.32x** | **8.32x** | **247,444** | 0.3% | 20.5% |
|
|
|
|
Amdahl serial tail (commit+root) = 15.33 ms; e2e ceiling 8.27x @16w, 43.88x @inf cores.
|
|
|
|
### 10% designed conflict - 18,342 keys
|
|
Sequential end-to-end: 672.71 ms, 29,731 TPS.
|
|
|
|
| W | exec ms | commit ms | root ms | e2e ms | execSpd | **e2eSpd** | **TPS** | abort% | tail% |
|
|
|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
|
|
| 1 | 699.73 | 5.15 | 4.77 | 709.65 | 0.96x | 0.95x | 28,183 | 0.0% | 1.4% |
|
|
| 2 | 366.73 | 5.31 | 4.38 | 376.42 | 1.83x | 1.79x | 53,133 | 0.1% | 2.6% |
|
|
| 4 | 187.09 | 5.15 | 3.88 | 196.13 | 3.58x | 3.43x | 101,975 | 0.3% | 4.6% |
|
|
| 8 | 96.64 | 5.06 | 4.29 | 105.99 | 6.93x | 6.35x | 188,699 | 0.7% | 8.8% |
|
|
| **16** | 66.57 | 4.37 | 3.20 | 74.14 | **10.06x** | **9.07x** | **269,750** | 1.2% | 10.2% |
|
|
|
|
Amdahl serial tail = 6.68 ms; e2e ceiling 9.64x @16w, 100.71x @inf.
|
|
|
|
### 50% designed conflict - 9,006 keys
|
|
Sequential end-to-end: 699.97 ms, 28,573 TPS.
|
|
|
|
| W | exec ms | commit ms | root ms | e2e ms | execSpd | **e2eSpd** | **TPS** | abort% | tail% |
|
|
|--:|--:|--:|--:|--:|--:|--:|--:|--:|--:|
|
|
| 1 | 712.46 | 2.63 | 1.96 | 717.06 | 0.98x | 0.98x | 27,892 | 0.0% | 0.6% |
|
|
| 2 | 367.61 | 2.46 | 2.01 | 372.07 | 1.90x | 1.88x | 53,753 | 2.1% | 1.2% |
|
|
| 4 | 195.00 | 2.58 | 1.98 | 199.56 | 3.58x | 3.51x | 100,222 | 5.7% | 2.3% |
|
|
| 8 | 113.28 | 2.50 | 1.72 | 117.51 | 6.17x | 5.96x | 170,202 | 10.7% | 3.6% |
|
|
| **16** | 74.60 | 2.35 | 1.59 | 78.53 | **9.36x** | **8.91x** | **254,686** | 16.6% | 5.0% |
|
|
|
|
Amdahl serial tail = 4.15 ms; e2e ceiling 8.73x @16w, 168.85x @inf.
|
|
|
|
### Pathological ~100% conflict - 1,996 keys (honest floor)
|
|
Sequential end-to-end: 664.65 ms, 30,091 TPS.
|
|
|
|
| W | exec ms | commit ms | root ms | e2e ms | execSpd | **e2eSpd** | **TPS** | abort% |
|
|
|--:|--:|--:|--:|--:|--:|--:|--:|--:|
|
|
| 1 | 682.90 | 0.06 | 0.31 | 683.28 | 0.97x | 0.97x | 29,271 | 0.0% |
|
|
| 2 | 378.02 | 0.04 | 0.37 | 378.42 | 1.76x | 1.76x | 52,851 | 6.5% |
|
|
| 4 | 213.51 | 0.04 | 0.38 | 213.93 | 3.11x | 3.11x | 93,488 | 14.5% |
|
|
| 8 | 133.61 | 0.04 | 0.30 | 133.95 | 4.96x | 4.96x | 149,314 | 21.2% |
|
|
| **16** | 135.50 | 0.04 | 0.40 | 135.94 | **4.90x** | **4.89x** | **147,125** | 25.0% |
|
|
|
|
(Here the state is tiny, so commit+root is negligible and e2e ~= exec; the limit is
|
|
conflict, not the serial tail. 16 workers do not beat 8 under 25% aborts.)
|
|
|
|
---
|
|
|
|
## 6. The honest Amdahl boundary
|
|
|
|
**End-to-end speedup is consistently lower than execution-phase speedup.** At 16
|
|
workers, on the realistic 0-50% conflict range:
|
|
|
|
| Conflict | execSpd @16 | **e2eSpd @16** | gap |
|
|
|---|--:|--:|--:|
|
|
| 0% | 10.32x | **8.32x** | -1.9x |
|
|
| 10% | 10.06x | **9.07x** | -1.0x |
|
|
| 50% | 9.36x | **8.91x** | -0.45x |
|
|
|
|
The gap is **largest at 0% conflict** and this is the important, non-obvious
|
|
finding: the workload with the *most* execution parallelism (10.32x) has the
|
|
*least* end-to-end benefit (8.32x), because it touches the *most* state (49,637
|
|
keys), which makes the serial commit+root the largest fraction of the pipeline
|
|
(20.5% of end-to-end time at 16 workers). More parallelizable execution buys a
|
|
bigger, not smaller, serial-tail penalty, exactly the Amdahl trade.
|
|
|
|
**Serial fraction and ceiling.** With the commit+root tail fixed and only exec
|
|
scaling, the end-to-end speedup saturates at `T_seq / (serial_tail + exec_floor)`.
|
|
Measured 16-worker ceilings: **8.27x (0%), 9.64x (10%), 8.73x (50%)**. Even with
|
|
infinite cores (exec -> 0) the flat-keccak tail alone caps end-to-end at
|
|
44x / 101x / 169x respectively; the real cap is far lower because exec has its own
|
|
floor (residual serialization + thread overhead) and, in the real client, the
|
|
commit is much heavier (§7).
|
|
|
|
**Bottom line:** the honest end-to-end block-production speedup of this Rust
|
|
Block-STM executor at 16 workers is roughly **8.3x to 9.1x** on realistic
|
|
0-50%-conflict execution-heavy batches, versus the ~9.4-10.3x execution-phase
|
|
figure on the same box. The end-to-end win is real and large, but it is
|
|
**lower** than the execution-phase headline, precisely as Amdahl predicts.
|
|
|
|
---
|
|
|
|
## 7. Real end-to-end TPS, and why it does NOT reach or imply the 273k ceiling
|
|
|
|
The measured end-to-end TPS at `gas=80` (~247k-270k on realistic conflict) lands
|
|
**coincidentally** near the documented 273k architectural ceiling. It must not be read
|
|
as reaching or validating it. Two independent reasons:
|
|
|
|
**(a) TPS is entirely a function of the assumed per-tx cost.** The gas sweep at 16
|
|
workers proves the absolute number is not a fixed capability:
|
|
|
|
| per-tx cost | e2eSpd @16 (0%/10%/50%) | **end-to-end TPS @16 (0%/10%/50%)** |
|
|
|---|---|---|
|
|
| gas=20 (light) | 3.67x / 4.36x / 3.97x | **416k / 502k / 477k** |
|
|
| gas=80 (default) | 8.32x / 9.07x / 8.91x | **247k / 270k / 255k** |
|
|
| gas=200 (heavy) | 11.97x / 11.91x / 9.55x | **138k / 143k / 115k** |
|
|
|
|
Change the simulated tx weight and the harness reports TPS from ~115k to ~500k on
|
|
the same box. The `gas=80` proximity to 273k is a coincidence of one chosen
|
|
per-tx cost, not a capability ceiling. (Note the honest inverse: heavier txs give
|
|
*higher* speedup, because compute amortizes the serial tail and scheduler
|
|
overhead, but *lower* TPS; lighter txs give lower speedup but higher TPS.)
|
|
|
|
**(b) This is the rollup executor with a light commit proxy, not L1, not a real
|
|
MPT.** The state model is balances + kv slots (not full EVM), and `state_root` is
|
|
a flat keccak fold, a *lighter* commit than a real Merkle Patricia Trie. The
|
|
273k figure is a separate documented-conditions ceiling. These are different
|
|
measurements under different conditions and this report neither reaches nor
|
|
implies it.
|
|
|
|
The invariant, honest deliverable is the **speedup curve and its Amdahl bound**,
|
|
not the absolute TPS.
|
|
|
|
---
|
|
|
|
## 8. Corroboration: the real client's commit is heavier and anti-scales
|
|
|
|
The Rust `state_root` is a light proxy for the commit. The real forked client's
|
|
commit was measured separately (`aerenew/parallel/`, Besu Bonsai world-state, a
|
|
throwaway box, DELETED). Findings there, which make the end-to-end picture in the
|
|
*real* client even more conservative than this Rust harness:
|
|
|
|
- Bit-identical state roots proven four independent ways (in-JVM harness, faithful
|
|
storage-phase test, genesis-root equality, and re-import + validation of 253 real
|
|
exported blocks with zero root mismatch).
|
|
- The multi-threaded **parallel-commit** path **anti-scales**: storage-commit
|
|
scaling vs w=1 was 1.00x / ~0.8x / ~0.6x / ~0.4x / ~0.4x at w=1/2/4/8/16. More
|
|
commit threads made it **slower**. The shipped optimization is therefore a
|
|
**sequential** storage trie (faster than the fork/join parallel one), not a
|
|
parallel commit.
|
|
|
|
So in the real client the commit is not merely a fixed serial tail; parallelizing
|
|
it is counterproductive. The real-client end-to-end ceiling is thus **tighter**
|
|
than the Rust flat-keccak numbers here, not looser. Honest direction of the error
|
|
bar: down.
|
|
|
|
---
|
|
|
|
## 9. Box lifecycle
|
|
|
|
- Provisioned: a dedicated single-purpose scratch VM behind its own scratch firewall,
|
|
created solely for this benchmark.
|
|
- Live chain 2800, its validators, and all production nodes were **not** touched.
|
|
No benchmark compute ran on production infrastructure.
|
|
- **Destroyed at end of run; destruction confirmed** (see
|
|
`endtoend-logs-2026-07-13/`). The scratch firewall was also removed.
|
|
|
|
---
|
|
|
|
## 10. Reproduce
|
|
|
|
```
|
|
cd aerenew/parallel-executor
|
|
cargo test --release # 7 serial-equivalence tests
|
|
cargo run --release -- harness # 6000-comparison serializability gate
|
|
cargo run --release -- bench # execution-phase speedup (the ~9.4x)
|
|
cargo run --release -- endtoend # END-TO-END pipeline (this report), gas=80 ntx=20000
|
|
cargo run --release -- endtoend 200 20000 5 # heavier tx
|
|
cargo run --release -- endtoend 20 20000 5 # lighter tx
|
|
```
|
|
|
|
Raw logs: `endtoend-logs-2026-07-13/` (env, cargo-test, harness, bench,
|
|
endtoend at gas 80/200/20, empty stderr = zero mismatches).
|
|
|
|
---
|
|
|
|
## 11. One-paragraph honest summary
|
|
|
|
The AERE Block-STM executor's ~9.4x execution-phase scaling was, until now, an
|
|
execution-phase-only measurement. Measured end-to-end (parallel execution +
|
|
serial commit + serial keccak state root) on a 16-vCPU box, under an
|
|
execution-heavy realistic transaction mix, at 0/10/50% conflict, the real
|
|
end-to-end block-production speedup at 16 workers is **~8.3x to 9.1x** - clearly
|
|
lower than the execution-phase figure, exactly by the Amdahl serial tail (commit +
|
|
state-root), which is 5-20% of pipeline time and grows with state footprint.
|
|
Serial-equivalence (parallel state and keccak root identical to sequential) held
|
|
on all 6,000 + 140 checks. The measured end-to-end TPS (~250k at gas=80) is a real
|
|
rollup-batch number for this harness and this box, swings from ~115k to ~500k as
|
|
the assumed per-tx cost changes, and is **not** the 273k documented-conditions
|
|
architectural ceiling and does not reach or imply it. This remains a testnet-grade
|
|
executor measurement; it does not make Block-STM mainnet-active on chain 2800.
|