Release verification
Before a Cosmovisor upgrade, curators recurate the published terpd ELF from the git tag, not from a developer laptop that already has module caches and gitignored crates. Operators can treat a passing recurate as: this S3 object is the same bytes we get by compiling that tag in a throwaway GOPATH.
This page is the record of that workflow. Scripts live in terp-core scripts/release/fresh-vm/.
What a pass actually proves
A pass means:
git cloneof tagvX.Y.Z(annotated tag commit, notfeat/…-devHEAD).- Git submodules
crates/zk-wasmd,crates/zk-wasmvm, andcrates/cosmwasmat the gitlinks on that tag. - Checksummed fetch of
ibc-hooks-v11.tar.gz(gitignored; not copied from a laptop). - Rebuild the alpine muslc builder image from
crates/zk-wasmvm/builders/Dockerfile.alpine, thencargolibwasmvm_muslc.{aarch64,x86_64}.a. Rebuilt.amust match the published muslc pin unlessFRESH_VM_ALLOW_MUSLC_DRIFT=1. GOPATH/GOMODCACHE/GOCACHEare a throwaway directory, not$HOME/go.- Linux ELFs:
make build-reproducible-amd64/arm64with Docker Buildx--no-cache(rebuilds the terpd image, then extracts the binary). - SHA-256 of those ELFs equals
https://s3.terp.network/releases/terp-core/<tag>/sha256sum.txt. - If two guests both rebuilt the same ELF name, those hashes also equal each other.
That is from-source muslc + terpd on a fresh guest, plus GOPROXY module zips. WASMVM_MUSLC_FETCH=1 skips the Rust rebuild and only links the published .a (weaker).
What a pass does not prove
| Input | What happens | Why it matters |
|---|---|---|
| Go modules (SDK, IAVL, IBC, …) | go build downloads module zips via GOPROXY into the empty cache | Fresh bytes for go.mod / go.sum. Not a rebuild of each upstream git tree. |
Docker Hub rust: / golang: parents | --no-cache --pull on our Dockerfiles. Parent tags still come from the registry. | Independent of the curator’s terp layer cache. |
| Hasher / BLAKE3 vendor | crates/cosmos/{iavl,store-v2} must not appear on a fresh clone. Published v6.1.0 / v6.2.0 do not replace store/v2. | Recurate of those tags proves the published ELF (live CMS SHA-256). It does not compile the gitignored hasher patch. |
| Upgrade behavior | Not run. | Cosmovisor halt, TSH, ict-rs, and gov info JSON are separate gates. This workflow only checks binary identity. |
make recurate-upgrade-binaries is a different tool: it rebuilds in a git worktree and compares ARTIFACT_LOCK. Fresh-VM compares S3. Do not mix them.
Two guests, one script
Firecracker and Wasmer are backends for the same guest.sh. They are not two compilers.
| Backend | What you set | What must be true of the machine |
|---|---|---|
firecracker | FIRECRACKER_SSH=user@microvm | Linux with git, docker, curl. Empty GOPATH is created in /tmp. The script does not boot Firecracker itself. |
wasmer | WASMER_SSH=user@linux | Same payload as Firecracker, different host. That is the redundant confirmation. |
wasmer CLI | WASMER_PACKAGE=… | WASIX. Public packages do not include Docker. Cannot run linux muslc recurate unless the package actually has docker/git/make. |
local | (default if no SSH) | Throwaway clone on the curator laptop. Weaker: Docker Desktop may be the same daemon used for daily work. --no-cache still applies. |
Two SSH hosts matching S3 and each other is the high-certainty path: two kernels, two Docker daemons, two empty GOPATHs, one checksum file.
wasmer run on a WASIX package is not that path.
How curators run it
From a terp-core checkout (or any machine that can SSH the guest). The guest fetches ibc-hooks itself; it does not need our laptop’s crates/ tree:
# one Linux guest
FIRECRACKER_SSH=root@fc TAG=v6.2.0 \
PLATFORMS=linux/amd64,linux/arm64 \
./scripts/release/fresh-vm/run.sh
# two independent Linux guests
FIRECRACKER_SSH=root@fc WASMER_SSH=root@wasmer-linux \
GUESTS=firecracker,wasmer TAG=v6.2.0 \
PLATFORMS=linux/amd64,linux/arm64 \
./scripts/release/fresh-vm/run.shOr TAG=v6.2.0 make verify-fresh-vm with those env vars set.
Per-tag extras are historical files: scripts/release/fresh-vm/releases/v6.1.0.sh, v6.2.0.sh, …. Copy forward for a new tag; do not edit a published tag’s file. Do not put guest logic in networks/upgrades/ or recurate_upgrade_binaries.sh.
Hashes from each guest: /tmp/terp-fresh-toolkit-<tag>/out/<guest>.sha256sum.txt.
How operators should read a recurate during an upgrade
- Confirm the Cosmovisor plan name (
v6.1,v6.2, …) and the binary tag (v6.1.0, …) in the proposal / upgrade guide. - Download
sha256sum.txtand the tarball fromhttps://s3.terp.network/releases/terp-core/<tag>/. sha256sum -c sha256sum.txt --ignore-missing.- Treat a published curator recurate as extra evidence that those checksums are the tag, not a laptop cache. If you want to repeat it, you need a Linux Docker host and the extras for that tag — not only
git clone && make buildon a dirty GOPATH.
Darwin/arm64 installer ELFs are a separate Darwin-host rebuild. Firecracker and Wasmer Linux guests skip Mach-O.