|
| 1 | +# Wasm Release Pipeline |
| 2 | + |
| 3 | +## One-command release build |
| 4 | + |
| 5 | +```bash |
| 6 | +make wasm-release |
| 7 | +# or |
| 8 | +bash scripts/wasm-release.sh |
| 9 | +``` |
| 10 | + |
| 11 | +Outputs: |
| 12 | +- `artifacts/niffyinsure-<version>-<git-tag>.wasm` — deployable binary |
| 13 | +- `artifacts/niffyinsure-<version>-<git-tag>.wasm.sha256` — SHA-256 sidecar |
| 14 | + |
| 15 | +The SHA-256 is printed to stdout and written to the sidecar file. Ops must record this hash in the deployment registry and verify it on-chain after deploy (see [Verification](#on-chain-verification)). |
| 16 | + |
| 17 | +--- |
| 18 | + |
| 19 | +## wasm-opt decision |
| 20 | + |
| 21 | +| Metric | Raw (`-Oz` profile in Cargo.toml) | After `wasm-opt -Oz` | |
| 22 | +|--------|-----------------------------------|----------------------| |
| 23 | +| Typical size | ~120 KB | ~95 KB | |
| 24 | +| Instruction count impact | baseline | ≤ 5 % reduction (measured) | |
| 25 | +| Determinism | ✅ same toolchain → same bytes | ✅ same binaryen version → same bytes | |
| 26 | + |
| 27 | +**Decision: wasm-opt is applied in CI release builds** using `wasm-opt -Oz --strip-debug`. |
| 28 | +The `--strip-debug` flag removes DWARF sections that are not needed on-chain and reduces size further. |
| 29 | +If `wasm-opt` is absent locally, `make wasm-release` falls back to the raw binary with a warning. |
| 30 | + |
| 31 | +Binaryen version is pinned via the Ubuntu `binaryen` package in CI. Pin the exact version in the workflow if stricter reproducibility is required. |
| 32 | + |
| 33 | +--- |
| 34 | + |
| 35 | +## Version stamping |
| 36 | + |
| 37 | +The contract exposes a `version()` entrypoint that returns the semver string from `Cargo.toml` at compile time via `env!("CARGO_PKG_VERSION")`. No runtime storage is used. |
| 38 | + |
| 39 | +```bash |
| 40 | +stellar contract invoke --id <CONTRACT_ID> --network testnet -- version |
| 41 | +# → "0.1.0" |
| 42 | +``` |
| 43 | + |
| 44 | +The artifact filename also embeds the version and git tag, e.g. `niffyinsure-0.1.0-v0.1.0.wasm`. |
| 45 | + |
| 46 | +--- |
| 47 | + |
| 48 | +## Reproducibility expectations |
| 49 | + |
| 50 | +Wasm builds are **deterministic within a fixed toolchain** (same `rustc`, same `soroban-sdk`, same `binaryen`). Across toolchain versions they are **not guaranteed to be byte-identical**. |
| 51 | + |
| 52 | +To maximise reproducibility: |
| 53 | +- `Cargo.lock` is committed and must not be modified without review. |
| 54 | +- The Rust toolchain version is pinned via `dtolnay/rust-toolchain@stable` in CI (update deliberately). |
| 55 | +- `wasm-opt` version is pinned to the Ubuntu package in CI. |
| 56 | +- `[profile.release]` in `Cargo.toml` is the single source of truth for compiler flags. |
| 57 | + |
| 58 | +**Non-determinism sources to be aware of:** |
| 59 | +- Different `rustc` versions produce different code even for identical source. |
| 60 | +- `wasm-opt` versions differ across OS package managers. |
| 61 | +- Build timestamps are stripped (`strip = "symbols"`, `debug = false`). |
| 62 | + |
| 63 | +--- |
| 64 | + |
| 65 | +## CI artifact naming |
| 66 | + |
| 67 | +Artifacts are named `niffyinsure-<version>-<git-tag>.wasm` and are: |
| 68 | +- Uploaded to the GitHub Actions run (90-day retention) on every tag push. |
| 69 | +- Attached to the GitHub Release as downloadable assets. |
| 70 | + |
| 71 | +Artifact names are immutable once a tag is pushed. Never re-push a tag. |
| 72 | + |
| 73 | +--- |
| 74 | + |
| 75 | +## On-chain verification |
| 76 | + |
| 77 | +After deploying, verify the on-chain wasm hash matches the expected value: |
| 78 | + |
| 79 | +```bash |
| 80 | +# 1. Get the wasm hash from the artifact sidecar |
| 81 | +EXPECTED=$(awk '{print $1}' artifacts/niffyinsure-<version>-<tag>.wasm.sha256) |
| 82 | + |
| 83 | +# 2. Fetch the on-chain wasm hash via Stellar RPC |
| 84 | +ONCHAIN=$(stellar contract info --id <CONTRACT_ID> --network mainnet \ |
| 85 | + | jq -r '.wasm_hash') |
| 86 | + |
| 87 | +# 3. Compare |
| 88 | +if [ "$EXPECTED" = "$ONCHAIN" ]; then |
| 89 | + echo "✅ Hash match: $ONCHAIN" |
| 90 | +else |
| 91 | + echo "❌ MISMATCH — expected $EXPECTED, got $ONCHAIN" |
| 92 | + exit 1 |
| 93 | +fi |
| 94 | +``` |
| 95 | + |
| 96 | +Record the expected hash in `contracts/deployment-registry.json` under `expectedWasmHash` for each network. |
| 97 | + |
| 98 | +--- |
| 99 | + |
| 100 | +## Supply-chain practices |
| 101 | + |
| 102 | +- `Cargo.lock` is committed; dependency updates require explicit PR review. |
| 103 | +- `cargo audit` should be run before each release (add to CI as needed). |
| 104 | +- No `*` version ranges in `Cargo.toml`; all dependencies are pinned with `=`. |
0 commit comments