Releases: bitcoin-ghost/hazync
Release list
v0.8.0 — real Core pow.cpp retarget + all consensus constants from chainparams.cpp
Hazync v0.8.0 — the difficulty retarget and every consensus constant now come from real Core
METHOD_ID: 7a8b29e0d644eecd6c46d125d6646909f017c80a2de679301228d428cdccae3d
(supersedes ffdc6095… / cb114426…)
This release moves the last algorithmic piece of block-connection glue — the difficulty retarget — from
a hand-written transcription to Bitcoin Core's own compiled pow.cpp, and sources every remaining
consensus constant straight from Core's chainparams.cpp. It is a re-baseline: the guest image id
changes, so proofs are re-verified against the new id (the live board is re-proven to match). Valid-block
behaviour is byte-identical — only the id moves.
What changed
- Real
CalculateNextWorkRequiredin the guest. The guest compiles Core's actualpow.cpp+
chain.cpp;calc_next_bitsdrives Core's own retarget through the realCBlockIndex. Proven
byte-identical to the prior (validated) transcription over all 476 mainnet retargets + a fuzz sweep. - Every consensus constant sourced from Core. The guest also compiles
kernel/chainparams.cpp:
calc_next_bitsandblock_subsidyreadpowLimit, the 2-week timespan, the target spacing, and the
halving interval straight from Core's realCChainParams::Main(). Every remaining Rust-side literal
(retarget interval, block weight/sigop limits, the buried soft-fork heights, theSCRIPT_VERIFY_*bit
positions) is runtime-pinned to Core's compiled value on every proving path — a mismatch aborts.
Nothing consensus-relevant is a hand-typed magic number anymore. - Platform shims (
coreshim/): no-op single-threaded locking + logging so Core'schain.h/
chainparams.cppcompile on the freestanding zkVM target. Non-consensus glue only.
New continuously-enforced tests (CI)
- Retarget differential — carved Core reproduces the actual on-chain nBits at all 476 mainnet
retargets; clamp/powLimit/monotonicity invariants hold. - Script-flag differential — the guest's flag schedule is a proven sound superset of Core's
GetBlockScriptFlags; buried forks flip at Core's exact heights; both exception blocks behave. - Chainparams anchor — Core's compiled constants equal the canonical mainnet values.
Compatibility / verification
- Binaries:
hazync-host-x86_64-linux-gnu(CPU) and…-cuda(CUDA, multi-arch sm_80/86/89/90 + PTX 90),
both glibc 2.34+ (ubuntu:22.04), both embedding the new guest id. Verify with./hazync-host-… method-id. - Reproduce the canonical id:
docker build -f reproduce/Dockerfile -t hazync-repro . && docker run --rm hazync-repro. - Proofs under earlier ids don't verify against this id (expected — new guest); the coordinator
re-verifies every submission and the board is re-proven at the new id.
v0.7.2 — in-block spend detection by leaf (host fix)
v0.7.2 — in-block spend detection by leaf, not txid (host fix)
METHOD_ID unchanged: 36a0415d5763ed62e71c44915d36caa34ae840cfd1051587bce1de27be0dd7f5. This is a host-only fix — proofs made with v0.7.0/v0.7.1 still verify, and the guest image is byte-identical.
What changed
- Host: in-block spend cancellation (H1) now keyed on the coin leaf, not its txid — in both
build_full(thecheck-fullvalidator) andbuild_block_carried(the production bridge). The guest has always detected in-block-created coins by leaf membership in the block's created-output set; the host builders used txid membership. These diverge on a pre-BIP34 coinbase-txid collision — a block that spends an older coin whose funding transaction shares a txid with a transaction in the spending block. Because the leaf carries the coin's real (older) creation height, the guest correctly treats such a coin as external, while the txid heuristic falsely cancelled it. Effects fixed:check-fullreportedroot_matches=falseon any busy block with in-block spends (e.g. segwit block 500000);- the bridge could emit a witness the guest rejects, stalling a genesis→tip proof at the first block that spends a colliding-txid coin — a liveness bug on the full-chain path.
- Both builders now recompute the block's created-output leaf set (coinbase + every transaction, unspendable outputs skipped, using the block's creation median-time-past) and detect in-block spends by leaf — the guest's exact rule.
Validation
- Busy segwit block 500000 (thousands of in-block spends) now validates with every consensus flag true (archive node, execute mode).
- Pre-BIP34 blocks 130000 / 140000 validate; the
COV-1 / COV-2 / SEC-2reject-path suite passes.reproducible-image-idCI confirms36a0415dis unchanged.
Assets
hazync-host-x86_64-linux-gnu— CPU build, reproducible at36a0415d(glibc 2.34+ (Ubuntu 22.04+, Debian 12+)). Verify:docker build -f reproduce/Dockerfile -t hazync-repro . && docker run --rm hazync-reproprints36a0415d….hazync-host-x86_64-linux-gnu-cuda— CUDA build (glibc 2.34), multi-architecture: SASS forsm_80/86/89/90(Ampere, Ada, Hopper — A100, RTX 30xx/40xx, L4/L40/L40S, H100) +compute_90PTX for forward-compat to newer GPUs. Reproducible at36a0415d; needs the CUDA 12.6 runtime. Verified proving on an L40S in ~3.3s.
Verify
SHA256SUMS.txt is PGP-signed by the maintainer key (fingerprint 777FE81F8CC077FD3D08055E852C2B3190F5B928): gpg --verify SHA256SUMS.txt.asc SHA256SUMS.txt.
v0.7.1 — BIP30 bridge handling (METHOD_ID unchanged)
v0.7.1 — BIP30 bridge handling (host-side, METHOD_ID unchanged)
METHOD_ID = 36a0415d5763ed62e71c44915d36caa34ae840cfd1051587bce1de27be0dd7f5 (unchanged from v0.7.0). This is a host-side release, so v0.7.0 proofs remain valid — v0.7.1 only adds handling for the two BIP30 blocks.
What changed
- BIP30 bridge fix (#6/#2). The archive-node bridge now emits the BIP30 duplicate-coinbase overwrite witness for blocks 91842 (dup of 91812) and 91880 (dup of 91722), so those grandfathered blocks are provable via the bridge. Without it the guest — which mandates the overwrite at those two hashes — sets
all_ok=falseand the prove panics, hard-stopping any full-chain run at 91842. - Validated end-to-end: the bridge replayed to 91842, emitted
witness.bip30 = OVERWRITE(old_height=91812, dels=1), andprove-range-bridge 91842proved +verify-anyreturnedRANGE-OK lo=91842 hi=91842 out_tip=eccae000…(block 91842's real hash). Block 91880 uses the identical path.
Assets (both at 36a0415d)
hazync-host-x86_64-linux-gnu— CPU (glibc 2.39 / Ubuntu 24.04+).hazync-host-x86_64-linux-gnu-cuda— CUDA (L40S / CUDA 12.6).
Verify
SHA256SUMS.txt is PGP-signed by the maintainer key (777FE81F8CC077FD3D08055E852C2B3190F5B928).
v0.7.0 — sigop fix + corrected CUDA (METHOD_ID re-baseline 36a0415d)
v0.7.0 — sigop-count fix + corrected CUDA binary (METHOD_ID re-baseline)
METHOD_ID: 36a0415d5763ed62e71c44915d36caa34ae840cfd1051587bce1de27be0dd7f5 (was 601d7ca2…). Proofs made against 601d7ca2 (v0.6.x) do not verify against this guest — the board is being re-proven on the new guest. See reproduce/METHOD_ID.
What changed
- Consensus fix (guest, changes
METHOD_ID): P2SH sigop over-count.tx_full_sigopsnow guards the P2SH redeemScript sigop count withIsPayToScriptHash(), matching Core'sGetP2SHSigOpCount. The previous code over-counted every non-P2SH (legacy) input and could reject a Core-valid block near the sigop limit. Reject-valid only — never accept-invalid. (Issue #1 / PR #4.) - Prover reliability (host): the risc0 4.0.5 segment-boundary retry, now on ALL prove paths.
HAZYNC_SEG_PO2segment-limit + 20→19→18 retry is applied to every zkVM prove path (single-block, fold, chunk, aggregate, replay, IVC, snark), guarded by a CI gate. Both binaries below carry it — including the CUDA binary, which in v0.6.x still panicked on ~10% of workloads.
Assets (both built reproducibly at 36a0415d)
hazync-host-x86_64-linux-gnu— CPU build. glibc 2.39 (Ubuntu 24.04+).hazync-host-x86_64-linux-gnu-cuda— CUDA build (L40S/CUDA 12.6), the corrected GPU binary.
Verify
SHA256SUMS.txt is PGP-signed by the maintainer key (fingerprint 777FE81F8CC077FD3D08055E852C2B3190F5B928). Build reproducibly and confirm the id: docker build -f reproduce/Dockerfile -t hazync-repro . && docker run --rm hazync-repro must print 36a0415d….
v0.6.2 — prover reliability fix
Hazync v0.6.2 — prover reliability fix (segment-boundary retry)
METHOD_ID is unchanged: 601d7ca298f32c54137fdb395d0debd31e95e4f084615fa710e5db5c785f05e6. The guest is byte-identical to v0.6.1 — this release only changes the host prover, so every proof made against v0.6.0/v0.6.1 still verifies, and the reproducible build still yields this id.
What changed
The pinned prover (risc0-circuit-rv32im 4.0.5) has a preflight bug: for ~10% of blocks a proving segment packs right to its 2^po2 boundary and the assertion cycles <= 1 << segment.po2 overflows, so the prove panics — on CPU and CUDA. It's a liveness bug only (it never produces a wrong proof — every proof this project has ever published is valid; it just failed to produce a proof for those blocks). This is why the v0.6.1 seeding stalled on ~10% of blocks.
Fix (host-side, so the guest / METHOD_ID is untouched): host now reads HAZYNC_SEG_PO2 for the executor's segment_limit_po2 (default 20 = the risc0 default), and the hazync CLI retries a failed block with progressively smaller segments (20 → 19 → 18). Smaller segments repartition the work and clear the boundary. Normal blocks prove at the default; only the affected ~10% fall back, and the receipt is identical either way. Confirmed: 213/213 affected blocks prove, 0 failures.
Binaries — read this
hazync-host-x86_64-linux-gnu— CPU build, fixed. Includes the segment-boundary fix.hazync-host-x86_64-linux-gnu-cuda— CUDA build, UNCHANGED from v0.6.1 — it does not yet have the fix (it needs a rebuild on a GPU machine, coming in the next release). GPU provers using this binary will still hit the ~10% panic until then; use the CPU binary, or wait for the corrected CUDA build.
Both are the reproducible guest (reproduce/Dockerfile). SHA256SUMS.txt + .asc are PGP-signed with the maintainer key (fingerprint in SECURITY.md).
v0.6.1 — the archive-node bridge
Hazync v0.6.1 — the archive-node bridge
METHOD_ID is unchanged: 601d7ca298f32c54137fdb395d0debd31e95e4f084615fa710e5db5c785f05e6. The guest is byte-for-byte the v0.6.0 guest — this release only changes the host (how witnesses are produced and served), so every proof made against v0.6.0 still verifies, and docker build -f reproduce/Dockerfile . still yields exactly this id.
This release kills the quadratic replay that kept the board pinned near genesis: a persistent archive node now drives one resident Utreexo forest forward over the chain and emits a ready-made witness per block, so a prover proves a block with no replay — O(1) per block instead of O(N).
What changed, file by file
prover/host/src/main.rs— newhost bridge: drives one resident forest forward over the chain from a localbitcoind, emitting a per-block bundle (in-boundary + the realroot_prev+ inclusion proofs). Checkpoints the forest + UTXO-metadata map + MTP/difficulty carry and resumes mid-chain instead of rebuilding from genesis; advances only totip-100and then follows the tip, so the resident forest never enters the re-org zone. Newhost prove-range-bridge <n>proves a block straight from its bundle (mode 6, no replay); the receipt is byte-identical to the replay path's.verify-anyand the guest are untouched.coordinator/server.py—/api/witness/<n>now serves the archive bundle from the bridge directory (local read, no cross-box copy), falling back to the legacy per-block witness. Genesis seed: a[1..hi]receipt is accepted for a claimed[0..hi]range (block 0 is unprovable) and recorded as the proven[1..hi]so the frontier chains from genesis.coordinator/hazync(CLI) —hazync runuses the bridge path (prove-range-bridge, O(1)/block) when the coordinator serves bundles for the whole range, and falls back to genesis replay otherwise.coordinator/deploy/—hazync-bridge.service(the persistent bridge), the coordinator unit wired to the bundle directory, andmigrate-coordinator.sh(WAL-safe DB + receipts migration for co-locating the coordinator beside the bridge)..github/workflows/release-sign.yml— signs whateverhazync-host-*binaries a release carries (CPU-only or CPU+CUDA) rather than a hardcoded pair.README.md— leads with the moat (Bitcoin Core's own consensus code proven in a zkVM) and an honest "proving the chain, live" status.
Binaries
hazync-host-x86_64-linux-gnu— CPU build. Use this to verify proofs (./host verify-any proof.bin); no GPU needed.hazync-host-x86_64-linux-gnu-cuda— CUDA build for GPU proving. Same guestMETHOD_ID.
Both are the reproducible guest (reproduce/Dockerfile). SHA256SUMS + SHA256SUMS.asc are PGP-signed with the maintainer key (fingerprint in SECURITY.md).
Hazync v0.6.0 — round-8 audit: anchor-bound chain proofs + gated witness commitment
Round-8 soundness audit — a five-reviewer completeness + verifier pass over the guest, the C++ VerifyScript boundary, the Utreexo accumulator, enforcement gating, and the end-to-end trust scope. Four dimensions came back sound; one verifier-hole and five completeness deviations were found and fixed (bar the one rule that is mathematically unprovable in a zkVM). Full write-up: AUDIT_2026-07.md.
The guest changed, so METHOD_ID is re-pinned c029cee4… → 601d7ca298f32c54137fdb395d0debd31e95e4f084615fa710e5db5c785f05e6. Proofs made against the old id no longer verify and are being re-proven from genesis. The reproducible-build mechanism is unchanged (pinned toolchain, Bitcoin Core v28.0, secp256k1 v0.5.1, Cargo.lock, reproduce/Dockerfile) — the id is simply a new value. NB: the guest ELF embeds assert!/panic! line numbers, so its exact (compact) formatting is load-bearing for the id — do not cargo fmt the guest.
What changed
- Anchor-bound chain proofs (S5) +
verify-chain.ChainStatenow commitsanchor_id(the double-SHA256 of the base anchor), set in the base step and carried forward, and the newverify-chaincommand pins it to the genesis anchor. A bare mode-2/5 chain receipt is now self-authenticating — a receipt built on a fabricated anchor is rejected — closing a verifier-side foot-gun (RangeStatealready had this via its genesis in-boundary pin). - Witness-commitment activation gate (G3) +
unexpected-witnessincl. coinbase (G2). The BIP141 commitment is now enforced only from segwit height 481824, matching Core; below activation any witness data is rejected. This removes a reject-valid stall on canonical pre-activation blocks (433k–481823). - Block-level
MoneyRange(nFees)(G5). Explicit fee-total range check plus an i128-safecoinbase ≤ subsidy + feesbound. - BIP30 as a documented, gated, bounded invariant (G1). A Utreexo Stump cannot prove non-membership, so Core's general
HaveCoinlookup is replaced by an in-code structural argument (BIP34 uniqueness ≥227931 + the two grandfathered overwrites), sound to ~height 1,983,702. - Hardening (N1/N2/N3). Removed the dead host-supplied
BlockInput.flags(flags are guest-derived); length-prefixed thescriptPubKeyin the UTXO-leaf commitment;tx_full_sigopsnow fails closed on a short prevouts blob.
Per-file breakdown
prover/methods/guest/src/main.rs—ChainState.anchor_id+ carry logic inchain_step/aggregate; witness-commitment activation gate + coinbase-inclusivehas_witness; block-levelMoneyRange; BIP30 bounded-invariant documentation; removed deadBlockInput.flags.prover/methods/guest/verify_input.cpp— length-prefixedscriptPubKeyincoin_leafandtx_out_leaves(N2, changes every leaf hash);tx_full_sigopsreturns a poison cost on a short prevouts blob (N3).prover/host/src/main.rs—verify-chaincommand;ChainState.anchor_idmirror + all anchor constructors; hostcoin_leaflength-prefix (kept byte-identical to the guest); removedBlockInput.flags/Spend.flags.reproduce/METHOD_ID— re-pinned to601d7ca2…with a note not tocargo fmtthe guest.AUDIT_2026-07.md(new),SECURITY.md(round-8 section + status table),docs/SOUNDNESS.md(§3c + completeness matrix),docs/PROVING.md(verify-chain),README.md— audit record and docs.
Verification
Verified on a 2×L40S box against real mainnet data: regress, the adversarial soundness suite (all holes reject), check-bip30, check-full 741000 (byte-exact tip f0e89160…), and a genesis-anchored range proof — all green on this guest.
Assets
hazync-host-x86_64-linux-gnu— CPU host (verify + prove on CPU).hazync-host-x86_64-linux-gnu-cuda— CUDA host (GPU proving).
Both are the 601d7ca2… guest. SHA256SUMS.txt is PGP-signed (maintainer key 852C2B3190F5B928); verify per SECURITY.md.
v0.5.2 — docs currency + diagnostic completeness
Hazync v0.5.2 — docs currency + diagnostic completeness
A small hygiene release so the published binaries match main. The zkVM guest is unchanged — METHOD_ID is still c029cee4be0a0478af667b03d95112304e574beb93e23ffd97afb93d66742059. Every existing proof still verifies, the version-less download URLs are unchanged, and verify-any / prove-range are byte-identical to v0.5.1. No re-prove.
Download (URLs stable across releases)
- Verify a proof (any Linux x86-64, glibc 2.39+):
releases/latest/download/hazync-host-x86_64-linux-gnu - Prove (NVIDIA GPU + CUDA 12.6):
releases/latest/download/hazync-host-x86_64-linux-gnu-cuda
What changed, by file (all host / docs / CI — no guest change)
prover/host/src/main.rs(build_full) — thecheck-fulldiagnostic now sources the real previous-11-block MTP window (recent_times) from the block JSON when present, falling back to the prior placeholder for older fixtures. This letscheck-fullvalidate an isolated real time-locked block; the actual proving path (prove-range→build_block_carried) already derives this itself and is unaffected.prover/fetch_block.py— walks back 11 blocks viapreviousblockhashto supply that MTP window.prover/ci_negative_tests.sh+.github/workflows/adversarial.yml— added the SEC-2 forged-accumulator-inclusion reject test to CI (the guest already rejected it; now it's continuously enforced).SECURITY.md— corrected a stale line that still called BIP68-time "the one open soundness item"; it is fixed (realcoin_mtpcommitted, CSV gate at 419328 inverify_input.cpp). Consistent with the rest of the file now.docs/HAZYNC_ARCHITECTURE.md— corrected the same stale BIP68-time "OPEN" reference; scrubbed the removed k256 ECDSA-acceleration experiment down to a past-tense record; affirmed Schnorr/taproot are fully verified via reallibsecp256k1(only their acceleration was ever open).docs/ACCELERATION.md— reframed k256 /patches/0003/bigint_accel.rs(all removed in v0.5.0) as historical; kept the bigint2 field-backend research intact..gitignore— never commit prover identity / key material.
Soundness
Unchanged and re-verified in CI: block-170 regression, the adversarial suite (every known hole REJECTs), BIP30, the COV-1/COV-2/SEC-2 negative tests, and reproducible-image-id asserting the guest builds bit-for-bit to c029cee4.
v0.5.1 — pre-release hardening + docs
Hazync v0.5.1 — pre-release hardening + docs
A hardening and documentation release following an adversarial pre-release audit. The zkVM guest is unchanged — METHOD_ID is still c029cee4be0a0478af667b03d95112304e574beb93e23ffd97afb93d66742059. Every existing proof still verifies, and the version-less download URLs are unchanged. This release repackages the same guest with an improved host binary and updated docs.
Download (URLs stable across releases)
- Verify a proof (any Linux x86-64, glibc 2.39+):
releases/latest/download/hazync-host-x86_64-linux-gnu - Prove (NVIDIA GPU + CUDA 12.6):
releases/latest/download/hazync-host-x86_64-linux-gnu-cuda
What changed, by file
prover/host/src/main.rs—verify-anynow distinguishes a genuinely invalid/forged proof from a build (METHOD_ID) mismatch, using the proof's own committed guest id. A real forgery is no longer reported as a benign build mismatch. (Verification still fails closed either way — this is diagnostics, not soundness.)coordinator/server.py— DoS/abuse hardening for the public coordinator: per-IP read rate-limit + a short/api/statecache;X-Forwarded-Fortrusted only from a configured proxy + a bounded rate map (anti-spoof / anti-memory-exhaustion); reserved-handle rejection + a pubkey takedown list; and a startup guard that refuses a public bind while verification/signatures are in a permissive mode.coordinator/deploy/nginx-hazync.conf— addslimit_req/limit_conn, a 1-second/api/statemicro-cache, andclient_max_body_size 8m(so folded multi-block receipts don't 413 at the proxy).coordinator/deploy/backup.sh(new) +RUNBOOK.md— back up both the ledger DB and the proof receipts, offsite, with a documented restore drill; plus moderation notes.coordinator/hazync—run <range>fails fast when the range is outside the served witness window, instead of claiming it and then 404-ing mid-fetch.provision-vps.sh— pins Bitcoin Corev28.0and libsecp256k1v0.5.1by immutable commit hash (asserts the checkout), so a re-pointed upstream tag can't silently change the guest. Source is unchanged —METHOD_IDis unaffected.prover/ci_negative_tests.sh(new) +.github/workflows/adversarial.yml— wires the COV-1 (time-too-old) and COV-2 (CVE-2012-2459 merkle-mutation) consensus reject-paths into CI, so a future guest change can't silently regress them.- Docs —
README(glibc prereq, licence section),SECURITY.md(H2 resolved),ROADMAP.md(canonical id corrected toc029cee4),THIRD_PARTY_NOTICES.md(new), and misc currency fixes.
Soundness
Unchanged and re-verified in CI: block-170 regression, the adversarial suite (every known hole REJECTs), BIP30, the new COV negative tests, and reproducible-image-id asserting the guest builds bit-for-bit to c029cee4.
Hazync v0.5.0 — minimal pure-Core guest
Hazync v0.5.0 — minimal pure-Core guest
The zkVM guest is now Bitcoin Core + the Utreexo accumulator, nothing else. The dormant k256 EC-acceleration experiment and an unreachable legacy mode — dead code that was still compiled into the guest — are gone. No alternative crypto implementation is linked in; an auditor reasons only about real Core.
Canonical METHOD_ID: c029cee4be0a0478af667b03d95112304e574beb93e23ffd97afb93d66742059 (was d1fc4065). Reproducible — docker build -f reproduce/Dockerfile . yields exactly this on any machine (verified local == CI). Soundness unchanged: regress + adversarial + BIP30 all pass on the stripped guest.
Install — no build
Linux x86-64, glibc 2.39+ (Ubuntu 24.04+). These URLs always point to the latest release:
Verify a proof (any box, no GPU):
curl -L -o host https://github.com/bitcoin-ghost/hazync/releases/latest/download/hazync-host-x86_64-linux-gnu && chmod +x host
curl https://bitcoinghost.org/hazync/api/proof/1 -o proof.bin && ./host verify-any proof.bin # → RANGE-OK
Prove / contribute (NVIDIA GPU + CUDA 12.6): hazync-host-x86_64-linux-gnu-cuda. See CONTRIBUTING.md.
Both are the canonical guest, so proofs verify and submissions are accepted. Each ships with a .sha256.
What changed
- Guest minimised: removed
k256_ecdsa_verify+ thek256/crypto-bigintdeps +[patch.crates-io]entries, theHAZYNC_ECDSA_BENCHbranch,ecdsa_vec.h,patches/0003, and the unreachablelegacy()mode (the dispatch now fail-closes on an unknown mode). The sound guest never used any of it — ECDSA runs through the real, compiledlibsecp256k1. - New canonical
METHOD_IDc029cee4;reproduce/METHOD_IDupdated, thereproducible-image-idCI job asserts it. - Version-less binary names — the download URL no longer changes across releases.
- Docs (
SECURITY,PROVING,ACCELERATION,HAZYNC_ARCHITECTURE) updated to reflect the removal — "it's Core, nothing else" is now literally true.
Note on the board
The board proofs are being re-proven on this minimal guest; a v0.5.0 binary verifies them to RANGE-OK.