open-standards/wai/examples/verify-receipts/test/verify-receipts.test.sh
Transaction Science 02ee638902 wai/examples: encoder-ingest subscribes once the gateway publishes; tests take CARGO_TARGET_DIR
The relay refuses a subscription to a track nobody publishes yet
(DOES_NOT_EXIST): the example now calls first, or waits for the encoder, and
asks again until the gateway's tracks are there. The Rust examples' tests
find their binaries under CARGO_TARGET_DIR when it is set.

Co-Authored-By: Claude Opus 5.5 <[email protected]>
2026-10-26 22:58:39 -04:00

60 lines
2.7 KiB
Shell
Executable file

#!/usr/bin/env bash
# The verify-receipts example: `wai create` makes the project and `wai hello` writes an object
# and its receipts. Both verifiers, the Rust one on the repository's wai crate (the template's
# git dependency patched to this checkout) and the Python one, must accept them, and each must
# refuse them when one byte of the object, or of the group's signature, is changed.
#
# bash wai/examples/verify-receipts/test/verify-receipts.test.sh
# Needs wai on PATH, cargo and python3.
# No -e: each check records its own result, and the run goes on to the next.
set -uo pipefail
REPO=$(cd "$(dirname "$0")/../../../.." && pwd)
T=$(mktemp -d)
fails=0
check() { if [ "$2" = 0 ]; then echo "ok $1${3:+ ($3)}"; else echo "FAIL $1${3:+ ($3)}"; fails=$((fails + 1)); fi; }
wai create "$T/check" --template verify-receipts > /dev/null || { echo "FAIL wai create"; exit 1; }
cd "$T/check"
wai hello receipts > hello.log || { cat hello.log; echo "FAIL wai hello"; exit 1; }
# The template's git dependency, pointed at this checkout.
sed -i.bak "s#git = \"https://git.transaction.science/Transaction-Science/open-standards\"#path = \"$REPO/wai/wai-rs\"#" rust/Cargo.toml
grep -q "path = \"$REPO/wai/wai-rs\"" rust/Cargo.toml || { echo "FAIL the dependency was not pointed at the checkout"; exit 1; }
(cd rust && cargo build --release --quiet 2> ../build.log) || { cat build.log; echo "FAIL the Rust verifier builds"; exit 1; }
BIN="${CARGO_TARGET_DIR:-$PWD/rust/target}/release/verify-receipts"
rust() { "$BIN" receipts; }
py() { python3 -I python/verify_receipts.py receipts; }
for v in rust py; do
s=0; out=$($v) || s=$?
check "$v: accepts the receipts wai hello wrote" $s "$(echo "$out" | head -1)"
done
obj=$(ls receipts/*.wai)
cp "$obj" obj.bak
printf 'x' >> "$obj"
for v in rust py; do
s=0; out=$($v) || s=$?
[ "$s" = 1 ]; check "$v: refuses an object one byte longer" $? "$(echo "$out" | head -1)"
done
cp obj.bak "$obj"
g=$(ls receipts/rcpt/*.json)
cp "$g" g.bak
python3 - "$g" <<'PY'
import sys
p = sys.argv[1]
t = open(p).read()
i = t.index('"sig":"') + 7
open(p, "w").write(t[:i] + ("1" if t[i] == "0" else "0") + t[i + 1:])
PY
for v in rust py; do
s=0; out=$($v) || s=$?
[ "$s" = 1 ]; check "$v: refuses a group whose signature changed" $? "$(echo "$out" | head -1)"
done
cp g.bak "$g"
for v in rust py; do
s=0; out=$($v) || s=$?
check "$v: accepts them again once restored" $s
done
# The Python verifier's Ed25519 and BLAKE3 are the corpus verifiers' own, copied unchanged.
for f in _ed25519.py _blake3.py; do
cmp -s "$REPO/wai/examples/verify-receipts/python/$f" "$REPO/wai/claim-conformance/$f"; check "python/$f is claim-conformance/$f, unchanged" $?
done
echo "verify-receipts: $([ $fails = 0 ] && echo all checks held || echo "$fails check(s) failed")"
exit $fails