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.
496 lines
29 KiB
Markdown
496 lines
29 KiB
Markdown
# 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/<Name>.sol/<Name>.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":["<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
|
|
|
|
```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/<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)
|
|
|
|
```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.
|