#!/usr/bin/env bash # Builds the reference modules (extensions/quantum-wasmq.md ยง8) for wasm32-unknown-unknown # and writes the modules of record, with what decided their bytes, into # wai/quantum-conformance/wasmq/modules/. # # build.sh build and write the modules of record and modules.json # build.sh --check build, and fail unless the build equals the modules of record # build.sh --sources build nothing; fail unless every source modules.json pins has # its digest (any host: python3 alone) # # rustc's wasm32 output depends on the host it runs on, so the modules of record are # built on x86_64 Linux, the CI image's host; `--check` is run there. Every other host # reads the committed modules, and modules.json pins the sources that made them. set -euo pipefail here=$(cd "$(dirname "$0")" && pwd) root=$(cd "$here/../../.." && pwd) out="$root/wai/quantum-conformance/wasmq/modules" check=0 mkdir -p "$out" [ "${1:-}" = "--check" ] && check=1 if [ "${1:-}" = "--sources" ]; then python3 -I - "$root" <<'PY' import hashlib, json, os, sys root = sys.argv[1] doc = json.load(open(os.path.join(root, "wai/quantum-conformance/wasmq/modules/modules.json"))) bad = [p for p, h in doc["sources_sha256"].items() if hashlib.sha256(open(os.path.join(root, p), "rb").read()).hexdigest() != h] for n, m in doc["modules"].items(): b = open(os.path.join(root, "wai/quantum-conformance/wasmq/modules", m["file"]), "rb").read() if hashlib.sha256(b).hexdigest() != m["sha256"]: bad.append(m["file"]) for p in bad: print(f"::error::{p} is not what the modules of record were built from: rebuild them with wai/wai-wasmq/modules/build.sh on x86_64 Linux") print(f"modules of record: {len(doc['sources_sha256'])} sources and {len(doc['modules'])} modules as pinned" if not bad else "") sys.exit(1 if bad else 0) PY exit $? fi cd "$here" export CARGO_TARGET_DIR="${CARGO_TARGET_DIR:-$here/target}" sysroot=$(rustc --print sysroot) commit=$(rustc -vV | sed -n 's/^commit-hash: //p') # The paths a build records: the same on every host. export RUSTFLAGS="-C target-cpu=lime1 -C link-arg=--max-memory=67108864 --remap-path-prefix=$root=/src --remap-path-prefix=${CARGO_HOME:-$HOME/.cargo}=/cargo --remap-path-prefix=$sysroot/lib/rustlib/src/rust=/rustc/$commit" cargo build --locked --release --target wasm32-unknown-unknown built="$CARGO_TARGET_DIR/wasm32-unknown-unknown/release" status=0 for name in qldpc_decoder atom_planner; do f="$built/wasmq_$name.wasm" if [ "$check" = 1 ]; then if cmp -s "$f" "$out/$name.wasm"; then echo "$name: the build equals the module of record" else echo "::error::$name: the build differs from the module of record ($(wc -c <"$f") bytes against $(wc -c <"$out/$name.wasm"))" status=1 fi else cp "$f" "$out/$name.wasm" fi done if [ "$check" = 0 ]; then python3 - "$root" "$(rustc -V)" <<'PY' import hashlib, json, sys, os root, rustc = sys.argv[1], sys.argv[2] def b3(p): # blake3 is not in the standard library; sha256 pins the sources, the crate pins the modules by blake3. return hashlib.sha256(open(os.path.join(root, p), 'rb').read()).hexdigest() sources = ["wai/wai-wasmq/modules/Cargo.toml", "wai/wai-wasmq/modules/Cargo.lock", "wai/wai-wasmq/modules/.cargo/config.toml", "wai/wai-wasmq/modules/qldpc-decoder/Cargo.toml", "wai/wai-wasmq/modules/qldpc-decoder/src/lib.rs", "wai/wai-wasmq/modules/atom-planner/Cargo.toml", "wai/wai-wasmq/modules/atom-planner/src/lib.rs", "wai/wai-quantum/src/quantum_qec.rs", "wai/wai-quantum/src/quantum_atom.rs", "wai/wai-quantum/src/quantum_ops.rs", "rust-toolchain.toml"] mods = {} for n in ["qldpc_decoder", "atom_planner"]: b = open(os.path.join(root, "wai/quantum-conformance/wasmq/modules", n + ".wasm"), 'rb').read() mods[n] = {"file": n + ".wasm", "bytes": len(b), "sha256": hashlib.sha256(b).hexdigest()} doc = {"built_with": rustc, "target": "wasm32-unknown-unknown", "host": "x86_64-unknown-linux-gnu", "modules": mods, "sources_sha256": {s: b3(s) for s in sources}} open(os.path.join(root, "wai/quantum-conformance/wasmq/modules/modules.json"), "w").write(json.dumps(doc, indent=2, sort_keys=True) + "\n") PY echo "wrote the modules of record and modules.json" fi exit $status