aere-docs/AERE-REPRODUCIBLE-BUILDS.md
Aere Network e4cead319d Initial public release
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.
2026-07-20 01:01:36 +03:00

29 KiB

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:

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/<Name>.sol/<Name>.json  ->  .deployedBytecode

Then compare against what is live:

# 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":["<CONTRACT_ADDRESS>","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

# 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.]

# 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

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

cd aerenew/contracts
npm ci
npx hardhat compile
# Compare artifacts/contracts/<Name>.sol/<Name>.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)

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.