An append-only log that commits in 1040 bytes, however long it gets
A Merkle Mountain Range on Solana devnet: the account keeps at most 32 peak hashes and a count — never the leaves, never the interior nodes — so a log of ten entries and a log of a million cost the same 1040 bytes. A Solidity verifier on Base Sepolia checks the same proofs from the same specification. Both were deployed by us, to devnet and Base Sepolia.
Hzc3ss3WxYMv4NAd1ish5idKZTbtvrb2jx4CtwinC25a
the program
0xa8c151dE9b7AE952f2a712eBe42b36C5f03a430b
the verifier
The log account is
BxrToumKoEDmnCbVfXSbr8Vz9U6rVU9YWYAAhHxx5Jv9. It holds
1023 leaves and its commitment is
0x3fe25b476b431746b5357fcced1bca1493f5bc86ef7a32a1e9ee30d142570727. The program's upgrade authority has been
revoked — it is immutable, set in
this transaction.
What the compute cost actually does
An append merges as many peaks as the new leaf count has trailing zeros, so the
cost is a sawtooth: appending at n = 7 runs three merges and appending at
n = 8 runs none. Every figure below was measured once against devnet and committed to the
repository; this page performs no chain call, because a compute-unit cost is a property of a run
and re-measuring on each visit would put a different number under a fixed prediction.
The predicted column comes from a cost model committed before a single measurement existed, so it could not be fitted to the results. Its shape held: cost rises monotonically with the hash count, the measured-to-predicted ratio spreads only 1.463× against the model's own 2× threshold for declaring the shape wrong, and 8, 16 and 32 are local minima. Its constants did not: the model said 1500 CU of overhead and 350 CU per hash; the measurements say 2437.8 and 165.8.
| n | merges | hashes | predicted | measured | naive rebuild | tx |
|---|---|---|---|---|---|---|
| 7 → 8 | 3 | 5 | 3250 | 3266 | 4925 | explorer |
| 8 → 9 | 0 | 3 | 2550 | 2926 | 5256 | explorer |
| 9 → 10 | 1 | 4 | 2900 | 3100 | 5588 | explorer |
| 15 → 16 | 4 | 6 | 3600 | 3436 | 7578 | explorer |
| 16 → 17 | 0 | 3 | 2550 | 2930 | 7909 | explorer |
| 17 → 18 | 1 | 4 | 2900 | 3100 | 8241 | explorer |
| 31 → 32 | 5 | 7 | 3950 | 3602 | 12883 | explorer |
| 32 → 33 | 0 | 3 | 2550 | 2930 | 13215 | explorer |
| 33 → 34 | 1 | 4 | 2900 | 3100 | 13547 | explorer |
| 63 → 64 | 6 | 8 | 4300 | 3768 | 23495 | explorer |
| 64 → 65 | 0 | 3 | 2550 | 2930 | 23826 | explorer |
| 127 → 128 | 7 | 9 | 4650 | 3945 | 44717 | explorer |
| 128 → 129 | 0 | 3 | 2550 | 2941 | 45049 | explorer |
| 255 → 256 | 8 | 10 | 5000 | 4111 | 87163 | explorer |
| 256 → 257 | 0 | 3 | 2550 | 2941 | 87494 | explorer |
| 511 → 512 | 9 | 11 | 5350 | 4277 | 172053 | explorer |
| 512 → 513 | 0 | 3 | 2550 | 2941 | 172385 | explorer |
| 1022 → 1023 | 0 | 11 | 5350 | 4217 | 341502 | explorer |
The naive-rebuild column is computed, not measured. naive_rebuild_cu uses the MODEL constants; naive_rebuild_cu_fitted uses the measured ones. Both are computed, neither is measured: at n=1023 a rebuild needs 2045 hashes, which exceeds the 1,400,000 CU per-instruction ceiling under the fitted cost and would also need account space for every leaf.
Where the model was wrong
The model said: MODEL.md, section 'The naive baseline': at n=1023 a rebuild is 'over Solana's per-instruction ceiling even with the compute budget raised to its 1,400,000 maximum'.
WRONG, and wrong on the model's own arithmetic as well as on the measured constants. With the model's own PER_HASH=350 the figure is 717,250 CU, which is already under 1,400,000 - so the sentence did not follow from the numbers printed two lines above it.
A naive rebuild at n=1023 costs about 341,499 CU, roughly 81x the MMR append, and DOES fit under the raised ceiling. It stops fitting at around n = 4,215 leaves. The compute argument is therefore a ratio argument at this size, not a possibility argument.
The SPACE argument, which was never in doubt: the MMR account is 1040 bytes at any length, while storing 1023 leaves needs 32,736 bytes for the leaves alone. Solana's 10 MB account ceiling caps a leaf-storing log near 327,000 entries; the peaks-only log has no such bound below 2^32.
The model file was not edited to match the results. A prediction quietly corrected after the data arrives is worth nothing, so the correction lives beside the measurements that forced it.
One finding nobody planned
Two appends in the table perform the same number of hashes and cost different
amounts. At n = 511 the work is 4277 CU across nine
merges; at n = 1022 it is 4217 CU across nine
bagging hashes. The 60 CU between them is loop overhead the model had
assumed was identical.
What this does not claim
- The Base Sepolia verifier proves a proof is consistent with a root it is handed. It has no view of Solana and cannot confirm that root is the one the devnet account holds — the operator supplies it. This is not cross-chain verification.
- The log stores no leaves. Recovering them means replaying the transactions that appended them, which is what the repository's CLI does.
- Appends are permissionless in this build. There is no access control, because the property on show is the commitment structure and an authority check would demonstrate something else.
- It is not a rollup, a bridge or a light client.
The two repositories
- pigfox/mmr-log — the specification, the
no_stdRust crate, the native Solana program, the CLI and the benchmark. - pigfox/mmr-verifier — the Solidity verifier, with a differential gate that runs the Rust reference over FFI and requires byte-identical roots and proofs.