Midstate

github.com/ciphernom/midstate — f84fb78e8a761448a760e2331efa95fde3b04340

Audit date ·

Audits are prepared by the site owner with a self-hosted (local) AI, checked against the exact commit above, and hand-edited before publishing. This is not financial, legal, or investment advice. Read it as one person's notes on one commit at one date. Do your own research.

This is a point-in-time review of code quality and tokenomics at the commit above, not a safety certification. Projects can change after this date. Check for newer releases or a newer audit before relying on these scores.

Hand-written Rust L1; BLAKE3 sequential-time PoW and post-quantum WOTS+MSS signatures. No premine - the initial coins are burned as an inscription, and the coinbase must equal reward plus fees exactly.

Code 8.5 · Tokenomics 10 · Risk 8.5 · GOOD

🪙 Midstate — Code & Tokenomics Audit

Repo: ciphernom/midstate at commit f84fb78e8a761448a760e2331efa95fde3b04340 (re-cloned 2026-10-20; the 2026-10-19 pass read 493bd5a)
Date: 2026-10-17 Scope: recon, code review (money and consensus path read line by line), tokenomics, write-up. All phases ran. Skipped: on-chain supply check (no node or RPC consulted) and any third-party review of the novel crypto. Hashrate and profitability are out of scope for this scale.

Supersedes the 2026-10-16 note at cd579d9 (old scale, "risk 6/10"). Re-audited at v5.0.0 under the audit-crypto arithmetic.

🎯 Verdict: GOOD (code 8.5 / tokenomics 10.0) — moved up from GOOD on 2026-10-20

Midstate is a hand-written Rust layer-1: BLAKE3 sequential-time proof of work, post-quantum WOTS+MSS signatures, UTXO set in a sparse Merkle tree. The money path is clean. The block reward is a pure function of height, every node recomputes it, and a block's coinbase must equal reward + fees exactly or the node rejects the block. There is no premine, no mint path to the native coin, and no dev or founder share in consensus.

This scores code and tokenomics only. It says nothing about whether Midstate survives, whether it gets listed, or whether the novel cryptography holds up. One human author plus AI-generated commits, and the post-quantum signatures, the sparse Merkle tree and the ASERT variant have no independent audit. Those are survival risks, not trust problems, and they do not move this number.

Re-checked against current HEAD on 2026-10-20. Tokenomics still scores 10.0. Code moves from 6.0 to 8.5 because the MSS keygen bug is fixed: the checkpoint file is now keyed on a blake3 hash of the seed, not just the tree height (src/core/mss.rs:199-206, commit c903d7b). Two findings remain — a replay path that accepts local blocks with no cryptography at all, and a safety contract that exists only as a comment. This is a code and tokenomics judgement only; it says nothing about survival, liquidity or the fact that the author's own docs say the chain is not for real value.

🔑 At a glance

FieldValue
ProjectMidstate (unit "MS", integer values)
Chain / consensusOwn L1; BLAKE3 sequential-time PoW (1,000,000 iterations), ASERT difficulty, 60 s target
Code score8.5 / 10 (was 6.0 at 493bd5a)
Tokenomics score10.0 / 10
Risk score8.5 / 10 (the lower of the two)
Verdict✅ GOOD on code and tokenomics — not a survival or liquidity judgement

🔗 Links & sources

WhatLinkStatus
🏠 Homepage🔍 GitHub homepage field, not fetched
💻 Source✅ cloned in this audit
🔎 Explorer—
📄 Whitepaper—
📣 Announcement—
💬 Socials—

🧮 Risk score inputs

#Findingfile:lineReachableDeductionApplies to
1✅ FIXED at HEAD — deduct nothing. Was HIGH, reachable: MSS key generation resumed from mss_h{height}.checkpoint keyed only on the tree height, never on the seed. If keygen is interrupted and a different seed later generates a same-height key in the same directory, the old leaves are loaded, the tree no longer matches its seed, and every signature from that tree fails to verify. No seed fingerprint, no validation of what was loaded. The author's own midwimble repo fixes this in its vendored copy by keying the file on a seed fingerprint — Midstate did not take the fix backsrc/core/mss.rs:113-127, src/core/mss.rs:164-170live (wallet keygen path)−0 (fixed, c903d7b)code
2MEDIUM — apply_batch_trusted bypasses both PoW and signature checks. Used on the disk-replay and state-rebuild path, so the trust boundary is local disk: a tampered or corrupted local database is re-accepted with no cryptography. The doc-comment states the constraint ("Bypasses ALL cryptography ... MUST ONLY be used when replaying blocks loaded from the local trusted disk database"), so it is documented, not hiddensrc/core/state.rs:194-204, callers src/node.rs:7406,7442,7456live (local replay only)−1.0code
3LOW — apply_batch_skip_pow accepts a caller-supplied verified_mining_hash. Correct as written: PoW is verified on the header chunk first (src/node.rs:4811-4830, gated at src/node.rs:4840-4850) and batch-to-header final_hash equality is re-checked per batch (src/node.rs:5162-5166). But the safety rule is a doc-comment with no runtime assertion, so a future caller can silently break itsrc/core/state.rs:181-190, src/node.rs:5162-5166live−0.5code
4No hard cap — tail emission continues forever. The halving bottoms out at 1 unit per block and stays there. Deliberate, and stated in the docssrc/core/types.rs:996-999, DESIGN.md:68-69live−0tokenomics
5Issuance is enforced in consensus: coinbase total must equal block_reward(height) + fees exactly. No miner-declared amount exists anywhere in the header or the coinbasesrc/core/state.rs:438-467, src/mining.rs:63-72live−0tokenomics
6Premine: none. Genesis pays two outputs of 536,870,912 whose address and salt bytes are the plaintext inscription message, so no known WOTS secret key can ever spend themsrc/core/types.rs:292-340live−0tokenomics
7Dev / founder / treasury share: none in consensus. The pool's pool_fee_percent is a pool operator's own cut inside its own payout, not a protocol tax. Solo coinbase pays only the miner's derived addresssrc/pool.rs:877-1325, src/mining.rs:63-95live−0tokenomics
8Emission in code matches the documented curve exactly (2^30 initial, halving every 525,600 blocks, floor 1)src/core/types.rs:976-998 vs yellowpaper.md:232, DESIGN.md:68-69live−0tokenomics
923 real unsafe { blocks, all in SIMD kernels, one of which (wots_simd) is on the signature verification path. Justified and parity-tested, so no deduction under the "no justification" rulesrc/core/simd_mining.rs (17), src/core/wots_simd.rs (6), used at src/core/wots.rs:31,110,133live−0code
10EXTENSION_ITERATIONS drops 1,000,000 → 100 under the fast-mining cargo feature. CI builds without it, so shipped binaries are unaffected. Build-flag footgun, recorded at INFOsrc/core/types.rs:902-905, .github/workflows/build.yml:118dead in release builds−0code
code deductions, one at a time:
  1.0 -> 1.5   (the 2.5 MSS finding is fixed at HEAD)
tokenomics deductions, one at a time:
  0.0

code_score       = 10 − (1.0 + 0.5)                   = 8.5
tokenomics_score = 10 − 0                              = 10.0
risk_score       = min(8.5, 10.0)                     = 8.5

Instant override check: none fired. All five checked —

  1. No key, role or admin path mints native supply or changes the issuance schedule outside consensus. The RPC surface is explorer reads plus /commit, /send, /check (src/rpc/server.rs:133-160). No faucet, no mint, no admin credit route. The activation heights are compiled-in constants (src/core/types.rs:918-967), so changing the schedule means shipping a new binary.
  2. No code sends a seed, private key or wallet contents anywhere. Wallet keys are Argon2id + AES-256-GCM at rest (src/wallet/crypto.rs:1-79). The MSS checkpoint bug writes key material to a local file; it never leaves the machine, so this is a correctness bug, not exfiltration.
  3. No backdoor, killswitch or remote-code path found in src/, crates/walletd, wasm-wallet.
  4. Not a fork presented as original work with the upstream identity stripped. BLAKE3 is an external library used openly, and both the sequential-chain construction and the ASERT difficulty variant are named by name in the docs.
  5. No supply or privacy claim that the code contradicts — see the tokenomics table.

🔒 Code

Commit audited for the score shown above: f84fb78 (re-check completed 2026-10-20). The original pass ran 2026-10-17 at 493bd5a and scored code 6.0; the re-check below raised it to 8.5.

📊 Tokenomics

ItemValueEvidenceFlag
PremineNone. The genesis batch pays two outputs of 536,870,912 each (2^29), whose address and salt fields hold plaintext inscription bytes ("Harvest Now, Decrypt Later: The Quantum Era's Encryption Challenge"). An address is hash(p2pk bytecode), so spending needs a WOTS secret key whose public key hashes to that plaintext — no such key is known or derivable. The coins are burned by constructionsrc/core/types.rs:292-340, src/core/types.rs:122-124, applied through the normal coinbase check at src/node.rs:1538✅ no premine, deliberately burned
Mint authority over the native coinNone. No faucet, mint or credit route. The RPC surface is explorer reads plus /commit, /send, /check (src/rpc/server.rs:133-160). Value enters the ledger only through the coinbase checksrc/rpc/server.rs:133-160✅ none
Issuance enforced in consensusYes. On every block accept the node recomputes block_reward(state.height), adds the tally of fees, and requires the coinbase outputs to sum to exactly that amount — not less, not more (coinbase_total != allowed_value bails)src/core/state.rs:438-467✅ enforced in consensus
Hard capNo hard cap — tail emission continues forever. The halving bottoms out at a reward of 1 unit per block and stays there forever. Under this scale that is a design fact, not a deductionsrc/core/types.rs:996-999, DESIGN.md:68-69✅ no cap — perpetual tail at 1 unit/block
Emission curveInitial reward 2^30 = 1,073,741,824 units. Halves every BLOCKS_PER_YEAR = 525,600 blocks (one year at 60 s blocks). Floor of 1 after 30 halvings. Arithmetic shift with .min(30), so the shift can never overflowsrc/core/types.rs:976-999✅ matches the docs exactly
Supply totalsThe schedule sums to roughly 2,102,400,000 units before the tail takes over, then 1 unit per block forever. The repo states no cap constant, and none is neededsrc/core/types.rs:976-999🔍 derived from code, not asserted in docs
Dev / founder / treasury shareNone in consensus. The solo coinbase pays only the miner's derived WOTS address; pool mode pays the pool's MSS address and watermarks the miner's payout address into the salt. pool_fee_percent is a pool operator's own configuration, not a protocol tax, and it never appears in consensus validationsrc/mining.rs:63-95, src/pool.rs:877-1325✅ 0% dev tax
TreasuryNo treasury exists, so there is no spending key to consider. The genesis burn is the only large holding and it has no spend pathsrc/core/types.rs:292-340✅ no treasury, no key
Docs vs codeClaim: "Block Reward: Starts at 1,073,741,824 (2^30). Halving: Reward halves every 525,600 blocks (~1 year at 1-min blocks). Minimum reward: 1" (DESIGN.md:68-69) and yellowpaper §6.5 with the power-of-two coinbase constraint. Code confirms every part of itDESIGN.md:68-69, yellowpaper.md:230-235 vs src/core/types.rs:976-999, src/core/state.rs:447-467✅ docs match code
Genesis reproducible from published paramsYes. Anchored to Bitcoin block 938,708 (0000000000000000...af2e) and its height, with a hardcoded initial target and timestamp. No config or local state enters it — the comment says divergence would silently partition peer discoverysrc/core/types.rs:285-345✅ reproducible
Schedule tamper resistanceV2_ACTIVATION_HEIGHT, V4_ACTIVATION_HEIGHT = 163,675 and V5_ACTIVATION_HEIGHT = 340,000 are compiled-in constants. Changing one is a code change plus a release users must adopt — a hard fork. No admin endpoint touches emissionsrc/core/types.rs:918-967✅ not admin-changeable

🕵️ Privacy

🚩 Red flags

✅ Green flags

📋 Context (does not affect the score)

SignalValue
Repo / commit auditedoriginal pass ciphernom/midstate at 493bd5a389f87dacaa6c5fabf570834d158d18a9, version 5.0.0, last commit 2026-10-17; re-checked 2026-10-20 at f84fb78e8a761448a760e2331efa95fde3b04340
Contributors / commitsshallow clone holds 50 commits. Visible: ciphernom, Ciphernom, "Security Patch", Claude. Full history not fetched
AI-assisted commitsyes — 9 co-author trailers (7 Claude Opus 4.8, 2 Claude Opus 5.5)
Relaunch, rename or abandoned predecessornone found in this clone. Repo dates to 2026-02-10 per the earlier note; domain about three months old
Independent auditnone found in-repo. The post-quantum signatures, the SMT accumulator and the ASERT variant are unaudited
Public RPC or explorer reachableno public JSON API found; the node's explorer RPC is loopback (crates/walletd/src/node_host.rs:38)
Market datanot relevant at this stage
Hashrate, difficulty, power cost, profitabilityout of scope for this scale

❓ What I could not check

🧭 Bottom line

The consensus core is small, careful and readable, and the money path is exactly what you want it to be: the subsidy is a pure function of height, every node recomputes it, and a block's coinbase total must equal reward + fees exactly or the node rejects it (src/core/state.rs:438-467). There is no premine — the initial coins are burned into an inscription — no mint path to the native coin, and no dev, founder or treasury share in the protocol at all.

Tokenomics scores 10.0 because there is nothing to deduct. Note the shape of the supply: halving every 525,600 blocks down to a floor of 1 unit per block, forever. No hard cap, tail emission continues forever. That is a design choice, not a defect, and issuance being a pure function of height means the absent cap constant means nothing.

Code scores 8.5 on current HEAD, which puts this in the GOOD band for code and tokenomics. The wallet keygen bug that drove the old 6.0 is fixed — the checkpoint is now named after a hash of the seed (src/core/mss.rs:199-206), so a second keygen in the same directory can no longer load another seed's leaves. Two things keep it out of 9.0: apply_batch_trusted still accepts locally stored blocks with no PoW and no signature check (src/core/state.rs:194-204), and apply_batch_skip_pow's safety contract is still only a doc-comment (src/core/state.rs:178-190). A runtime assertion on the caller-supplied mining hash and an explicit operator opt-in for trusted replay would take code to 9.0. GOOD describes only the scored code and tokenomics; it does not certify operation, survival, or liquidity. It says nothing about whether the chain survives, and the author's own docs say it is not for real value.

Two remaining issues keep the code score below 9.0: apply_batch_trusted accepts locally stored blocks with no PoW and no signature check (src/core/state.rs:194-204, src/node.rs:7406), and apply_batch_skip_pow's safety contract exists only as a doc-comment (src/core/state.rs:171-189). A runtime assertion that the caller-supplied mining hash equals compute_header_hash(batch.header()), and an explicit operator opt-in flag for trusted replay, would take code to 9.0.

The unmeasured risk here is not the arithmetic of issuance — it is that the post-quantum signature scheme, the sparse Merkle accumulator and the sequential-hash PoW have never been reviewed by anyone but the author. This scale does not score that. It remains the first thing to fix before moving real value.


🔗 Related

Files we opened

src/core/state.rs:438-467

src/core/types.rs:976-999

src/core/types.rs:996-999

src/core/types.rs:292-340

src/core/mss.rs:199-206

src/core/state.rs:194-204

src/mining.rs:63-95

src/core/types.rs:902-905

src/wallet/crypto.rs:1-79

Every file listed here was opened by us during the audit. Nothing here is a guess.

Back to Projects