/* The reach conformance workloads, in ECMAScript 5 so that one file runs on every engine * the proxies stand for. * * WaiReachWorkloads.forProfile(profile) -> [name, ...] * WaiReachWorkloads.run(W, ctx, names) -> { name: { ok, out, err, ms } } * * W is the wai-web API a rung loaded (the shipped module or the reach glue: the same * surface). ctx reads the repository's corpora: ctx.bytes(rel), ctx.text(rel), * ctx.json(rel), ctx.dirs(rel) (sub-folders, sorted), ctx.sha256(u8) (hex, computed by * the host, not by the build under test), ctx.now(). * * Every workload checks its result against an independent reference: a corpus's own * hashes, a sidecar's SHA-256, the signed receipt's fields, or the registry. Its `out` is * a canonical summary that the runner compares byte for byte with the shipped build's. * 64-bit values are turned into strings before they enter `out`, so a BigInt and a * Number of the same value compare equal. */ (function (root) { 'use strict'; var PROFILE_WORKLOADS = { receipt: ['hashes', 'envelope', 'receipt_verify'], verify: ['menu', 'stage_ids', 'multi', 'output_tree'], verify_decode: ['int_payloads', 'int_json', 'int_synth', 'staged_sink'], full: ['i64_boundary'] }; var INCLUDES = { receipt: [], verify: ['receipt'], verify_decode: ['verify'], full: ['verify_decode'] }; function forProfile(p) { if (!PROFILE_WORKLOADS[p]) throw new Error('unknown profile ' + p); var out = [], inc = INCLUDES[p]; for (var i = 0; i < inc.length; i++) out = out.concat(forProfile(inc[i])); return out.concat(PROFILE_WORKLOADS[p]); } function S(v) { return v === null || v === undefined ? String(v) : String(v); } function keys(o) { var k, a = []; for (k in o) if (Object.prototype.hasOwnProperty.call(o, k)) a.push(k); return a; } function canon(v, depth) { depth = depth || 0; if (depth > 12) return ''; if (v === undefined) return ''; if (v === null) return null; var t = typeof v; if (t === 'bigint') return 'BIGINT:' + String(v); if (t === 'number' || t === 'boolean' || t === 'string') return v; if (typeof Map !== 'undefined' && v instanceof Map) { var es = []; v.forEach(function (val, key) { es.push([canon(key, depth + 1), canon(val, depth + 1)]); }); return { '': es }; } if (typeof v.length === 'number' && typeof v.BYTES_PER_ELEMENT === 'number') return '<' + v.length + ' x ' + v.BYTES_PER_ELEMENT + ' bytes>'; if (Object.prototype.toString.call(v) === '[object Array]') { var a = []; for (var i = 0; i < v.length; i++) a.push(canon(v[i], depth + 1)); return a; } var o = {}, ks = keys(v).sort(); for (var j = 0; j < ks.length; j++) o[ks[j]] = canon(v[ks[j]], depth + 1); return o; } function same(a, b) { return JSON.stringify(a) === JSON.stringify(b); } function errText(e) { return String(e && e.message !== undefined ? e.message : e); } function errCode(e) { return errText(e).split(':')[0]; } function concat(list) { var n = 0, i, o = 0; for (i = 0; i < list.length; i++) n += list[i].length; var u = new Uint8Array(n); for (i = 0; i < list.length; i++) { u.set(list[i], o); o += list[i].length; } return u; } function hexToBytes(h) { var u = new Uint8Array(h.length / 2); for (var i = 0; i < u.length; i++) u[i] = parseInt(h.substr(2 * i, 2), 16); return u; } function ascii(s) { var u = new Uint8Array(s.length); for (var i = 0; i < s.length; i++) u[i] = s.charCodeAt(i) & 0xff; return u; } function u8view(ta) { return new Uint8Array(ta.buffer, ta.byteOffset, ta.byteLength); } function copy(u) { var c = new Uint8Array(u.length); c.set(u); return c; } var PROV = 'wai-web/reach/test/vectors/provenance/'; var V = 'wai-rs/tests/vectors/'; var WORK = {}; // receipt ------------------------------------------------------------------------- WORK.hashes = function (W, ctx) { var files = [PROV + 'captured.jpeg.wai', V + 'int_video/int_video_bitstream.wiv1', V + 'int_audio/audio_model.bin']; var out = {}, ok = true; for (var i = 0; i < files.length; i++) { var b = ctx.bytes(files[i]); var r = { sha256: W.sha256Hex(b), blake3: W.blake3Hex(b), fnv1a: W.fnv1aHex(b) }; if (r.sha256 !== ctx.sha256(b)) ok = false; out[files[i]] = r; } return { ok: ok, out: out }; }; WORK.envelope = function (W, ctx) { var cap = ctx.bytes(PROV + 'captured.jpeg.wai'), receipt = ctx.json(PROV + 'captured.receipt.json'); var e = W.parse(cap); var out = { capability: S(e.capability), kind: S(e.kind), media: S(e.media), intent: S(e.intent), fallback: canon(e.fallback), payload_len: S(e.payload_len), version: S(W.detectVersion(cap)) }; e.free(); var refused; try { W.parse(ascii('not an envelope')); refused = 'parsed'; } catch (x) { refused = errCode(x); } out.garbage = refused; return { ok: out.capability === receipt.capability && out.media === receipt.media && out.version === '1' && refused !== 'parsed', out: out }; }; WORK.receipt_verify = function (W, ctx) { var cap = ctx.bytes(PROV + 'captured.jpeg.wai'), json = ctx.text(PROV + 'captured.receipt.json'), r = JSON.parse(json); var p = new W.AssetProvenance(cap, json); var out = { content_ok: p.content_ok(), signature_ok: p.signature_ok(), capability: p.capability(), media: p.media(), asset: p.asset_hash_hex(), computed: p.computed_hash_hex(), receipt_hash: p.receipt_hash_hex(), signer: p.signer_id(), steps: p.step_count(), joules_micro: S(p.total_joules_micro()), payload_sha256: ctx.sha256(p.payload()) }; p.free(); var t = copy(cap); t[Math.floor(t.length * 0.7)] ^= 0x40; try { var q = new W.AssetProvenance(t, json); out.tampered = { content_ok: q.content_ok(), signature_ok: q.signature_ok() }; q.free(); } catch (x) { out.tampered = { refused: errCode(x) }; } var forged = JSON.parse(json); forged.total_joules_micro = forged.total_joules_micro + 1; var f = new W.AssetProvenance(cap, JSON.stringify(forged)); out.forged = { content_ok: f.content_ok(), signature_ok: f.signature_ok() }; f.free(); var ok = out.content_ok === true && out.signature_ok === true && out.asset === r.asset_hash && out.computed === r.asset_hash && out.receipt_hash === r.receipt_hash && out.joules_micro === String(r.total_joules_micro) && out.steps === r.steps.length && out.signer === r.signer_id && (out.tampered.refused !== undefined || out.tampered.content_ok === false) && out.forged.signature_ok === false; return { ok: ok, out: out }; }; // verify -------------------------------------------------------------------------- WORK.menu = function (W, ctx) { var reg = ctx.json('registry/capabilities.json').capabilities, byName = {}, i; for (i = 0; i < reg.length; i++) byName[reg[i].capability] = reg[i]; var menu = Array.prototype.slice.call(W.known_capabilities()), bad = []; for (i = 0; i < menu.length; i++) { var c = menu[i], r = byName[c]; if (!r || (r.kind !== 'payload' && r.kind !== 'companion') || r.status !== 'registered' || W.isCandidate(c) || !W.isRegistered(c)) bad.push(c); } var disagree = []; for (i = 0; i < reg.length; i++) { if ((reg[i].kind === 'payload' || reg[i].kind === 'companion') && W.isCandidate(reg[i].capability) !== (reg[i].status === 'candidate')) disagree.push(reg[i].capability); } return { ok: menu.length > 0 && bad.length === 0 && disagree.length === 0, out: { menu: menu, bad: bad, disagree: disagree } }; }; WORK.stage_ids = function (W, ctx) { var names = ctx.dirs('staged-conformance/cases'), n = 0, bad = [], info = {}; for (var i = 0; i < names.length; i++) { var dir = 'staged-conformance/cases/' + names[i] + '/', c = ctx.json(dir + 'case.json'); for (var j = 0; j < c.bases.length; j++) { n++; if (W.stageContentHash(ctx.bytes(dir + c.bases[j].file)) !== c.bases[j].object) bad.push(names[i] + '/' + c.bases[j].file); } if (i % 8 === 0 && c.files.length) info[names[i] + '/' + c.files[0].file] = canon(W.stageLayerInfo(ctx.bytes(dir + c.files[0].file))); } return { ok: n > 0 && bad.length === 0, out: { bases: n, bad: bad, layer_info: info } }; }; WORK.multi = function (W, ctx) { var idx = ctx.json('staged-conformance/wai2/index.json'), out = {}, parsed = 0; for (var i = 0; i < idx.files.length; i++) { var f = idx.files[i].file, b = ctx.bytes('staged-conformance/wai2/' + f), r; try { var m = W.parseMulti(b); r = { n: m.n_renditions, media: S(m.media), intent: S(m.intent), meta: canon(m.renditionsMeta()), pins: canon(m.checkPins()) }; m.free(); parsed++; } catch (x) { r = { refused: errText(x) }; } out[f] = r; } return { ok: parsed > 0, out: out }; }; WORK.output_tree = function (W, ctx) { var g = ctx.json('staged-measure-conformance/goldens.json').fixtures, out = {}, ok = g.length > 0; for (var i = 0; i < g.length; i++) { var outputs = []; for (var j = 0; j < g[i].presentations.length; j++) { var p = g[i].presentations[j]; outputs.push({ unit: p.unit, layers: p.layers, decoder: p.decoder, out_digest: p.out_sha256 }); } var root = W.outputRoot(JSON.stringify(outputs)); if (root !== g[i].output_root) ok = false; out[g[i].title] = root; } return { ok: ok, out: out }; }; // verify_decode -------------------------------------------------------------------- function clipDigest(v, ctx) { var n = v.width * v.height * 3, rgb = v.rgb, ds = []; for (var f = 0; f < v.nFrames; f++) { var one = v.frame(f); if (one.length !== n) throw new Error('frame ' + f + ' has ' + one.length + ' bytes'); for (var k = 0; k < n; k++) if (one[k] !== rgb[f * n + k]) throw new Error('frame ' + f + ' differs from rgb'); ds.push(hexToBytes(ctx.sha256(one))); } return ctx.sha256(concat(ds)); } WORK.int_payloads = function (W, ctx) { var side = function (rel, key) { return ctx.json(V + rel)[key]; }; var g = ctx.bytes(V + 'int_hyper/tiny_g_s.bin'), h = ctx.bytes(V + 'int_hyper/tiny_h_s.bin'), e = ctx.bytes(V + 'int_hyper/tiny_entropy.json'); var checks = [ ['int_video', function () { var v = W.decodeWiv1('wai.video.int_motion', ctx.bytes(V + 'int_video/int_video_bitstream.wiv1')); var d = clipDigest(v, ctx); v.free(); return d; }, side('int_video/sha256.json', 'int_video').clip_sha256], ['video_real', function () { var v = W.decodeWiv1('wai.video.int_motion', ctx.bytes(V + 'int_video/video_real_bitstream.wiv1')); var d = clipDigest(v, ctx); v.free(); return d; }, side('int_video/sha256.json', 'video_real').clip_sha256], ['video_nk', function () { var v = W.decodeWiv1('wai.video.int_hyper', ctx.bytes(V + 'int_video/video_nk_bitstream.wiv1'), g, h, e); var d = clipDigest(v, ctx); v.free(); return d; }, side('int_video/sha256.json', 'video_nk').clip_sha256], ['tiny', function () { var im = W.decodeWih1(ctx.bytes(V + 'int_hyper/tiny_bitstream.wih1'), g, h, e); var d = ctx.sha256(im.rgb); im.free(); return d; }, side('int_hyper/sha256.json', 'tiny').sha256], ['audio', function () { var a = W.decodeWia1(ctx.bytes(V + 'int_audio/audio_bitstream.wia1'), ctx.bytes(V + 'int_audio/audio_model.bin')); if (a.sampleRate !== 16000) return 'sample rate ' + a.sampleRate; var d = ctx.sha256(u8view(a.pcm)); a.free(); return d; }, side('int_audio/sha256.json', 'audio').sha256], ['splat', function () { var s = W.decodeWis1(ctx.bytes(V + 'int_splat/splat.wis1'), ctx.bytes(V + 'int_splat/splat_gs.bin')); if (s.ranges.length !== 2 * s.nAttr || s.nGaussians !== 1024) return 'ranges or Gaussian count'; var d = ctx.sha256(u8view(s.attr)); s.free(); return d; }, side('int_splat/sha256.json', 'splat').sha256], ['json_refused', function () { try { W.decodeWiv1('wai.video.int_motion', ctx.bytes(V + 'int_video/int_video_bitstream.json')); return 'decoded'; } catch (x) { return errCode(x); } }, 'bad_magic'] ]; var out = {}, ok = true; for (var i = 0; i < checks.length; i++) { var got = checks[i][1](); out[checks[i][0]] = got; if (got !== checks[i][2]) ok = false; } return { ok: ok, out: out }; }; WORK.int_json = function (W, ctx) { var v = W.decodeIntVideo(ctx.bytes(V + 'int_video/int_video_bitstream.json')); var vd = clipDigest(v, ctx); v.free(); var a = W.decodeIntAudio(ctx.bytes(V + 'int_audio/audio_model.bin'), ctx.bytes(V + 'int_audio/audio_bitstream.json')); var conf = ctx.json(V + 'int_audio/audio.json'); var out = { video: vd, audio_samples: a.nSamples, audio_fnv1a: W.fnv1aHex(u8view(a.pcm)), audio_sha256: ctx.sha256(u8view(a.pcm)) }; a.free(); var ok = vd === ctx.json(V + 'int_video/sha256.json').int_video.clip_sha256 && out.audio_samples === conf.n_samples && out.audio_fnv1a === conf.pcm_fnv1a; return { ok: ok, out: out }; }; WORK.int_synth = function (W, ctx) { var base = 'neural-conformance/', expected = ctx.json(base + 'expected_hashes.json'), names = ['gradient', 'bloom', 'facade', 'photo']; var dom = ascii('wai:int-synth-rgb'), out = {}, ok = true; for (var i = 0; i < names.length; i++) { var img = W.decodeIntSynth(ctx.bytes(base + 'vectors/' + names[i] + '/latent.bin'), ctx.bytes(base + 'vectors/' + names[i] + '/int_synth.json')); var rgb = img.rgb, buf = new Uint8Array(dom.length + 1 + rgb.length); buf.set(dom, 0); buf[dom.length] = 1; buf.set(rgb, dom.length + 1); var got = W.blake3Hex(buf), want = expected[names[i]]; out[names[i]] = { w: img.width, h: img.height, rgb_hash: got }; if (got !== want.rgb_hash || img.width !== want.width || img.height !== want.height || rgb.length !== want.width * want.height * 3) ok = false; img.free(); } return { ok: ok, out: out }; }; // The staged-delivery corpus replayed through StageSink (the replay of // demo/verify_staged_wasm.mjs; its guards and fuzz run there, on the full builds). WORK.staged_sink = function (W, ctx) { var LIMIT = { output_bytes: 64 << 20, symbols: 64 << 20, working_bytes: 256 << 20 }; var names = ctx.dirs('staged-conformance/cases'), fails = [], replayed = 0, stageHashes = 0, digest = []; function fail(m) { if (fails.length < 12) fails.push(m); else if (fails.length === 12) fails.push('...'); } function modelSet(set) { var ks = keys(set || {}); if (!ks.length) return undefined; var m = new Map(); for (var i = 0; i < ks.length; i++) m.set(ks[i], ctx.bytes(set[ks[i]])); return m; } function withoutClaimed(o) { var r = {}, ks = keys(o); for (var i = 0; i < ks.length; i++) if (ks[i] !== 'claimed') r[ks[i]] = o[ks[i]]; return r; } for (var ci = 0; ci < names.length; ci++) { var name = names[ci], dir = 'staged-conformance/cases/' + name + '/', c = ctx.json(dir + 'case.json'); var bases = [], okCase = true, b, i; for (i = 0; i < c.bases.length; i++) { b = c.bases[i]; var env = ctx.bytes(dir + b.file), stage0 = ctx.bytes(dir + b.stage0), elem = b.units[0].elem, shapeList = [], base, k; for (k = 0; k < b.units.length; k++) { if (b.units[k].elem !== elem) { fail(name + ': mixed element types'); okCase = false; } shapeList = shapeList.concat(b.units[k].shape); } var shapes = new Uint32Array(shapeList.length); for (k = 0; k < shapeList.length; k++) shapes[k] = shapeList[k]; var make = (function (b, env, stage0, elem, shapes) { return function () { var x = b.decode.kind === 'int' ? W.StageBase.decode(env, modelSet(b.decode.set), b.decoded_via, LIMIT) : W.StageBase.fromStage0(env, b.decoded_via, b.tier, shapes, elem, stage0); x.attested = b.attested; x.setFirstUnit(b.first_unit); return x; }; })(b, env, stage0, elem, shapes); try { base = make(); } catch (x) { fail(name + ': ' + b.file + ': ' + errText(x)); okCase = false; continue; } if (b.decode.kind === 'int') { if (ctx.sha256(base.stage0()) !== b.stage0_sha256) { fail(name + ': the decode of ' + b.file + ' is not ' + b.stage0); okCase = false; } if (base.tier !== b.tier || base.viaFallback !== b.via_fallback || base.capability !== b.decoded_via) { fail(name + ': base facts'); okCase = false; } } else if (!base.claimed || base.viaFallback !== b.via_fallback || base.tier !== b.tier) { fail(name + ': claimed base facts'); okCase = false; } bases.push({ base: base, hash: base.contentHash, claimed: base.claimed, remake: make, spent: false }); } if (!okCase) continue; var files = {}; for (i = 0; i < c.files.length; i++) files[c.files[i].file] = ctx.bytes(dir + c.files[i].file); var sink = new W.StageSink(c.config), reports = [], s, got; for (i = 0; i < c.steps.length; i++) { s = c.steps[i]; if (s.op === 'offer') { try { got = sink.offer(files[s.file], s.at_ms, s.evidence); } catch (x) { got = { error: errCode(x) }; } } else if (s.op === 'base') { var bb = bases[s.index]; if (bb.spent) bb.base = bb.remake(); got = sink.addBase(bb.base); bb.spent = true; } else if (s.op === 'expire') got = sink.expire(s.at_ms); else if (s.op === 'remove') { got = sink.removeBase(bases[s.index].hash); if (got === undefined || got === null) got = []; } else if (s.op === 'attest') { sink.markAttested(bases[s.index].hash); got = []; } else { fail(name + ': unknown op ' + s.op); got = null; } if (Object.prototype.toString.call(got) === '[object Array]') { var un = []; for (var r = 0; r < got.length; r++) { if (got[r].claimed !== undefined && got[r].claimed !== true) fail(name + ': claimed is ' + got[r].claimed); un.push(withoutClaimed(got[r])); } got = un; } reports.push(got); } if (reports.length !== c.expect.reports.length) fail(name + ': ' + reports.length + ' steps'); for (i = 0; i < c.expect.reports.length; i++) { if (!same(reports[i], c.expect.reports[i])) fail(name + ': step ' + i + ' (' + c.steps[i].op + ') reports ' + JSON.stringify(reports[i]).slice(0, 120)); } for (i = 0; i < c.expect.bases.length; i++) { var want = c.expect.bases[i], h = bases[i].hash, raw = sink.units(h), fin = null; if (raw !== null) { fin = withoutClaimed(raw); var us = []; for (var u = 0; u < raw.units.length; u++) us.push(withoutClaimed(raw.units[u])); fin.units = us; } if (!same(fin, want)) { fail(name + ': base ' + i + ' final units differ'); continue; } if (fin === null) continue; for (var kk = 0; kk < fin.units.length; kk++) { var unit = fin.units[kk], sh = sink.unitSha256(h, kk); if ((sh ? sh.sha256 : null) !== unit.stage_sha256) fail(name + ': base ' + i + ' unit ' + kk + ': unitSha256'); if (unit.stage_sha256 !== null) { stageHashes++; var buf; try { buf = sink.unitBytes(h, kk); } catch (x) { buf = u8view(sink.unitPcm(h, kk)); } if (ctx.sha256(buf) !== unit.stage_sha256) fail(name + ': base ' + i + ' unit ' + kk + ': the output does not hash to its stage hash'); } } var clip = sink.clipSha256(h); if ((clip ? clip.sha256 : null) !== want.clip_sha256) fail(name + ': base ' + i + ': clipSha256'); } digest.push(JSON.stringify(reports)); sink.free(); for (i = 0; i < bases.length; i++) if (!bases[i].spent) bases[i].base.free(); replayed++; } return { ok: replayed === names.length && replayed > 0 && fails.length === 0, out: { cases: names.length, replayed: replayed, stage_hashes: stageHashes, fails: fails, reports_sha256: ctx.sha256(ascii(digest.join('\n'))) } }; }; // full ------------------------------------------------------------------------------ // The 64-bit boundary: i64 parameters and results through the glue, with values on // both sides of 2^32. WORK.i64_boundary = function (W, ctx) { var I64 = function (n) { return typeof root.BigInt === 'function' ? root.BigInt(n) : n; }; var seed = new Uint8Array(32), node = new Uint8Array(16), i; for (i = 0; i < 32; i++) seed[i] = 0x2a; for (i = 0; i < 16; i++) node[i] = i + 1; var actor = new W.Actor(seed); var op1 = actor.sign_truss_impulse(I64(7), node, 0.25, -0.5, 1.0); actor.observe_lamport(I64(100)); var op2 = actor.sign_truss_impulse(I64(9), node, 0.25, -0.5, 1.0); actor.observe_lamport(I64(5000000000)); var op3 = actor.sign_truss_impulse(I64(4294967297), node, 0.25, -0.5, 1.0); // 2^32 + 2^31: a low half with its top bit set, in both directions. actor.observe_lamport(I64(6442450944)); var op4 = actor.sign_truss_impulse(I64(6442450944), node, 0.25, -0.5, 1.0); var out = { pub: actor.pubkey_hex(), op1: W.fnv1aHex(op1), lamport1: S(W.op_lamport(op1)), op2: W.fnv1aHex(op2), lamport2: S(W.op_lamport(op2)), op3: W.fnv1aHex(op3), lamport3: S(W.op_lamport(op3)), op4: W.fnv1aHex(op4), lamport4: S(W.op_lamport(op4)), quantize: S(W.quantizeScale(0.5, 16)), // i64 results returned directly (op_lamport returns through memory): a low half with its // top bit set, with a zero and a non-zero high half. quantize32_low: S(W.quantizeScale(0.75, 32)), quantize32_high: S(W.quantizeScale(1.5, 32)), session: W.worldSessionHash('0707070707070707070707070707070707070707070707070707070707070707', I64(0), 64, 64, 24, '2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a', ascii('[{"lamport":1,"tick":1,"dx":1,"dy":0,"buttons":0},{"lamport":2,"tick":2,"dx":0,"dy":1,"buttons":0}]')) }; actor.free(); var ok = out.lamport1 === '1' && out.lamport2 === '101' && out.lamport3 === '5000000001' && out.lamport4 === '6442450945' && out.quantize === '32768' && out.quantize32_low === '3221225472' && out.quantize32_high === '6442450944' && out.session.length === 64; return { ok: ok, out: out }; }; function run(W, ctx, names) { var R = {}; for (var i = 0; i < names.length; i++) { var name = names[i], rec = { ok: false, out: null, err: null, ms: 0 }, t0 = ctx.now(); try { if (!WORK[name]) throw new Error('no workload ' + name); var res = WORK[name](W, ctx); rec.ok = res.ok === true; rec.out = canon(res.out); } catch (e) { rec.err = errText(e) + (e && e.name ? ' [' + e.name + ']' : ''); } rec.ms = Math.round(ctx.now() - t0); R[name] = rec; } return R; } root.WaiReachWorkloads = { forProfile: forProfile, run: run, canon: canon }; })(typeof self !== 'undefined' ? self : typeof global !== 'undefined' ? global : this);