# spec-28: Aere Network Reproducible Builds and Deterministic Release Prepared 2026-07-19. This is the rebuild-the-binary manifest for Aere Network. Its companion, [spec-23 / REPRODUCE.md] (`aerenew/REPRODUCE.md`), is the run-the-tests manifest: that document lets a third party re-run our test suites, formal models, cryptographic known-answer tests, and benchmarks. This document covers the other half of supply-chain integrity: how a third party rebuilds the node client and the contract bytecode from source and confirms, by SHA256, that what is running matches what was published. The two are meant to be read together and deliberately do not duplicate each other. Honesty tags used throughout: - **[REAL]** the artifact exists in the tree at the cited path and was inspected for this document. - **[CONFIRMED]** additionally exercised here (a script was run, a command produced output) on 2026-07-19. - **[VERIFY: ...]** a claim that could not be confirmed from the tree alone and must be checked before it is trusted. - **[MEASURE: ...]** a heavy build or a digest that was not computed here. Run the stated command to produce the real value. Do not quote a figure until you have. If you find a bare claim without a tag where one is warranted, treat it as a bug in this document. --- ## 1. Why reproducible builds matter A blockchain that "nobody owns" is only as trustworthy as the operator's ability to check what code is actually running. Reproducible builds turn that from a promise into a checkable property: > Anyone with the source tree at a given commit can rebuild the byte-identical client image (and the > byte-identical contract bytecode) that the network runs, and confirm the match by SHA256. The supply-chain threat this closes is a tampered binary masquerading as the real release. If the published release carries a canonical SHA256 digest, and a stranger can independently rebuild from public source and land on the same digest, then a modified binary (a backdoored signer, a silent consensus change, an exfiltration hook) cannot pass as the genuine artifact: its digest will differ, and the difference is visible to everyone at once. This is the precondition for two claims the project makes elsewhere: 1. "The Foundation cannot secretly modify the chain." Unenforceable unless the running code is verifiable against published source. 2. "Permissionless validator entry without trusted setup." A community operator joining the validator set (the live set is N=7 today, roadmap to 21) must be able to prove they are running the same code as every other operator, without trusting the Foundation to tell them so. Reproducibility is the mechanism. The rest of this document inventories what is built, states plainly what is not yet live, and gives the exact commands. --- ## 2. What exists today (inventory) Every path below is relative to the repository root `aerenew/` unless stated otherwise. All were read for this document. ### 2.1 The reproducible node image build **`aerenew/node/Dockerfile.reproducible`** [REAL]. A multi-stage Docker build that compiles Hyperledger Besu at a pinned ref and assembles a distroless runtime image. The reproducibility levers actually present in the file: - **Base images pinned by digest, not tag.** The builder stage is `FROM eclipse-temurin@sha256:...` and the runtime stage is `FROM gcr.io/distroless/java21-debian12@sha256:...`. A tag can be retagged to point at different bytes; a digest cannot. The file states the intent explicitly ("the tag is documentation; the digest is the law"). - **`SOURCE_DATE_EPOCH` build arg** threaded into `ENV` and used to stamp fixed mtimes: every source file is `touch -d "@${SOURCE_DATE_EPOCH}"` before the Gradle build and every install output is re-touched after. Identical epoch means identical mtimes throughout, so archive contents do not drift with wall-clock time. - **Deterministic Gradle flags.** `./gradlew --no-daemon --no-build-cache --no-watch-fs -Porg.gradle.parallel=false -PreproducibleBuild=true installDist`. No daemon state, no local build cache, no filesystem watcher, single-threaded, reproducible-archive mode. `GRADLE_OPTS` also sets `-Dorg.gradle.daemon=false -Dorg.gradle.parallel=false -Dfile.encoding=UTF-8`, and `LC_ALL=C`, `TZ=UTC` fix locale and timezone. - **Besu ref pinned** via `ARG BESU_REF=25.5.0`; the build clones `https://github.com/hyperledger/besu` at `v${BESU_REF}` with `--depth=1` and then `rm -rf .git` so no git metadata leaks into a layer. - **Alpine toolchain packages pinned by version** in the builder: `git=2.45.1-r0 bash=5.2.21-r0 unzip=6.0-r14`, and there is no `apk upgrade` (upstream package mutation would break determinism). - **Fixed UID/GID** (`USER 10001:10001`) so no `useradd -m` writes a fresh home-directory timestamp. - **Runtime layer is distroless** (`gcr.io/distroless/java21-debian12`): no shell, no package manager, no version drift in the shipped image. Only the deterministic Besu install, the AERE `config/genesis.json`, and `config/config.toml` are copied in. Genesis and config are copied last so an application-level config change does not invalidate the deterministic Besu layer above it. - **OCI labels** record source, license (Apache-2.0), and `io.aere.reproducible="true"`. **[VERIFY: the two `FROM ... @sha256:` digest values in the Dockerfile appear to be illustrative placeholders, not registry-resolved digests.** The builder digest ends `...a0c2e4f6a8c0e2f4a6c8e0a` and the distroless digest ends `...c1d0e9f8a7b6c5d4e3f2a1b0`; both are visibly patterned rather than random SHA256 output. Before any real reproducible build can resolve, these must be replaced with genuine digests, obtained with `docker buildx imagetools inspect eclipse-temurin:21.0.3_9-jdk-alpine` and `docker buildx imagetools inspect gcr.io/distroless/java21-debian12:latest`, and pinned. As written, the structure is correct and the levers are real, but a `docker build` would fail to pull those exact digests. This is the single most important gap in the "what exists" column.] **Scope note.** This Dockerfile builds stock upstream Hyperledger Besu at `v25.5.0` plus the AERE genesis and config. QBFT consensus and the 0.5 second block period are configured through `config/genesis.json` and `config/config.toml`, not through a client source patch, so the mainnet consensus binary in this image is upstream Besu with AERE configuration. The post-quantum precompile work (Falcon, ML-DSA, SLH-DSA, ML-KEM, HashToPoint at `0x0AE1..0x0AE7`) is a **separate** build path with its own pinned base commit; see section 2.5. [VERIFY: confirm whether the live N=7 validator image is this stock-Besu-25.5.0 build or the PQC-precompile fork build, and if the latter, whether `Dockerfile.reproducible` should target the fork ref rather than upstream `v25.5.0`. The two build recipes exist in the tree independently and their relationship to the live binary should be stated explicitly.] ### 2.2 The third-party verify script **`aerenew/scripts/verify-besu-image.sh`** [CONFIRMED]. A bash script that verifies a locally built image against a published manifest. `./scripts/verify-besu-image.sh --help` was run here and returned exit 0 with the usage banner, so the script is present and executable. What it does: 1. Requires `docker jq curl git` on PATH. 2. Resolves the local image digest: `docker image inspect "$IMAGE" -f '{{.Id}}'` (default image tag `aere-besu:reproducible`). If the image is not present it prints the build command and exits 2. 3. Fetches the manifest JSON, either from a `--manifest` local file or from the URL `https://aere.network/.well-known/besu-image-digest` (overridable with `--url`). 4. Parses `imageDigest`, `sourceCommit`, `sourceDateEpoch`, `besuRef`, `publishedAt`, `chainId` from the manifest. Asserts `chainId == 2800` (exits 3 otherwise). 5. Compares the local digest against `imageDigest`. On mismatch it prints both digests, lists the likely causes (wrong `SOURCE_DATE_EPOCH`, buildkit/arch difference, local edits to genesis/config, upstream toolchain drift), and exits 4. 6. As a sanity check, confirms the manifest's `sourceCommit` exists in the local checkout via `git rev-parse`. On match it prints the VERIFIED banner. The script is real and self-consistent. Its comparison step, however, has nothing live to compare against yet; see section 5. ### 2.3 The design and status document **`aerenew/node/REPRODUCIBLE.md`** [REAL]. The narrative that accompanies the Dockerfile: how the build achieves determinism, how to verify a running node, the intended published-manifest flow, the weekly drift-detection cron, and the strategic rationale (audit-contest scoping, MiCA Article 22 operational controls, validator decentralization). Critically, it already carries an honest status banner dated 2026-07-16 stating that the manifest is not yet published and that the end-to-end guarantee is therefore not yet third-party verifiable. This document does not soften that; it restates it in section 5. ### 2.4 The CI workflow **`aerenew/.github/workflows/reproducible-besu-build.yml`** [REAL]. A GitHub Actions workflow that mechanizes the double-build determinism check. Triggers: push to `main` touching `node/**`, `config/genesis.json`, `config/config.toml`, or the workflow itself; manual `workflow_dispatch` with an optional `besu_ref` input; and a weekly `cron: '0 3 * * 0'` (Sunday 03:00 UTC) for drift detection. Job steps: - Checkout with `fetch-depth: 0` (full history is needed to derive `SOURCE_DATE_EPOCH` from the HEAD commit timestamp). - Compute `SOURCE_DATE_EPOCH=$(git log -1 --pretty=%ct HEAD)`. - Resolve `BESU_REF` from the `workflow_dispatch` input, falling back to the `ARG BESU_REF` line in the Dockerfile. - **BUILD #1 (canonical)** with `--provenance=mode=max --sbom=true`, capture image ID. - **BUILD #2 (independent)** after `docker buildx prune` and with `--no-cache`, capture image ID. - **Compare digests.** On mismatch, emit `::error::`, `docker save` both images, and diff their tar listings for debugging, then fail. - Write `artifacts/besu-image-digest.json` (version, chainId 2800, imageDigest, besuRef, sourceDateEpoch, sourceCommit, workflowRun, publishedAt). This is exactly the schema `verify-besu-image.sh` parses. - Upload that artifact with 365-day retention. - **Sigstore keyless attestation** via `actions/attest-build-provenance@v1` over the image digest (`permissions: id-token: write, attestations: write`). - **Publish manifest to `/.well-known`**, gated on `github.ref == 'refs/heads/main'` and a `WELLKNOWN_DEPLOY_TOKEN` secret. If the secret is unset, the step prints a warning and exits 0 without publishing. [VERIFY: whether `WELLKNOWN_DEPLOY_TOKEN` is configured in the repository's Actions secrets. Its absence is the concrete reason no manifest is served today: the workflow reaches the publish step and skips it. Also [VERIFY] whether this workflow has ever executed, since the public mirror repositories it would run in are themselves not yet published, per REPRODUCE.md section 2.] ### 2.5 The PQC fork build recipe and its build record The post-quantum precompile client is a distinct artifact from the mainnet node image, built by a separate, pinned recipe. It is the "fork" whose KATs REPRODUCE.md section 3c covers. - **`aerenew/pqc-fork/setup-fork.sh`** [REAL] pins the upstream Besu base commit `BASE=d2032017bb3b8cb215a97303980a1e4a643f7180`, fetches it shallow, overlays the AERE PQC EVM layer (five existing precompiles at `0x0AE1..0x0AE5`), then adds the two newer precompiles (`0x0AE6` ML-KEM-768, `0x0AE7` Falcon HashToPoint), committing each stage for a clean patch. - **`aerenew/pqc-fork/build-dist.sh`** [REAL] runs the single full build `./gradlew -q :besu:installDist -x test` and lists the resulting `bin/besu` and lib jars. - **`aerenew/parallel/combined-fork-binary/BUILD_INFO.txt`** [REAL] is a committed build-and-validation record with real SHA256 checksums for a related fork artifact, including: - install tarball `sha256 = 9561c40d591a10c03518a88423ae3098f8ee3791dbddb5f73ce388cd426276fc` - `besu-evm.jar sha256 = 1d2bf44a08f306042c17276764fe05f040fe58371fb8e169fb1804bee815eb2d` - `besu-ethereum-core.jar sha256 = c3b7ebee48e34ec83454d6f3e9dd5baf3261d87cedee1cebe574e7696b7478d2` - the untouched "gold" isolator binary `sha256 = 7c5c0743088e9fa765d54c745814601b3c7a27a892e396156f88092b34c80772` and a JDK-21, `./gradlew installDist -x test` rebuild recipe from a one-file diff. This is the closest thing in the tree to a published expected-digest for a client artifact, though it is a BUILD_INFO text record for a specific offline validation, not a signed manifest served at a stable URL. These checksums are jar-level and tarball-level SHA256, not the Docker image digest that `verify-besu-image.sh` compares. They demonstrate that the project already computes and records real build hashes; they are not yet wired into the manifest the verify script fetches. ### 2.6 The on-chain binary-commitment registry **`aerenew/contracts/contracts/validators/AereValidatorManifest.sol`** [REAL] (with `aerenew/contracts/test/validator-manifest.test.js`). A no-admin Solidity contract where each validator's own QBFT signer key declares the SHA256 `binaryDigest` of the Besu image it runs plus a `manifestUri` (typically the published `.well-known/besu-image-digest`), an operator label, and a region. Commitments are keyed by signer with a monotonic serial and full event history; there is no Foundation override. The contract's own NatSpec is honest that it cannot verify a validator actually runs the claimed binary: that is the job of third-party probing plus the reproducible build. It gives one canonical on-chain place to attest so audits do not drift across mediums. [VERIFY: whether this contract is deployed on chain 2800 and, if so, at what address; the file and its test exist in the tree but deployment was not confirmed here.] ### 2.7 The publication checklist **`aerenew/GITHUB_DEPLOYMENT_CHECKLIST.md`** [REAL]. The gate that every public publish passes. Section 3 below turns it into the deterministic release checklist. It is a GitHub-publication checklist, explicitly not a mainnet deployment procedure: chain 2800 is already live and nothing in it deploys a contract or touches consensus. --- ## 3. The deterministic release process A release is deterministic when it runs the same way every time and produces the same published artifacts from the same source commit. The checklist below composes the publication gate (`GITHUB_DEPLOYMENT_CHECKLIST.md`), the reproducible-build CI (`reproducible-besu-build.yml`), and the verify step (`verify-besu-image.sh`) into one repeatable sequence. Steps marked (roadmap) are not yet live; see section 5. 1. **Freeze the source at a commit.** All release artifacts are keyed to one commit SHA. Nothing is built from a dirty working tree. The commit timestamp is the single source of `SOURCE_DATE_EPOCH`. 2. **Secret scan (hard gate).** No private keys, no `.env` files with real values, no API tokens, no internal host addresses anywhere in the diff. The DevRel publishing flow gates publication on a secret-scan pass and it must not be bypassed. (`GITHUB_DEPLOYMENT_CHECKLIST.md`, and REPRODUCE.md section 1.) 3. **Claim honesty check.** No fabricated or stale performance claims. Every TPS, latency, validator-count, block-time, supply, or "audited" statement in copy must match the checkable state of the chain or an existing dated doc under `docs/`. In particular: consensus is Besu QBFT with classical secp256k1 ECDSA (not proof-of-stake, not post-quantum); block time is 0.5 seconds with single-slot BFT finality; total supply is 2,800,000,000 AERE fixed since genesis-v2 (2026-05-07); 273,000 TPS is a synthetic design ceiling, not a measured mainnet number, and must be stated that way if it appears. No forbidden marketing superlatives ("world-class," "excellence," "gold standard," "trusted by"). No em-dashes in prose copy. Address book (`sdk-js/src/addresses.ts`) current with honest status for any referenced contract. 4. **Green CI (hard gate).** Build, the full test suite, and the secret scan run in CI, on a pull request, before merge. Merge to a protected branch happens through a reviewed pull request, not a direct push. 5. **Deterministic build, twice, byte-equal.** The `reproducible-besu-build.yml` workflow builds the node image on a clean runner, wipes the buildkit cache, rebuilds `--no-cache`, and asserts the two image IDs are identical. A mismatch fails the release and dumps a tar-listing diff for triage. The weekly cron runs the same check to catch upstream toolchain drift before an operator does. 6. **Compute and record the canonical digest.** CI writes `besu-image-digest.json` (chainId 2800, imageDigest, besuRef, sourceDateEpoch, sourceCommit, workflowRun, publishedAt) and uploads it with 365-day retention. 7. **Sign the build (provenance).** Sigstore keyless attestation over the image digest via `actions/attest-build-provenance@v1`, plus `--provenance=mode=max --sbom=true` on build #1. 8. **Publish the manifest at a stable URL (roadmap).** POST `besu-image-digest.json` to `https://aere.network/.well-known/besu-image-digest`, gated on `main` and on the `WELLKNOWN_DEPLOY_TOKEN` secret. This is the step that makes third-party verification possible and is not yet live (section 5). 9. **Tag the release honestly.** If the publish includes a release tag, the tag description matches what actually shipped, not aspirational figures. (`GITHUB_DEPLOYMENT_CHECKLIST.md`.) 10. **Post-publication smoke checks.** Confirm `https://rpc.aere.network` responds before linking it. Spot-check cited contract addresses with `eth_getCode` on the live RPC (non-empty result confirms real deployment). (`GITHUB_DEPLOYMENT_CHECKLIST.md`.) 11. **Third-party verification path (roadmap, once step 8 is live).** A stranger checks out the release commit, builds locally, and runs `verify-besu-image.sh`, which fetches the published manifest and asserts a digest match. Until step 8 serves a real manifest, this step can only be run against a `--manifest` local file, which proves local double-build determinism but not agreement with a Foundation-published canonical digest. Optionally, operators record their running binary's digest on chain via `AereValidatorManifest` (section 2.6) so the attestation is queryable, not just claimed. --- ## 4. Contract bytecode reproducibility The node client is one supply-chain surface; the deployed contracts are the other. Reproducing contract bytecode means: compile the source with the pinned compiler and settings, and confirm the result matches what is deployed on chain 2800 via `eth_getCode`. **Pinned compiler and settings** (`aerenew/contracts/hardhat.config.js`) [REAL]: - Global compiler `solc 0.8.23`, `optimizer.enabled = true`, `optimizer.runs = 1` (runs=1 chosen for contract-size headroom, documented in-file), `viaIR = true`. Default EVM version is shanghai for 0.8.23. - One per-file override: `contracts/AereCancunCanary.sol` compiles with `solc 0.8.24`, `optimizer.runs = 200`, `evmVersion = "cancun"`. Every other contract stays on 0.8.23 so its bytecode is untouched by the canary. The Foundry profile (`aerenew/contracts/foundry.toml`) [REAL] independently pins `solc = '0.8.23'`, `optimizer_runs = 200`, OpenZeppelin remapped to the single installed copy (OpenZeppelin 4.9.6). Note the two profiles differ in `optimizer_runs` (Hardhat 1, Foundry 200) and Foundry is scoped only to `contracts/pqc` for symbolic analysis, so the **functional deploy artifacts come from the Hardhat build**; use the Hardhat settings when reproducing deployed bytecode, not the Foundry profile. **Reproducing deployed bytecode:** ```bash cd aerenew/contracts npm ci # pinned toolchain (hardhat, solc 0.8.23, OZ 4.9.x) npx hardhat compile # deterministic given the pinned solc + settings above # The deployed runtime bytecode for a given contract is in # artifacts/contracts/.sol/.json -> .deployedBytecode ``` Then compare against what is live: ```bash # Fetch on-chain runtime bytecode for a deployed address on chain 2800: curl -s -X POST https://rpc.aere.network \ -H 'content-type: application/json' \ --data '{"jsonrpc":"2.0","id":1,"method":"eth_getCode","params":["","latest"]}' # Compare the returned 0x… string against the compiled .deployedBytecode. ``` **Honest caveat on the metadata hash.** `hardhat.config.js` does not set `settings.metadata.bytecodeHash`, so solc's default applies and the compiled bytecode ends with a CBOR-encoded metadata section that embeds a hash of the contract metadata (source, settings, compiler). Two compiles agree on that trailer only when the full metadata matches, so a byte-exact `eth_getCode` comparison requires the identical source, identical `solc 0.8.23`, identical optimizer and `viaIR` settings, and identical import paths. If any of those differ, the executable opcodes can still match while the metadata trailer differs. For a strict match, either reproduce the exact metadata or compile with `metadata.bytecodeHash = "none"` on both sides and compare the code minus the trailer. [MEASURE: pick one deployed contract, compile it under the pinned settings, and publish both the compiled `deployedBytecode` and the `eth_getCode` result so the match (or the metadata-only difference) is on the record. No specific contract byte comparison was run for this document.] REPRODUCE.md section 3a is the companion here: it covers running the contract **test** suite (137 Hardhat test files, spot-checked green on 2026-07-19) and the symbolic layer. This document covers reproducing the **bytecode**; the two together cover both "does it behave as claimed" and "is the deployed code the compiled code." --- ## 5. Honest status: done vs roadmap **Done and real today (local reproducibility):** - The digest-pinned, multi-stage `Dockerfile.reproducible` with `SOURCE_DATE_EPOCH`, deterministic Gradle flags, distroless runtime, and fixed UID/GID. [REAL] - The `verify-besu-image.sh` script, executable and self-consistent, with a `--manifest` local-file path that works without any network dependency. [CONFIRMED runs] - The `reproducible-besu-build.yml` CI workflow: double build, byte-equal compare, provenance and SBOM, Sigstore attestation, artifact upload. [REAL, execution not confirmed here] - The publication gate (`GITHUB_DEPLOYMENT_CHECKLIST.md`): secret scan, claim honesty, green CI. [REAL] - Pinned contract compiler settings (`solc 0.8.23`, optimizer, `viaIR`) enabling deterministic contract compilation. [REAL] - Real, recorded SHA256 checksums for fork jar and tarball artifacts in `combined-fork-binary/BUILD_INFO.txt`, and pinned fork base commits in `pqc-fork/`. [REAL] - The `AereValidatorManifest` on-chain attestation contract. [REAL, deployment unconfirmed] **Roadmap, not yet live (third-party verifiability):** - **The public digest manifest is not published.** This is the load-bearing gap. Per the status note in `REPRODUCIBLE.md` (dated 2026-07-16), a live check of `https://aere.network/.well-known/besu-image-digest` returned `Content-Type: text/html`, the site SPA fallback, not the JSON manifest. So the third-party comparison step in `verify-besu-image.sh` has nothing canonical to diff against. The CI publish step exists but is gated on a `WELLKNOWN_DEPLOY_TOKEN` secret and skips (with a warning) when the secret is unset. State it plainly: the build recipe exists and is reproducible locally; **publishing the canonical expected digests, so a stranger can diff against them, is the remaining step.** [VERIFY: re-check the `.well-known` URL and whether the deploy token is configured before making any "published" claim.] - **The Dockerfile base-image digests appear to be placeholders** (section 2.1), so even a local `docker build` will not resolve until real registry digests are pinned. This must be fixed before the first genuine reproducible build. [VERIFY] - **Kernel and host environment are not pinned** for operators. `REPRODUCIBLE.md` notes CI pins `ubuntu-22.04` but operators run their own systems; a recommended host kernel plus a reference OS image (Yocto / NixOS) is Phase 2. - **Genesis-snapshot distribution** for operators bootstrapping from state (rather than from genesis) needs its own signed snapshot manifest; tracked separately. - **Public source repositories that the site and docs reference do not all resolve yet** (REPRODUCE.md section 2, PASUL 0: `git.aere.network/aere-network/aerenew` returned 404 on 2026-07-19). Reproducible builds presume the source is actually published; until it is, "rebuild from source" over-promises. Bottom line: everything needed to reproduce the build **locally** and to prove double-build determinism is in the tree. The one thing standing between that and a stranger independently confirming a running validator matches a Foundation-published binary is the publication of the signed digest manifest at a stable URL, plus replacing the placeholder base-image digests. Neither is a research problem; both are wiring. --- ## 6. Reproduction commands Concrete values from the current checkout (`aerenew/`, HEAD `6c55540`, commit timestamp `1781391508` = 2026-06-14T01:58:28+03:00). Substitute the release commit when reproducing a specific release. ### 6.1 Rebuild the node image and check double-build determinism ```bash # From a checkout of the release commit: cd aerenew SDE=$(git log -1 --pretty=%ct HEAD) # SOURCE_DATE_EPOCH from the commit, e.g. 1781391508 # Build once. docker build \ --build-arg SOURCE_DATE_EPOCH=$SDE \ --build-arg BESU_REF=25.5.0 \ -f node/Dockerfile.reproducible \ -t aere-besu:reproducible \ . # Read the resulting image digest. docker image inspect aere-besu:reproducible -f '{{.Id}}' ``` [MEASURE: this is a full Besu compile in Docker (tens of minutes, several GB). It was NOT run for this document, and it will not resolve until the placeholder base-image digests in `node/Dockerfile.reproducible` are replaced with real registry digests (section 2.1). Publish the resulting image ID once the build succeeds; that value is the canonical digest.] ```bash # Double-build determinism, the check CI automates: docker build --build-arg SOURCE_DATE_EPOCH=$SDE --build-arg BESU_REF=25.5.0 \ -f node/Dockerfile.reproducible -t aere-besu:build1 . docker buildx prune -f docker build --no-cache --build-arg SOURCE_DATE_EPOCH=$SDE --build-arg BESU_REF=25.5.0 \ -f node/Dockerfile.reproducible -t aere-besu:build2 . diff <(docker image inspect aere-besu:build1 -f '{{.Id}}') \ <(docker image inspect aere-besu:build2 -f '{{.Id}}') && echo "REPRODUCIBLE" ``` [MEASURE: two full builds. Not run here. The identical-ID assertion is the reproducibility property.] ### 6.2 Verify against a manifest ```bash cd aerenew # Against the published manifest (roadmap; not serving JSON yet): ./scripts/verify-besu-image.sh --image aere-besu:reproducible # Against a local manifest file (works today, proves local determinism, not # agreement with a Foundation-published canonical digest): ./scripts/verify-besu-image.sh --image aere-besu:reproducible --manifest ./local-manifest.json ``` [CONFIRMED: `./scripts/verify-besu-image.sh --help` was run on 2026-07-19 and returned exit 0. The digest-comparison path was not exercised because no image was built here and no manifest is served.] ### 6.3 Reproduce contract bytecode ```bash cd aerenew/contracts npm ci npx hardhat compile # Compare artifacts/contracts/.sol/.json .deployedBytecode # against eth_getCode for the deployed address (see section 4 for the curl call). ``` [MEASURE: run a specific contract's compile-and-compare and publish both byte strings. Mind the metadata-hash trailer caveat in section 4. Not run for this document.] ### 6.4 Rebuild the PQC precompile fork (separate artifact, Linux) ```bash cd aerenew/pqc-fork bash setup-fork.sh # clones besu@d2032017, overlays fork EVM, adds 0x0AE6/0x0AE7 precompiles bash build-dist.sh # ./gradlew :besu:installDist -x test (one full build) ``` [MEASURE: heavy Linux-only build, targets `/root/besu` on a scratch box. Not run here, and never on the live infra box, which runs production services. Publish the resulting `bin/besu` and jar SHA256 values and compare against `combined-fork-binary/BUILD_INFO.txt`.] --- ## 7. Relationship to REPRODUCE.md (spec-23) `aerenew/REPRODUCE.md` (spec-23) and this document (spec-28) are the two halves of "verify Aere yourself" and are meant to be non-overlapping: - **spec-23 (REPRODUCE.md): run the tests.** Re-run the Hardhat suite, the z3 SMT formal models, the PQC KAT/ACVP harnesses, and the gas benchmarks, and get the same results we get. It answers "does the code behave as claimed." - **spec-28 (this doc): rebuild the binary.** Rebuild the node image and the contract bytecode from source and confirm the SHA256 match against the published release. It answers "is the running code the published code." Both are gated by the same publication gate (secret scan plus green CI) and both are honest that the public source repositories and the digest manifest are not fully live yet. Neither pushes anything; they document the verification story and the exact commands to execute it.