name: wai-quantum on every processor # The crate promises the same bits on every processor. Native legs run elsewhere # (x86_64 Linux, aarch64 macOS, the arm64 Linux VM, wasm32, wasip2); this # workflow runs the crate's byte-pinning tests under user-mode QEMU on the # instruction sets no runner has, the big-endian ones among them: # # bit_identity 23 digests across every numeric layer, taken natively and # confirmed under wasip2; # frame_reference the noisy-Clifford fixtures written by an independent tool; # the library the modules that pin exact bytes: the core and its corpora, # the fabric and its certificates, the strict JSON reader, # receipts, energy labels and the bill of materials. # # These are emulator results: they prove what each target's binary computes # under QEMU, not what that silicon does. i686 is the exception: it runs # directly on the x86_64 host in 32-bit mode, so that leg is silicon. # # Each leg's job container is that target's cross image (linker, sysroot and # QEMU, the runner preset in its environment), pinned by digest, capped at # 6 GiB: an uncapped emulated run once took the 15 GiB host down. The job # installs the pinned Rust into the runner's persistent cache, builds in a # target directory of its own there (a build script compiled in one image fails # in another with an older glibc), and holds a host-wide lock, so one leg runs # at a time across every run of this workflow. concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: true on: pull_request: paths: - 'wai/wai-quantum/**' - 'rust-toolchain.toml' - '.github/workflows/wai-quantum-processors.yml' schedule: - cron: '48 6 * * *' jobs: emulated: name: emulated ยท ${{ matrix.target }} runs-on: linux timeout-minutes: 120 container: image: ${{ matrix.image }} options: --memory=6g --memory-swap=6g ${{ matrix.options }} strategy: fail-fast: false max-parallel: 1 matrix: include: - target: s390x-unknown-linux-gnu image: ghcr.io/cross-rs/s390x-unknown-linux-gnu@sha256:0d8edc92c39158abe211fddfc9617bf5b7865c2ae0f58873f9cf0c58bb315271 how: emulated, qemu-user - target: sparc64-unknown-linux-gnu image: ghcr.io/cross-rs/sparc64-unknown-linux-gnu@sha256:2d04e507ee8bbb1ba61d483d22cf5839a0f138678f71facb40a08a9dffecf316 how: emulated, qemu-user - target: powerpc64-unknown-linux-gnu image: ghcr.io/cross-rs/powerpc64-unknown-linux-gnu@sha256:db02ecb2429912a6e939cc3d5cfe00aa20d7423ff484980f1fbfee4a3f2683cf how: emulated, qemu-user - target: powerpc64le-unknown-linux-gnu image: ghcr.io/cross-rs/powerpc64le-unknown-linux-gnu@sha256:de5114adcd786f6a41eb07379459aaae94de73670303e202ea3603d250c19091 how: emulated, qemu-user - target: riscv64gc-unknown-linux-gnu image: ghcr.io/cross-rs/riscv64gc-unknown-linux-gnu@sha256:67ee97dd4719390d299edfcf39f226360ccfb1539e08b078ec187d4848415794 how: emulated, qemu-user # QEMU 5.1's 32-bit ARM guest grows the emulator's own memory with the # guest's thread count: with all 20 host CPUs, bit_identity's threaded # state-vector run took qemu-arm past 6 GiB (a 32-bit guest addresses at # most 4 GiB, so the excess is the emulator's). Four CPUs keep it under # 1 GiB and still take the threaded paths. - target: armv7-unknown-linux-gnueabihf image: ghcr.io/cross-rs/armv7-unknown-linux-gnueabihf@sha256:4a08bebb60f08d52c1885b643a768f163c7318c05f91cf119f6c02855ea52699 options: --cpuset-cpus=0-3 how: emulated, qemu-user # Runs directly on the x86_64 host in 32-bit mode. - target: i686-unknown-linux-gnu image: ghcr.io/cross-rs/i686-unknown-linux-gnu@sha256:2647400f884dd399a3ce6f6d918fec0776d43e73f471f52e310cbe664ac1671f how: silicon, x86_64 host in 32-bit mode - target: aarch64-unknown-linux-gnu image: ghcr.io/cross-rs/aarch64-unknown-linux-gnu@sha256:7f8308a8734d9fcd2ebbe9a3e4bdea74af293f0799d80c3cc341e340cda49a4c how: emulated, qemu-user # cross 0.2.5 has no LoongArch image; this is cross's development image. - target: loongarch64-unknown-linux-gnu image: ghcr.io/cross-rs/loongarch64-unknown-linux-gnu@sha256:8968bd3b2c3b7b6d73c48e10faa605e14b40ce0080579a06402ea9fdfbc2a5c0 how: emulated, qemu-user steps: - name: Fetch the source shell: bash run: | set -euo pipefail want="${{ github.event.pull_request.head.sha || github.sha }}" # The commit itself, not the ref: a later commit on the ref that this # workflow's paths do not match would otherwise be tested instead. The # archive carries its commit id, checked before anything is built. rm -rf src src.tar.gz src.tar && mkdir src curl -sSf -o src.tar.gz "http://100.64.224.0:3400/Transaction-Science/open-standards/archive/$want.tar.gz" # Decompressed to a file, not a pipe: get-tar-commit-id stops reading at the # header, and the writer's broken pipe would fail the step under pipefail. gzip -dc src.tar.gz > src.tar got="$(git get-tar-commit-id < src.tar)" [ "$got" = "$want" ] || { echo "::error::the archive is of $got, not $want"; exit 1; } tar -xf src.tar -C src --strip-components=1 rm src.tar.gz src.tar - name: The byte-pinning tests shell: bash working-directory: src/wai/wai-quantum run: | set -euo pipefail t="${{ matrix.target }}" cache=/ci-cache/wai-quantum-processors mkdir -p "$cache" # One leg at a time on this host, across every run of this workflow: the # emulated tests are heavy, and the toolchain cache is shared. exec 9>"$cache/.lock" flock 9 export RUSTUP_HOME="$cache/rustup" CARGO_HOME="$cache/cargo" export PATH="$CARGO_HOME/bin:$PATH" if ! command -v rustup >/dev/null; then curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --no-modify-path --profile minimal --default-toolchain none fi rustup toolchain install rustup target add "$t" export CARGO_TARGET_DIR="$cache/target/$t" logs="$(mktemp -d)" run() { local name="$1"; shift timeout 2700 cargo test --locked --release -j 6 --target "$t" --features full "$@" 2>&1 | tee "$logs/$name.log" } run bit_identity --test bit_identity grep -qE '^test result: ok\. 23 passed; 0 failed' "$logs/bit_identity.log" || { echo "::error::$t: the 23 bit-identity digests did not all pass"; exit 1; } run frame --test frame_reference grep -qE '^test result: ok\. 2 passed; 0 failed' "$logs/frame.log" || { echo "::error::$t: the fixtures did not pass"; exit 1; } run lib --lib -- quantum:: quantum_fabric:: ijson:: quantum_receipt quantum_energy quantum_qbom merkle grep -qE '^test result: ok\. [1-9][0-9]+ passed; 0 failed' "$logs/lib.log" || { echo "::error::$t: the byte-pinning library tests did not pass"; exit 1; } echo "processor: $t (${{ matrix.how }}) bit_identity 23/23, fixtures 2/2, $(grep -E '^test result' "$logs/lib.log" | tail -1)"