#!/usr/bin/env python3 """receipt_verify.py: a second, independent verifier of WAI Quantum job receipts. Written from wai/extensions/quantum-providers.md §8 alone (the working text), and sharing no code with the engine. Its wasmQ rules (`wasmq_form`) were written from wai/extensions/quantum-wasmq.md §6.5, which §8.4 names, by a reader who had not seen the reference; the second version's (§11.6: rules 4, 8, 11, 12 and 30 as that version reads them, and rule 36, its energy) from §11 there. Outside specifications it relies on: RFC 8785 (JCS), RFC 8032 (Ed25519), the BLAKE3 specification, RFC 8259 (JSON), RFC 6901 (JSON Pointer). Standard library only, Python 3.9 or later, run as `python3 -I`. python3 -I receipt_verify.py FILE... one verdict line per file python3 -I receipt_verify.py --lines FILE one compact job a line, one verdict a line python3 -I receipt_verify.py --trust KEYS.json [--at MS [--skew-ms MS]] FILE... each receipt also held to a trust list and a time (§8.8), each when given python3 -I receipt_verify.py --self-test [ES_NUMBER_FILE] python3 -I receipt_verify.py --wasmq-cases OUT.jsonl [ES_NUMBER_FILE] python3 -I receipt_verify.py --plant NAME ... a deliberate fault (below), never for use --wasmq-cases writes every wasmQ case of the self-test whose whole-job verdict the self-test writes, one JSON object a line, {"name", "raw" (base64 of the job's exact bytes), "reasons" (sorted, [] when valid)}: what the self-test's author wrote from the text, not a verdict of this file, for another verifier to be run on. It judges nothing. The ES_NUMBER_FILE is taken for the self-test's shape and not read. A verdict line is {"file", "valid", "reasons": [sorted §8.4 reasons], "key", "form"} with "key" the receipt's key hex when the receipt is of its form (else null) and "form" "rfc8785", "first" or null. A receipt of its form adds what it seals of its time (§8.2), "time": {"sealed": true, "issued_ms", "not_after_ms" (or null)} or {"sealed": false} and, held to a trust list (--trust) or a time (--at), what it was held to (§8.8): "trust": {"listed": true, "not_before_ms", "not_after_ms", "revoked_from_ms"} (each a number or null) or {"listed": false} "checked_at_ms", "skew_ms" A trust list that does not read, or is not of its form, judges nothing: the verifier says why and exits 2. A provider's result adds "provider": {"form": "stated"|"earlier", "class", "read_as", "counts_source", "execution"} and a wasmQ job (its result's format is wai.quantum.wasmq.result/1 or /2) that was judged (not unreadable, not_a_job or no_receipt) adds, as quantum-wasmq §6.5 says a verifier states beside the verdict, "wasmq": {"outcome", "problems": [...], "notes": [...]} with "outcome" the sealed result's status (null when it is not a string), "problems" each §6.5 rule the job breaks, one entry a rule ("rule 14: ..."), the first 64 and then "and N more", and "notes" where the body's unsealed status, method and other members differ from what is sealed or are missing. Neither changes "valid" or "reasons". A set is no wasmQ job, and states none for its items. The exit status is 0 only when every verdict is valid. The reasons are exactly §8.4's, §8.6's and §8.7's: unreadable, not_a_job, no_receipt (each reported alone); receipt_form, digest_mismatch, bad_key, bad_signature; inexact_number; provider_class, request_provider, request_shots, counts (every provider result); provider_members, counts_source, execution, compiled_program, cost_confirmation (the stated form); wasmq_form (a wasmQ job, quantum-wasmq §6.5, whatever its method); set_items, set_item, set_root (a set, section 8.6); contract_form, planner_form, planner_route, planner_choice, planner_stable, planner_kept, contract_class, shadow, stopped (a job under a contract, section 8.7); key_untrusted, key_window, key_revoked (held to a trust list, section 8.8); expired, issued_later (held to a time, section 8.8). --plant NAME exists only to prove that a differential against another verifier can fail: each plant breaks one rule on purpose, and a verifier run with one is wrong by design. NAME is one of: lenient-key accept small-order and mixed-order keys (a library's default) no-alg skip the alg check last-duplicate read a duplicated member name, keeping the last, not refusing no-inexact skip inexact_number measured-simulator accept class measured on a simulator's stated result whole-cap cap every whole number at 2^53 − 1, not only a count's value lax-small-order-r do not refuse an R of small order no-canonical-spelling refuse an inexact whole number even in its canonical spelling set-seal-only check a set's seal, and nothing of its items or its root names-layout-only check compiled.qubit_names against the layouts only, not qasm3 route-unchecked take each route's stated outcome as it stands (section 8.7) choice-unchecked take the planner's choice as it stands (section 8.7) distance-unchecked take a shadow's stated distance as it stands (section 8.7) wasmq-unchecked skip the wasmQ rules (quantum-wasmq §6.5): no wasmq_form, and the wasmq statement's problems empty (its outcome and notes, which are no rules, still given) landscape-unchecked skip an energy-landscape job's rules (quantum-landscape §5.4): no landscape_form landscape2-unchecked hold a second-version landscape job to its names only (quantum-landscape-2 §5.4): a capacity, a parity of statistical and joules of any kind pass time-outside-digest take a receipt's time as it stands, its digest read as one that seals none (section 8.2) window-end-inside take a key's window to hold its last moment (section 8.8) untimed-anywhere place a receipt that seals no time in any window, and before any revocation (section 8.8) Without --plant the verifier is exactly §8's (and quantum-wasmq §6.5's, and quantum-landscape §5.4's, and quantum-landscape-2 §5.4's). Its reader's questions of the text, gap by gap, are what §8 now says: where §8 left a choice, it was settled in the text, and this file follows the text. Where quantum-wasmq §6.5 leaves one, the reading taken is marked SPEC-GAP [Wn]: [W2], [W5], [W9] to [W14], and [W18] to [W23]. [W1], [W3], [W4], [W6], [W7], [W8], [W15], [W16] and [W17] are gone: the text now settles them. """ import fractions import hashlib import json import math import re import struct import sys import time PLANTS_KNOWN = ("lenient-key", "no-alg", "last-duplicate", "no-inexact", "measured-simulator", "whole-cap", "lax-small-order-r", "no-canonical-spelling", "set-seal-only", "names-layout-only", "route-unchecked", "choice-unchecked", "distance-unchecked", "wasmq-unchecked", "landscape-unchecked", "landscape2-unchecked", "time-outside-digest", "window-end-inside", "untimed-anywhere") PLANTS = set() MAX_DEPTH = 127 # §8.2: nesting deeper than 127 is unreadable MAX_SAFE = 2 ** 53 - 1 # §8.8: what each receipt is held to beside its seal, when the reader gives it: "trust", # a trust list as read_trust reads one; "at_ms", a time; "skew_ms", the allowance. HOLD = {"trust": None, "at_ms": None, "skew_ms": 0} # =============================================================== 1. reading (§8.2) class Unreadable(Exception): """The text breaks a rule of reading (§8.2). `detail` is for the self-test only.""" def __init__(self, detail): Exception.__init__(self, detail) self.detail = detail class Num(object): """A JSON number: the text as written, and the double it reads as.""" __slots__ = ("text", "value") def __init__(self, text, value): self.text = text self.value = value def literal_whole(self): """§8.2: a whole number written as one (no fraction, no exponent).""" return not any(c in self.text for c in ".eE") def __repr__(self): return "Num(%s)" % self.text _WS = re.compile(r"[ \t\n\r]*") _NUMBER = re.compile(r"-?(?:0|[1-9][0-9]*)(?:\.[0-9]+)?(?:[eE][+-]?[0-9]+)?") _PLAIN = re.compile(r'[^"\\\x00-\x1f]*') _HEX4 = re.compile(r"[0-9A-Fa-f]{4}") _UNESCAPE = {'"': '"', "\\": "\\", "/": "/", "b": "\b", "f": "\f", "n": "\n", "r": "\r", "t": "\t"} def _number(text): # §8.2: the nearest double, ties to even (Python's float() is correctly # rounded); a magnitude of 2^1024 − 2^970 or more rounds to infinity and is # unreadable; one too small for any double but zero reads as zero. value = float(text) if math.isinf(value): raise Unreadable("number_overflow") return Num(text, value) class _Reader(object): def __init__(self, text): self.s = text self.i = 0 def ws(self): self.i = _WS.match(self.s, self.i).end() def value(self, depth): self.ws() s, i = self.s, self.i c = s[i:i + 1] if c == "{": return self.obj(depth + 1) if c == "[": return self.arr(depth + 1) if c == '"': return self.string() for word, val in (("true", True), ("false", False), ("null", None)): if s.startswith(word, i): self.i = i + len(word) return val m = _NUMBER.match(s, i) if m: self.i = m.end() return _number(m.group()) raise Unreadable("syntax") def obj(self, depth): if depth > MAX_DEPTH: # the outermost counted as the first raise Unreadable("depth") self.i += 1 out = {} self.ws() if self.s[self.i:self.i + 1] == "}": self.i += 1 return out while True: self.ws() if self.s[self.i:self.i + 1] != '"': raise Unreadable("syntax") key = self.string() self.ws() if self.s[self.i:self.i + 1] != ":": raise Unreadable("syntax") self.i += 1 value = self.value(depth) # §8.2: a member named twice, names compared after their escapes are read. if key in out: if "last-duplicate" not in PLANTS: raise Unreadable("duplicate") del out[key] # PLANT: keep the last out[key] = value self.ws() c = self.s[self.i:self.i + 1] self.i += 1 if c == "}": return out if c != ",": raise Unreadable("syntax") def arr(self, depth): if depth > MAX_DEPTH: raise Unreadable("depth") self.i += 1 out = [] self.ws() if self.s[self.i:self.i + 1] == "]": self.i += 1 return out while True: out.append(self.value(depth)) self.ws() c = self.s[self.i:self.i + 1] self.i += 1 if c == "]": return out if c != ",": raise Unreadable("syntax") def string(self): s = self.s i = self.i + 1 parts = [] while True: m = _PLAIN.match(s, i) parts.append(m.group()) i = m.end() c = s[i:i + 1] if c == '"': self.i = i + 1 return "".join(parts) if c != "\\": # §8.2: an unescaped control character (or the text's end) raise Unreadable("control" if c else "syntax") e = s[i + 1:i + 2] if e in _UNESCAPE: parts.append(_UNESCAPE[e]) i += 2 continue if e != "u" or not _HEX4.fullmatch(s, i + 2, i + 6): raise Unreadable("syntax") u = int(s[i + 2:i + 6], 16) i += 6 # §8.2: a high surrogate not followed at once by a low one, or a low alone. if 0xD800 <= u <= 0xDBFF: if s[i:i + 2] == "\\u" and _HEX4.fullmatch(s, i + 2, i + 6): lo = int(s[i + 2:i + 6], 16) if 0xDC00 <= lo <= 0xDFFF: parts.append(chr(0x10000 + ((u - 0xD800) << 10) + (lo - 0xDC00))) i += 6 continue raise Unreadable("surrogate") if 0xDC00 <= u <= 0xDFFF: raise Unreadable("surrogate") parts.append(chr(u)) # §8.2: a noncharacter is a character like any other def read_json(raw): """§8.2: UTF-8, no byte order mark, one JSON value with whitespace around it.""" if raw.startswith(b"\xef\xbb\xbf"): raise Unreadable("bom") try: text = raw.decode("utf-8") # strict: no overlong forms, no encoded surrogates except UnicodeDecodeError: raise Unreadable("utf8") reader = _Reader(text) value = reader.value(0) reader.ws() if reader.i != len(text): raise Unreadable("syntax") return value def _numbers(value): stack = [value] while stack: v = stack.pop() if isinstance(v, Num): yield v elif isinstance(v, dict): stack.extend(v.values()) elif isinstance(v, list): stack.extend(v) # ===================================================== 2. the two texts (§8.2) _ESCAPED = re.compile(r'[\x00-\x1f"\\]') _SHORT_ESCAPE = {'"': '\\"', "\\": "\\\\", "\b": "\\b", "\f": "\\f", "\n": "\\n", "\r": "\\r", "\t": "\\t"} def _quote(s): # §8.2: '"' and '\' escaped, the five short forms, other C0 controls as \u00xx # (lower case), every other character as its UTF-8 bytes, '/' and U+007F included. return '"' + _ESCAPED.sub( lambda m: _SHORT_ESCAPE.get(m.group(), "\\u%04x" % ord(m.group())), s) + '"' def _digits(x): """For a finite x > 0: (s, n) with s the fewest digits that read back as x (the nearest, a tie to the even last digit: Python's repr) and x = 0.s × 10^n.""" mant, _, exp = repr(x).partition("e") whole, _, frac = mant.partition(".") raw = whole + frac digits = raw.lstrip("0") lead = len(raw) - len(digits) return digits.rstrip("0"), len(whole) - lead + int(exp or 0) def es_number(x): """§8.2's canonical number: ECMAScript's Number::toString of the double.""" if x == 0: return "0" sign = "-" if x < 0 else "" d, n = _digits(abs(x)) k = len(d) if k <= n <= 21: return sign + d + "0" * (n - k) if 0 < n <= 21: return sign + d[:n] + "." + d[n:] if -6 < n <= 0: return sign + "0." + "0" * (-n) + d e = n - 1 return sign + (d if k == 1 else d[0] + "." + d[1:]) + "e" + ("+" if e >= 0 else "-") + str(abs(e)) def first_form_number(num): """§8.2's first-form number.""" t = num.text # §8.2: without a "-" from 0 to 2^64 − 1, or with a "-" from −2^63 to −1, as # its digits; so "-0" is a double: "-0.0". if num.literal_whole() and t != "-0": i = int(t) # at most 309 digits: longer ones are unreadable if 0 <= i <= 2 ** 64 - 1 or -2 ** 63 <= i <= -1: return str(i) x = num.value if x == 0: return "-0.0" if math.copysign(1.0, x) < 0 else "0.0" sign = "-" if x < 0 else "" d, n = _digits(abs(x)) k = len(d) if k <= n <= 16: return sign + d + "0" * (n - k) + ".0" if 0 < n <= 16: return sign + d[:n] + "." + d[n:] if -5 < n <= 0: return sign + "0." + "0" * (-n) + d # §8.2: then e, a sign (+ or -), and |n − 1| (1e+16, 1e-7) e = n - 1 return sign + (d if k == 1 else d[0] + "." + d[1:]) + "e" + ("+" if e >= 0 else "-") + str(abs(e)) def _utf16(s): return s.encode("utf-16-be") def text_of(value, canonical): """§8.2: the canonical text, or (canonical False) the first form's compact text.""" out = [] _write(value, out, canonical) return "".join(out) def _write(v, out, canonical): if v is None: out.append("null") elif v is True: out.append("true") elif v is False: out.append("false") elif isinstance(v, Num): out.append(es_number(v.value) if canonical else first_form_number(v)) elif isinstance(v, str): out.append(_quote(v)) elif isinstance(v, list): out.append("[") for j, x in enumerate(v): if j: out.append(",") _write(x, out, canonical) out.append("]") else: out.append("{") # canonical: names in UTF-16 code-unit order; first form: as the job gives them for j, k in enumerate(sorted(v, key=_utf16) if canonical else v): if j: out.append(",") out.append(_quote(k)) out.append(":") _write(v[k], out, canonical) out.append("}") # ===================================================================== 3. BLAKE3 _IV = (0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19) _PERM = (2, 6, 3, 10, 7, 0, 4, 13, 1, 11, 12, 5, 9, 14, 15, 8) _M32 = 0xFFFFFFFF _CHUNK_START, _CHUNK_END, _PARENT, _ROOT = 1, 2, 4, 8 def _g(v, a, b, c, d, x, y): v[a] = (v[a] + v[b] + x) & _M32 t = v[d] ^ v[a] v[d] = ((t >> 16) | (t << 16)) & _M32 v[c] = (v[c] + v[d]) & _M32 t = v[b] ^ v[c] v[b] = ((t >> 12) | (t << 20)) & _M32 v[a] = (v[a] + v[b] + y) & _M32 t = v[d] ^ v[a] v[d] = ((t >> 8) | (t << 24)) & _M32 v[c] = (v[c] + v[d]) & _M32 t = v[b] ^ v[c] v[b] = ((t >> 7) | (t << 25)) & _M32 def _compress(cv, m, counter, block_len, flags): v = list(cv) + list(_IV[:4]) + [counter & _M32, (counter >> 32) & _M32, block_len, flags] m = list(m) for _ in range(7): _g(v, 0, 4, 8, 12, m[0], m[1]) _g(v, 1, 5, 9, 13, m[2], m[3]) _g(v, 2, 6, 10, 14, m[4], m[5]) _g(v, 3, 7, 11, 15, m[6], m[7]) _g(v, 0, 5, 10, 15, m[8], m[9]) _g(v, 1, 6, 11, 12, m[10], m[11]) _g(v, 2, 7, 8, 13, m[12], m[13]) _g(v, 3, 4, 9, 14, m[14], m[15]) m = [m[p] for p in _PERM] return [v[i] ^ v[i + 8] for i in range(8)] def _chunk_cv(chunk, counter, root): cv = _IV blocks = max(1, (len(chunk) + 63) // 64) for b in range(blocks): block = chunk[64 * b:64 * b + 64] flags = _CHUNK_START if b == 0 else 0 if b == blocks - 1: flags |= _CHUNK_END | (_ROOT if root else 0) cv = _compress(cv, struct.unpack("<16I", block.ljust(64, b"\0")), counter, len(block), flags) return cv def _parent_cv(left, right, root): return _compress(_IV, left + right, 0, 64, _PARENT | (_ROOT if root else 0)) def blake3(data): """BLAKE3, hash mode, 32 bytes.""" chunks = max(1, (len(data) + 1023) // 1024) if chunks == 1: return struct.pack("<8I", *_chunk_cv(data, 0, True)) stack = [] for i in range(chunks - 1): cv = _chunk_cv(data[1024 * i:1024 * (i + 1)], i, False) total = i + 1 while total & 1 == 0: cv = _parent_cv(stack.pop(), cv, False) total >>= 1 stack.append(cv) cv = _chunk_cv(data[1024 * (chunks - 1):], chunks - 1, False) while len(stack) > 1: cv = _parent_cv(stack.pop(), cv, False) return struct.pack("<8I", *_parent_cv(stack.pop(), cv, True)) # ============================================================ 4. Ed25519 (§8.2) _P = 2 ** 255 - 19 _L = 2 ** 252 + 27742317777372353535851937790883648493 _D = -121665 * pow(121666, _P - 2, _P) % _P _SQRT_M1 = pow(2, (_P - 1) // 4, _P) _IDENTITY = (0, 1, 1, 0) def _add(p, q): x1, y1, z1, t1 = p x2, y2, z2, t2 = q a = (y1 - x1) * (y2 - x2) % _P b = (y1 + x1) * (y2 + x2) % _P c = 2 * t1 * t2 * _D % _P d = 2 * z1 * z2 % _P e, f, g, h = b - a, d - c, d + c, b + a return (e * f % _P, g * h % _P, f * g % _P, e * h % _P) def _mul(k, p): q = _IDENTITY while k: if k & 1: q = _add(q, p) p = _add(p, p) k >>= 1 return q def _same_point(p, q): return ((p[0] * q[2] - q[0] * p[2]) % _P == 0 and (p[1] * q[2] - q[1] * p[2]) % _P == 0) def _decode_point(b): """§8.2 (RFC 8032 §5.1.3): the point, or None for y ≥ p, off the curve, or x = 0 signed.""" y = int.from_bytes(b, "little") sign = y >> 255 y &= (1 << 255) - 1 if y >= _P: return None x2 = (y * y - 1) * pow(_D * y * y + 1, _P - 2, _P) % _P x = pow(x2, (_P + 3) // 8, _P) if (x * x - x2) % _P: x = x * _SQRT_M1 % _P if (x * x - x2) % _P: return None if x == 0 and sign: return None if x & 1 != sign: x = _P - x return (x, y, 1, x * y % _P) def _encode_point(p): zi = pow(p[2], _P - 2, _P) x, y = p[0] * zi % _P, p[1] * zi % _P return (y | ((x & 1) << 255)).to_bytes(32, "little") def _small_order(p): return _same_point(_mul(8, p), _IDENTITY) _B = _decode_point((4 * pow(5, _P - 2, _P) % _P).to_bytes(32, "little")) def key_point(key): """§8.2: the key A as a point, or None when the strict rules refuse it (bad_key).""" a = _decode_point(key) if a is None: return None if "lenient-key" in PLANTS: # PLANT: a library's default verify return a if _small_order(a) or not _same_point(_mul(_L, a), _IDENTITY): return None return a def signature_holds(a, key, digest, sig): """§8.2: R decodes and is not of small order, S < ℓ, and [S]B = R + [k]A.""" r = _decode_point(sig[:32]) if r is None or ("lax-small-order-r" not in PLANTS and _small_order(r)): return False s = int.from_bytes(sig[32:], "little") if s >= _L: return False k = int.from_bytes(hashlib.sha512(sig[:32] + key + digest).digest(), "little") % _L return _same_point(_mul(s, _B), _add(r, _mul(k, a))) def _ed25519_sign(seed, msg): """RFC 8032 §5.1.6, for the self-test only: (public key, signature).""" h = hashlib.sha512(seed).digest() a = (int.from_bytes(h[:32], "little") & ((1 << 254) - 8)) | (1 << 254) public = _encode_point(_mul(a, _B)) r = int.from_bytes(hashlib.sha512(h[32:] + msg).digest(), "little") % _L r_bytes = _encode_point(_mul(r, _B)) k = int.from_bytes(hashlib.sha512(r_bytes + public + msg).digest(), "little") % _L return public, r_bytes + ((r + k * a) % _L).to_bytes(32, "little") # =============================================================== 5. the seal DOMAIN = b"wai:quantum-service-receipt" _LOWER_HEX = re.compile(r"[0-9a-f]*") def seal_digest(form_byte, q, t, v=None): """§8.2: BLAKE3(d ‖ u64(|Q|) ‖ Q ‖ u64(|T|) ‖ T), d the domain and its form byte; and, for a receipt that seals a time, ‖ u64(|V|) ‖ V after them, under the byte 3.""" data = (DOMAIN + bytes([form_byte]) + struct.pack(">Q", len(q)) + q + struct.pack(">Q", len(t)) + t) if v is not None: data += struct.pack(">Q", len(v)) + v return blake3(data) def _ms(v): """§8.2: a time, a whole number from 0 to 2^53 − 1 however it is written; else None.""" if isinstance(v, Num) and v.value == int(v.value) and 0 <= v.value <= MAX_SAFE: return int(v.value) return None def read_time(time): """§8.2: a receipt's `time` by its form, as (issued_ms, not_after_ms or None); None for what is not one: not an object, a member other than issued_ms and not_after_ms, no issued_ms, either not a whole number from 0 to 2^53 − 1, or an end not after the issue.""" if not isinstance(time, dict) or any(k not in ("issued_ms", "not_after_ms") for k in time): return None issued = _ms(time.get("issued_ms")) if issued is None: return None if "not_after_ms" not in time: return issued, None end = _ms(time["not_after_ms"]) if end is None or end <= issued: return None return issued, end def _lower_hex(v, length): return isinstance(v, str) and len(v) == length and _LOWER_HEX.fullmatch(v) is not None def check_seal(request, receipt, body, reasons): """§8.4 receipt_form, digest_mismatch, bad_key, bad_signature, over the request and the sealed body (a job's result less its receipt; a set's head). Returns (key, form, time), time the (issued_ms, not_after_ms) the receipt seals, or None.""" form = None if isinstance(receipt, dict): if "canon" not in receipt: form = "first" elif receipt["canon"] == "rfc8785": form = "rfc8785" # §8.2: a time is sealed by a canonical receipt alone, and is of its form. time = None if form is not None and "time" in receipt: time = read_time(receipt["time"]) if form == "rfc8785" else None if time is None: form = None if (form is None or ("no-alg" not in PLANTS and receipt.get("alg") != "ed25519") or not _lower_hex(receipt.get("key"), 64) or not _lower_hex(receipt.get("digest"), 64) or not _lower_hex(receipt.get("signature"), 128)): reasons.add("receipt_form") # and the next three are not checked return None, None, None key = bytes.fromhex(receipt["key"]) stated = bytes.fromhex(receipt["digest"]) sig = bytes.fromhex(receipt["signature"]) canonical = form == "rfc8785" q = text_of(request, canonical).encode("utf-8") t = text_of(body, canonical).encode("utf-8") if time is not None and "time-outside-digest" not in PLANTS: digest = seal_digest(3, q, t, text_of(receipt["time"], True).encode("utf-8")) else: digest = seal_digest(2 if canonical else 1, q, t) if stated != digest: reasons.add("digest_mismatch") a = key_point(key) if a is None: reasons.add("bad_key") # and the signature is not checked elif not signature_holds(a, key, stated, sig): reasons.add("bad_signature") # over the digest the receipt states return receipt["key"], form, time def _first_form_digits(num): """§8.2: a whole number the first form seals by its digits (its writer's integer range).""" if not num.literal_whole() or num.text == "-0": return False i = int(num.text) return 0 <= i <= 2 ** 64 - 1 or -2 ** 63 <= i <= -1 def check_inexact(request, body, form, reasons): # §8.4 inexact_number: a whole number written as one, in what the receipt seals # (the request, and the result less its receipt; a set's request and head) and # sealed as a double, is not a double, and is not the canonical text of the double # it reads as. A receipt is of the first form when receipt_form is not reported and # it has no canon; one receipt_form refuses names no form, and its numbers are # read as a canonical receipt's (every number sealed as its double). if any(writes_inexact(part, form) for part in (request, body)): reasons.add("inexact_number") def writes_inexact(value, form): """§8.2, §8.4: whether a value writes a whole number, sealed as a double, that is no double and not the canonical text of the double it reads as, by a receipt's form.""" if "no-inexact" in PLANTS: # PLANT return False first = form == "first" for n in _numbers(value): if not n.literal_whole() or (first and _first_form_digits(n)): continue if int(n.text) == int(n.value): continue # the double holds it exactly # §8.2: its one taken spelling, RFC 8785's for a whole double whose magnitude is # from 2^53 to under 10^21, a negative with its "-": shortest digits padded with # zeros (2^60 as 1152921504606847000). if "no-canonical-spelling" not in PLANTS and n.text == es_number(n.value): continue return True return False # ======================================================== 6. a provider's result STEPS = ("mitigation", "twirling", "decoupling", "remapping", "optimisation") COUNTS_SOURCES = ("shots", "vendor_counts", "probabilities") BASES = ("rzsxxcz", "prxcz", "gpizz", "prxrzxx") MAX_LISTED = 65536 _OUTCOME = re.compile(r"[01]*") _INDEX = re.compile(r"0|[1-9][0-9]*") # §8.4: an index in decimal, with no leading zero _QASM_INDEX = re.compile(r"\$([0-9]+)") # §8.4: a "$" and one or more decimal digits _MODEL_NAME = object() # a row's placeholder: the noise model's name def _row(fields, settings, steps, verbatim): row = {"stated_by": "client", "sent": {"fields": fields, "settings": settings}, "verbatim": verbatim} for step in STEPS: row[step] = steps.get(step, "default") return row _CLOUD_TASKS_FIELDS = ["action", "clientToken", "deviceArn", "outputS3Bucket", "outputS3KeyPrefix", "shots"] def _any_provenance(provenance): return True def _silicon(provenance): return provenance == "silicon" def _not_silicon(provenance): return provenance != "silicon" # §8.3: each built-in kind's rows as (the provenances it holds for, the counts' # sources it gives, the execution less its note): cloud-tasks' first row for # silicon, its second for any other; native-turns' row with noise for any but # silicon (its model's name a string, not empty), its row without noise for any. # §8.4: only a kind with rows constrains counts_source, to what the rows that hold # for its provenance give; http, process and later kinds give any of the three. _SHOTS, _VENDOR, _PROBABILITIES = ("shots",), ("vendor_counts",), ("probabilities",) _TASKS = ("shots", "probabilities") ROWS = { "sampler-v2": [(_any_provenance, _SHOTS, _row( ["backend", "params", "program_id"], {"/params/options/dynamical_decoupling/enable": False, "/params/options/twirling/enable_gates": False, "/params/options/twirling/enable_measure": False}, {"decoupling": "off", "twirling": "off"}, False))], "prx-circuits": [(_any_provenance, _VENDOR, _row(["circuits", "shots"], {}, {}, False))], "native-turns": [ (_any_provenance, _PROBABILITIES, _row( ["backend", "input", "settings", "shots", "type"], {"/input/gateset": "native", "/settings/error_mitigation/debiasing": False}, {"mitigation": "off"}, False)), (_not_silicon, _PROBABILITIES, _row( ["backend", "input", "noise", "settings", "shots", "type"], {"/input/gateset": "native", "/settings/error_mitigation/debiasing": False, "/noise/model": _MODEL_NAME}, {"mitigation": "off"}, False))], "cloud-tasks": [ (_silicon, _TASKS, _row(_CLOUD_TASKS_FIELDS, {"verbatim_box": True}, {"remapping": "off", "optimisation": "off"}, True)), (_not_silicon, _TASKS, _row(_CLOUD_TASKS_FIELDS, {}, {}, False))], } def _whole(v): """§8.4: a number whose value is whole, however it is written, however large (only a count's value has a ceiling, and check_counts holds it).""" if "whole-cap" in PLANTS and isinstance(v, Num) and abs(v.value) > MAX_SAFE: return False # PLANT return isinstance(v, Num) and v.value.is_integer() def _same(a, b): """JSON equality, numbers by value (spelling is not sealed).""" if isinstance(a, Num) or isinstance(b, Num): return isinstance(a, Num) and isinstance(b, Num) and a.value == b.value if isinstance(a, bool) or isinstance(b, bool) or a is None or b is None: return a is b if isinstance(a, str) or isinstance(b, str): return isinstance(a, str) and isinstance(b, str) and a == b if isinstance(a, list) and isinstance(b, list): return len(a) == len(b) and all(_same(x, y) for x, y in zip(a, b)) if isinstance(a, dict) and isinstance(b, dict): return set(a) == set(b) and all(_same(a[k], b[k]) for k in a) return False def read_class(provenance): """§8.4: the class a provenance gives: measured, simulated, or None.""" if provenance == "silicon": # §8.1: silicon exactly; "silicon:…" gives none return "measured" if isinstance(provenance, str) and provenance.split(":", 1)[0] in ("simulator", "emulator"): return "simulated" return None def _member(obj, *path): for name in path: if not isinstance(obj, dict) or name not in obj: return None obj = obj[name] return obj def check_class(result, provider, stated, reasons): # §8.4 provider_class. accuracy = result.get("accuracy") cls = accuracy.get("class") if isinstance(accuracy, dict) else None if not provider: # A sign-off (§8.9) repeats the class of the job it signs off. if cls in ("measured", "simulated") and result.get("format") != "wai.quantum.signoff/1": reasons.add("provider_class") return wanted = read_class(_member(result, "provider", "provenance")) if stated else "measured" planted = "measured-simulator" in PLANTS and stated and wanted == "simulated" and cls == "measured" if (wanted is None or cls != wanted) and not planted: reasons.add("provider_class") if isinstance(accuracy, dict) and "approximate" in accuracy: if accuracy["approximate"] is not True or not stated or cls != "simulated": reasons.add("provider_class") def check_counts(result, reasons): # §8.4 counts. counts = result.get("counts") shots, omitted, distinct = (result.get(k) for k in ("shots", "omitted_shots", "distinct_outcomes")) ok = isinstance(counts, dict) total, widths = 0, set() if ok: for outcome, n in counts.items(): if not _OUTCOME.fullmatch(outcome) or not (_whole(n) and 1 <= n.value <= MAX_SAFE): ok = False break widths.add(len(outcome)) total += int(n.value) ok = ok and len(widths) <= 1 # §8.4: shots a whole number of at least 1; omitted_shots and distinct_outcomes # whole numbers of at least 0. The counts and omitted_shots sum to accepted_shots, the # shots the device kept, when the result has that member (a whole number of at least 1, # whatever its value: null is present), and to shots when it has none (§8.1). kept = result["accepted_shots"] if "accepted_shots" in result else shots if (ok and _whole(shots) and shots.value >= 1 and _whole(kept) and kept.value >= 1 and _whole(omitted) and omitted.value >= 0 and _whole(distinct) and distinct.value >= 0): listed = len(counts) omitted_n, distinct_n = int(omitted.value), int(distinct.value) if total + omitted_n != int(kept.value): ok = False elif omitted_n == 0: ok = distinct_n == listed else: ok = listed == MAX_LISTED and distinct_n > listed else: ok = False if not ok: reasons.add("counts") def qubit_names_hold(names, compiled): """§8.4: compiled.qubit_names as given: an object from indices to non-empty strings, holding every entry of layout and final_layout, written in decimal in full, and every index qasm3 acts on, when qasm3 is a string.""" if not isinstance(names, dict): return False if not all(_INDEX.fullmatch(k) and isinstance(v, str) and v for k, v in names.items()): return False # SPEC-GAP: [N32] "in full": the exact digits of the double the entry reads as, # so 1.0 is "1" and 1e23 is "99999999999999991611392". An entry that is no # whole number is provider_members' already, and is not looked for here. for name in ("layout", "final_layout"): entries = compiled.get(name) if isinstance(entries, list): for q in entries: if _whole(q) and str(int(q.value)) not in names: return False qasm3 = compiled.get("qasm3") if "names-layout-only" not in PLANTS and isinstance(qasm3, str): # PLANT: skip it # §8.4: each "$" followed by one or more decimal digits names the index those # digits read as, written with no leading zero; a "$" with no digit names none. # §8.4: a "$" anywhere in it, followed by the ASCII digits 0 to 9. for m in _QASM_INDEX.finditer(qasm3): if (m.group(1).lstrip("0") or "0") not in names: return False return True def check_members(result, reasons): # §8.4 provider_members: each member, present and of its type. def text(v): return isinstance(v, str) and v != "" def natural(v): # §8.4: a whole number of at least 0 return _whole(v) and v.value >= 0 def naturals(v): return isinstance(v, list) and all(natural(x) for x in v) p = result.get("provider") c = result.get("compiled") j = result.get("job") cost = result.get("cost") energy = result.get("energy") engine = result.get("engine") p = p if isinstance(p, dict) else {} c = c if isinstance(c, dict) else {} j = j if isinstance(j, dict) else {} cost = cost if isinstance(cost, dict) else {} energy = energy if isinstance(energy, dict) else {} engine = engine if isinstance(engine, dict) else {} charged = cost.get("charged", 0) # §8.4: compiled.qubit_names is required of cloud-tasks and prx-circuits when the # execution is stated by client, and optional otherwise; when given it holds its # shape. SPEC-GAP: [N31] required on a cloud-tasks simulator too, as §8.4 says, # though §8.1 names only "a cloud-tasks processor's labels". §8.4: null is # given, and is no object. names_needed = (p.get("kind") in ("cloud-tasks", "prx-circuits") and _member(result, "execution", "stated_by") == "client") checks = ( all(text(p.get(f)) for f in ("name", "kind", "protocol", "device")), read_class(p.get("provenance")) is not None, _lower_hex(p.get("describe"), 64), _whole(p.get("qubits")) and p["qubits"].value >= 1, "basis" in p and "basis" in c and _same(p["basis"], c["basis"]), "calibration" in result and (result["calibration"] is None or isinstance(result["calibration"], str)), c.get("basis") in BASES if isinstance(c.get("basis"), str) else False, _lower_hex(c.get("program"), 64), isinstance(c.get("qasm3"), str), all(natural(c.get(f)) for f in ("native_gates", "two_qubit_gates", "swaps")), naturals(c.get("layout")) and naturals(c.get("final_layout")), isinstance(c.get("checked"), str), qubit_names_hold(c["qubit_names"], c) if "qubit_names" in c else not names_needed, text(j.get("id")) and natural(j.get("polls")), isinstance(_member(result, "ideal", "computed"), bool), isinstance(cost.get("free"), bool) and isinstance(cost.get("confirmed"), bool), isinstance(cost.get("estimate"), dict), # §8.1: with `unknown` when none was known charged is None or (isinstance(charged, dict) and isinstance(charged.get("amount"), str) and isinstance(charged.get("currency"), str)), isinstance(energy.get("unmetered"), str), "service_kwh" not in energy or isinstance(energy.get("service_kwh_is"), str), result.get("schema") == "wai.quantum.job-result/1", engine.get("name") == "wai-quantum" and isinstance(engine.get("version"), str), ) if not all(checks): reasons.add("provider_members") def execution_rules_hold(e): """§8.3's rules of an execution.""" if not isinstance(e, dict): return False if set(e) - set(STEPS + ("stated_by", "verbatim", "sent", "note")): return False # "and nothing else" if any(m not in e for m in STEPS + ("stated_by", "verbatim")): return False by = e["stated_by"] # §8.3: client: off, on or default, verbatim true or false, sent given; # provider: off, on, none or unknown, verbatim true or false, no sent; # nobody: unknown, verbatim null, no sent. if by == "client": allowed, verbatim_ok, sent = ("off", "on", "default"), isinstance(e["verbatim"], bool), True elif by == "provider": allowed, verbatim_ok, sent = ("off", "on", "none", "unknown"), isinstance(e["verbatim"], bool), False elif by == "nobody": allowed, verbatim_ok, sent = ("unknown",), e["verbatim"] is None, False else: return False if not verbatim_ok or ("sent" in e) != sent: return False if not all(isinstance(e[s], str) and e[s] in allowed for s in STEPS): return False if "note" in e and not isinstance(e["note"], str): return False if e["verbatim"] is True and not (e["remapping"] in ("off", "none") and e["optimisation"] in ("off", "none")): return False if by != "client": return True s = e["sent"] if not isinstance(s, dict) or set(s) != {"fields", "settings"}: return False fields, settings = s["fields"], s["settings"] if not isinstance(fields, list) or not all(isinstance(f, str) for f in fields): return False encoded = [f.encode("utf-8") for f in fields] if any(a >= b for a, b in zip(encoded, encoded[1:])): return False # each once, in increasing order of their UTF-8 bytes if not isinstance(settings, dict): return False # §8.3: each key of settings either begins with "/", and its first reference # token (up to the next "/", its ~1 and ~0 read as "/" and "~") is one of the # fields, the rest of it not read; or is a name, not empty, not beginning "/". named = set(fields) # a list here would make this quadratic for k in settings: if not k.startswith("/"): if not k: return False continue first = k[1:].split("/", 1)[0].replace("~1", "/").replace("~0", "~") if first not in named: return False if any(e[step] in ("off", "on") for step in STEPS) and not settings: return False # a step said off or on says by which setting return True def _matches_row(e, row): plain = dict((k, v) for k, v in e.items() if k != "note") if set(plain) != set(row): return False for name, want in row.items(): got = plain[name] if name != "sent": if not (got is want if isinstance(want, bool) else got == want): return False continue if not (isinstance(got.get("fields"), list) and got["fields"] == want["fields"]): return False have = got.get("settings") if not isinstance(have, dict) or set(have) != set(want["settings"]): return False for k, v in want["settings"].items(): if v is _MODEL_NAME: if not (isinstance(have[k], str) and have[k]): return False elif not (have[k] is v if isinstance(v, bool) else have[k] == v): return False return True def check_stated(result, reasons): """§8.4's rules for the stated form beyond provider_members.""" kind = _member(result, "provider", "kind") kind = kind if isinstance(kind, str) else None source = result.get("counts_source") provenance = _member(result, "provider", "provenance") if not (isinstance(source, str) and source in COUNTS_SOURCES and (kind not in ROWS or any(holds(provenance) and source in sources for holds, sources, _ in ROWS[kind]))): reasons.add("counts_source") e = result.get("execution") # §8.4: the rules of §8.3; for a kind with rows, one of the rows that hold for # its provenance, or stated by nobody; for http and process, stated by provider # or nobody. A later kind is held to §8.3's rules alone. if not execution_rules_hold(e): reasons.add("execution") elif kind in ROWS and e["stated_by"] != "nobody" and not any( holds(provenance) and _matches_row(e, row) for holds, _, row in ROWS[kind]): reasons.add("execution") elif kind in ("http", "process") and e["stated_by"] not in ("provider", "nobody"): reasons.add("execution") # §8.4 compiled_program, when qasm3 is a string and program 64 lower-case hex digits. c = result.get("compiled") if (isinstance(c, dict) and isinstance(c.get("qasm3"), str) and _lower_hex(c.get("program"), 64) and bytes.fromhex(c["program"]) != blake3(c["qasm3"].encode("utf-8"))): reasons.add("compiled_program") # §8.4 cost_confirmation: confirmed true on a free run, or false on one that is not; # or a member confirmed_by (null included) that is not "submit", or "submit" beside a # confirmed that is not true (§8.1: a provider's own record takes the job's submit as # the confirmation of a run that is not free, and of no other). cost = result.get("cost") if isinstance(cost, dict): free, confirmed = cost.get("free"), cost.get("confirmed") if isinstance(free, bool) and isinstance(confirmed, bool) and free is confirmed: reasons.add("cost_confirmation") if "confirmed_by" in cost and not (cost["confirmed_by"] == "submit" and confirmed is True): reasons.add("cost_confirmation") def check_provider(request, result, reasons): stated = "counts_source" in result or "execution" in result check_class(result, True, stated, reasons) # §8.4 request_provider: provider.name a string equal to the request's provider. # §8.4, §8.7: or, when the request gives none and its contract allows a provider, # the one its planner chose. name, asked = _member(result, "provider", "name"), request.get("provider") if asked is None and _member(request, "contract", "providers") == "allowed": choice = _member(result, "planner", "choice") asked = choice[len("provider:"):] if isinstance(choice, str) and choice.startswith("provider:") else None if not (isinstance(name, str) and isinstance(asked, str) and name == asked): reasons.add("request_provider") # §8.4 request_shots: the request's shots, 1024 when it gives none or null. want = request.get("shots") want = Num("1024", 1024.0) if want is None else want if "shots" not in result or not _same(result["shots"], want): reasons.add("request_shots") check_counts(result, reasons) if stated: check_members(result, reasons) check_stated(result, reasons) def _plain(v): """A value as Python's json module writes it, for the verdict line.""" if isinstance(v, Num): return int(v.value) if v.value.is_integer() and abs(v.value) < 2 ** 63 else v.value if isinstance(v, dict): return dict((k, _plain(x)) for k, x in v.items()) if isinstance(v, list): return [_plain(x) for x in v] return v def provider_statement(result): """§8.4: for a provider's result, its form, its class as its provenance reads it, and in the stated form its counts' source and its execution.""" stated = "counts_source" in result or "execution" in result accuracy = result.get("accuracy") return { "form": "stated" if stated else "earlier", "class": _plain(accuracy.get("class")) if isinstance(accuracy, dict) else None, "read_as": read_class(_member(result, "provider", "provenance")), "counts_source": _plain(result.get("counts_source")) if stated else None, "execution": _plain(result.get("execution")) if stated else None, } # ================================================== 6b. a job under a contract (§8.7) CONTRACT_MEMBERS = ("exactness", "max_cost", "deadline_seconds", "max_joules", "providers") MEETS = { "bit-exact": ("bit-exact",), "exact": ("bit-exact", "exact"), "single": ("bit-exact", "exact", "single"), "bounded": ("bit-exact", "exact", "bounded"), "estimate": ("bit-exact", "exact", "bounded", "estimate"), "heuristic": ("bit-exact", "exact", "single", "bounded", "estimate", "heuristic"), "measured": ("measured",), "simulated": ("simulated",), } CLASSES_WANTED = tuple(MEETS) + ("any",) LADDER = ("bit-exact", "exact", "single", "bounded", "estimate", "heuristic") LEAVES_OUT = ("time", "amount", "energy", "mitigation", "decoder", "charged", "cancel") QUESTIONS = ("noise", "counts", "expectations", "amplitudes") _DECIMAL = re.compile(r"[0-9]+(?:\.[0-9]+)?") _GPU_METHODS = ("method:statevector_single", "method:cutrank_single") MAX_SECONDS = 1e12 # §8.7: the most seconds a price may state MAX_AMOUNT = 64 # §8.7: the most characters an amount may have # §8.7: each built-in method's rank in auto's order, by question (noise, counts, # expectations, amplitudes); None where auto does not try it for that question. AUTO_RANKS = { "exact": (None, 20, 20, 10), "statevector": (None, 30, 30, 20), "statevector_single": (None, 40, 40, 30), "stabilizer": (20, 10, 10, None), "pauli": (None, None, 60, None), "mps": (None, 60, 70, 70), "stabilizer_rank": (None, None, 50, 50), "tensor_network": (None, None, None, 60), "cutrank": (None, 50, None, 40), "cutrank_single": (None, None, None, None), "density_matrix": (10, None, None, None), "trajectories": (30, None, None, None), "pulse": (None, None, None, None), } # §8.7: the classes each built-in method can have; which of two, on a job, by _route_class. METHOD_CLASSES = { "exact": ("bit-exact",), "statevector": ("exact",), "statevector_single": ("single",), "stabilizer": ("exact", "estimate"), "pauli": ("bounded",), "mps": ("exact", "heuristic"), "stabilizer_rank": ("exact", "estimate"), "tensor_network": ("exact",), "cutrank": ("exact", "single"), "cutrank_single": ("single",), "density_matrix": ("exact",), "trajectories": ("estimate",), "pulse": ("bounded",), } _GPU_NAMES = ("statevector_single", "cutrank_single") def meets(wanted, got): """§8.7's table. `any` takes every class; a class nobody knows meets nothing else.""" return wanted == "any" or (wanted in MEETS and got in MEETS[wanted]) def _is_decimal(s): """§8.7: digits, optionally '.' and digits, at most 64 characters.""" return isinstance(s, str) and len(s) <= MAX_AMOUNT and _DECIMAL.fullmatch(s) is not None def _value_of(v): return v.value if isinstance(v, Num) else None def _same_keys(v, keys): return isinstance(v, dict) and set(v) == set(keys) def read_contract(c): """§8.7: the contract as (exactness, max_cost, deadline, joules, providers), or None when it is not of its form. Null is absent.""" if not isinstance(c, dict) or any(k not in CONTRACT_MEMBERS for k in c): return None exactness = c.get("exactness") if exactness is not None and exactness not in CLASSES_WANTED: return None cost = c.get("max_cost") if cost is not None: if not (isinstance(cost, dict) and len(cost) == 2 and _is_decimal(cost.get("amount")) and isinstance(cost.get("currency"), str) and cost["currency"]): return None for k in ("deadline_seconds", "max_joules"): v = c.get(k) if v is not None and not (isinstance(v, Num) and v.value > 0): return None providers = c.get("providers") if providers is not None and providers not in ("never", "allowed"): return None return {"exactness": exactness, "max_cost": cost, "deadline": c["deadline_seconds"].value if c.get("deadline_seconds") is not None else None, "joules": c["max_joules"].value if c.get("max_joules") is not None else None, "providers": providers} def _seconds_ok(v): return isinstance(v, Num) and 0 <= v.value <= MAX_SECONDS def _price_form(p, local): """§8.7: a price. A local route's money is free; seconds and amounts are bounded.""" if not isinstance(p, dict): return False m = p.get("money") if not isinstance(m, dict): return False if m.get("free") is False: if local or not (isinstance(m.get("unknown"), str) or (isinstance(m.get("amount"), str) and isinstance(m.get("currency"), str))): return False elif m.get("free") is not True: return False if "at_least" in m and m["at_least"] is not True: return False if "amount" in m and not (isinstance(m["amount"], str) and len(m["amount"]) <= MAX_AMOUNT): return False t = p.get("time") if not isinstance(t, dict) or not (t.get("seconds") is None or _seconds_ok(t["seconds"])): return False e = p.get("energy") if not isinstance(e, dict) or not (e.get("joules") is None or isinstance(e["joules"], Num)): return False if any(k in e and not isinstance(e[k], str) for k in ("watch", "unwatched")) or ("watch" in e and "unwatched" in e): return False left = p.get("leaves_out") if not isinstance(left, list) or any(w not in LEAVES_OUT for w in left): return False for k in ("memory_bytes", "work"): # A method's are whole numbers, and a provider's null: it states neither. if k not in p or not ((_whole(p[k]) and p[k].value >= 0) if local else p[k] is None): return False return True def _route_form(r): if not isinstance(r, dict): return False name, kind = r.get("route"), r.get("kind") if not isinstance(name, str): return False local = name.startswith("method:") and len(name) > 7 and kind == "local" if not (local or (name.startswith("provider:") and len(name) > 9 and kind == "provider")): return False outcome = r.get("outcome") if outcome in ("chosen", "met"): if "rejected" in r: return False elif outcome == "rejected": rej = r.get("rejected") if not (isinstance(rej, dict) and isinstance(rej.get("code"), str) and isinstance(rej.get("why"), str)): return False else: return False if "price" not in r: return False if r["price"] is not None and not _price_form(r["price"], local): return False if local: if "auto_rank" not in r or not (r["auto_rank"] is None or (_whole(r["auto_rank"]) and r["auto_rank"].value >= 0)): return False return isinstance(r.get("class"), str) and isinstance(r.get("host_dependent"), bool) def _class_of_method(method, cls): """§8.7: whether cls is one the built-in method has; any class of another.""" return method not in METHOD_CLASSES or cls in METHOD_CLASSES[method] def _states_itself(r, request): """§8.7: a built-in method has the class its table gives it on this request, and depends on the host only when it runs on a GPU; a provider's route depends on it.""" name = r["route"] cls = r["class"] if not name.startswith("method:"): # A provider's route has the class its provenance gives. given = read_class(r.get("provenance")) return r["host_dependent"] is True and (given is None or cls == given) m = name[len("method:"):] if m not in METHOD_CLASSES: return r["host_dependent"] is True # a method the host registered is its own code options = request.get("options") given = lambda k: isinstance(options, dict) and options.get(k) is not None if m == "stabilizer": want = "estimate" if request.get("noise") is not None or request.get("target") is not None else "exact" if cls != want: return False if m == "stabilizer_rank" and cls != ("estimate" if given("terms") or given("epsilon") else "exact"): return False # Every other method but cut-rank (whose plan says which table fits) has the one # class its table gives: the first each class it declares meets. if m not in ("stabilizer", "stabilizer_rank", "cutrank"): declared = METHOD_CLASSES[m] worst = declared[0] if len(declared) == 1 else next((c for c in LADDER if all(meets(c, d) for d in declared)), None) if cls != worst: return False return cls in METHOD_CLASSES[m] and r["host_dependent"] is (m in _GPU_NAMES) def _ran_as_routed(routes, choice, result): """§8.7: the route chosen is what ran; for a provider's, the result's provider is the device and provenance it names, where it names them, and the result's cost is its money.""" r = next((x for x in routes if x["route"] == choice), None) if r is None or r["kind"] != "provider": return True money = _member(r, "price", "money") cost = result.get("cost") provider = result.get("provider") if not (isinstance(money, dict) and isinstance(cost, dict) and isinstance(provider, dict)): return False estimate = cost.get("estimate") if isinstance(cost.get("estimate"), dict) else {} return (all(k not in r or _alike(r[k], provider.get(k)) for k in ("device", "provenance")) and _alike(cost.get("free"), money.get("free")) and all(_alike(estimate.get(k), money.get(k)) for k in ("amount", "currency", "unit", "at_least"))) def _alike(a, b): """§8.7: two members alike: numbers by value (7 and 7.0, -0 and 0), a boolean only to a boolean, and null as an absent member.""" if isinstance(a, Num) or isinstance(b, Num): return isinstance(a, Num) and isinstance(b, Num) and float(a.value) == float(b.value) if isinstance(a, bool) or isinstance(b, bool): return isinstance(a, bool) and isinstance(b, bool) and a == b # Lists and objects member by member, by the same rule. if isinstance(a, list) or isinstance(b, list): return isinstance(a, list) and isinstance(b, list) and len(a) == len(b) and all(_alike(x, y) for x, y in zip(a, b)) if isinstance(a, dict) or isinstance(b, dict): return isinstance(a, dict) and isinstance(b, dict) and all(_alike(a.get(k), b.get(k)) for k in set(a) | set(b)) return a == b def _planner_form(p): if not isinstance(p, dict) or p.get("format") != "wai.quantum.planner/1": return False if not (p.get("wanted") is None or isinstance(p["wanted"], str)): return False if "wanted_from" not in p: return False if p["wanted_from"] is None: if p.get("wanted") is not None: return False elif p["wanted_from"] not in ("contract", "named", "auto"): return False routes = p.get("routes") if not isinstance(routes, list) or not routes or not all(_route_form(r) for r in routes): return False names = [r["route"] for r in routes] if len(set(names)) != len(names): return False for k in ("named", "auto"): if not (p.get(k) is None or p[k] in names): return False if p.get("question") not in QUESTIONS or p.get("choice") not in names: return False host = p.get("host") if not isinstance(host, dict) or not (_whole(host.get("job_bytes")) and host["job_bytes"].value >= 0): return False providers = host.get("providers") if not isinstance(providers, list) or not all(isinstance(x, str) for x in providers): return False return isinstance(p.get("why"), str) and isinstance(p.get("stable"), dict) and isinstance(p.get("kept"), dict) def _request_names(request): """§8.7: provider: for the provider a request names, else method: for a method other than auto, else None.""" provider = request.get("provider") if isinstance(provider, str): return "provider:" + provider m = request.get("method") if isinstance(m, str) and m != "auto": return "method:" + m return None def _question(request): """§8.7: the question a job asks, from its request alone.""" def listed(k): v = request.get(k) return isinstance(v, list) and len(v) > 0 observables, amplitudes = listed("observables"), listed("amplitudes") shots = request.get("shots") if isinstance(shots, Num) and shots.literal_whole() and not shots.text.startswith("-") and int(shots.text) <= 2 ** 64 - 1: shots = int(shots.text) else: shots = 1024 if not observables and not amplitudes else 0 if request.get("noise") is not None: return "noise" if shots > 0: return "counts" if observables and not amplitudes: return "expectations" return "amplitudes" def _fabric(request): f = request.get("fabric") if f is None or f == "auto": return "free" return "cpu" if f == "cpu" else "placed" def _auto(routes, request, named): """§8.7: the route auto picks, from the routes.""" if named is not None: return None if _fabric(request) == "placed": for r in routes: if r["route"] == "method:statevector" and r["kind"] == "local" and r["price"] is not None: return "method:statevector" return None best = None for i, r in enumerate(routes): if r["kind"] == "local" and r["price"] is not None and r.get("auto_rank") is not None: key = (r["auto_rank"].value, i) if best is None or key < best[0]: best = (key, r["route"]) return best[1] if best else None def _gate(r, contract, request, named, wanted, from_contract, job_bytes): """§8.7's rules, in order: the first that applies, or None.""" name, price = r["route"], r["price"] is_provider = name.startswith("provider:") # 1 if named is not None and name != named: return "not_named" # 2 if named is None: fabric = _fabric(request) if fabric == "cpu" and name in _GPU_METHODS: return "fabric" if fabric == "placed" and name != "method:statevector": return "fabric" cls = r["class"] # 3 if cls == "unknown" and price is None: return "cannot" # 4 if wanted is not None: if not meets(wanted, cls) or (from_contract and wanted == "simulated" and r.get("approximate") is True): return "class" elif is_provider: return "class" # 5 if price is None: return "cannot" # 6 memory = _value_of(price["memory_bytes"]) if memory is not None and memory > job_bytes: return "memory" # 7 if is_provider and contract["providers"] != "allowed": return "providers" # 8 if contract["deadline"] is not None: seconds = _value_of(price["time"].get("seconds")) if seconds is None: return "deadline_unknown" if seconds > contract["deadline"]: return "deadline" # 9 money = price["money"] if is_provider and money.get("free") is not True: ceiling = contract["max_cost"] if ceiling is None: if named != name: return "cost_no_ceiling" else: amount, currency = money.get("amount"), money.get("currency") if not (_is_decimal(amount) and isinstance(currency, str)): return "cost_unknown" if currency != ceiling["currency"]: return "cost_currency" if fractions.Fraction(amount) > fractions.Fraction(ceiling["amount"]): return "cost" if money.get("at_least") is True: return "cost_at_least" # 10 if contract["joules"] is not None: joules = _value_of(price["energy"].get("joules")) if not isinstance(price["energy"].get("watch"), str): return "energy_unwatched" if joules is not None and joules > contract["joules"]: return "energy" return None def _order_key(r): """§8.7's order: money (free, then an amount in decimals by value, then any other), time to the nearest millisecond (halves up; a stated one first), local first, memory, name.""" p = r["price"] money = p["money"] if money.get("free") is True: cost = (0, fractions.Fraction(0)) elif _is_decimal(money.get("amount")): cost = (1, fractions.Fraction(money["amount"])) else: cost = (2, fractions.Fraction(0)) seconds = _value_of(p["time"].get("seconds")) time = (1, 0) if seconds is None else (0, math.floor(seconds * 1000.0 + 0.5)) return (cost, time, 0 if r["kind"] == "local" else 1, _value_of(p["memory_bytes"]) or 0.0, r["route"].encode("utf-8")) def _picked(routes, auto, contract, passes): """§8.7's choice, of the routes the rules let through.""" let_through = [r for r in routes if passes(r)] if contract["exactness"] is None and auto is not None: for r in let_through: if r["route"] == auto: return r["route"] return min(let_through, key=_order_key)["route"] if let_through else None def _stable_holds(p, routes, contract): """§8.7 stable: routes, digest and choice as the routes give them.""" stable = p["stable"] covered = [r for r in routes if r["kind"] == "local" and r["host_dependent"] is False] facts = [] for r in covered: price = r["price"] if isinstance(r["price"], dict) else {} facts.append({"route": r["route"], "class": r["class"], "seconds": _member(price, "time", "seconds"), "memory_bytes": price.get("memory_bytes"), "work": price.get("work")}) digest = blake3(text_of({"job_bytes": p["host"]["job_bytes"], "routes": facts}, True).encode("utf-8")).hex() names = [r["route"] for r in covered] others = all(_member(r, "rejected", "code") in ("not_named", "fabric", "class") for r in routes if r["host_dependent"] is not False) choice = p["choice"] in names and others and contract["providers"] != "allowed" and contract["joules"] is None return stable.get("routes") == names and stable.get("digest") == digest and stable.get("choice") is choice def _kept_holds(p, contract, result): """§8.7 kept: exactly a member for each the contract gives, each of exactly its members, each as its table says.""" kept = p["kept"] asked = (("deadline", contract["deadline"] is not None), ("energy", contract["joules"] is not None), ("cost", contract["max_cost"] is not None)) if len(kept) != sum(1 for _, a in asked if a) or any((n in kept) != a for n, a in asked): return False if contract["deadline"] is not None: d = contract["deadline"] k = kept["deadline"] if not _same_keys(k, ("seconds", "elapsed_ms", "kept")): return False e = k.get("elapsed_ms") if not (e is None or (_whole(e) and e.value >= 0)): return False want = None if e is None else e.value <= d * 1000.0 if _value_of(k.get("seconds")) != d or k.get("kept") is not want: return False # A method's time is its result's, where its result states one. if result.get("method") != "provider" and "elapsed_ms" in result and _value_of(result.get("elapsed_ms")) != _value_of(e): return False if contract["joules"] is not None: j = contract["joules"] k = kept["energy"] if not _same_keys(k, ("max_joules", "joules", "kept")): return False micro = _value_of(_member(result, "energy", "joules_micro")) stopped = _value_of(_member(result, "stopped", "joules")) x = stopped if stopped is not None else (None if micro is None else micro / 1e6) want = False if stopped is not None else (None if x is None else x <= j) if _value_of(k.get("max_joules")) != j or _value_of(k.get("joules")) != x or k.get("kept") is not want: return False if contract["max_cost"] is not None: ceiling = contract["max_cost"] k = kept["cost"] if not _same_keys(k, ("max_cost", "charged", "kept")) or not _same_keys(k.get("max_cost"), ("amount", "currency")): return False charged = _member(result, "cost", "charged") free = _member(result, "cost", "free") no_free_member = not (isinstance(result.get("cost"), dict) and "free" in result["cost"]) if charged is not None: amount = _member(charged, "amount") if _is_decimal(amount) and _member(charged, "currency") == ceiling["currency"]: held = fractions.Fraction(amount) <= fractions.Fraction(ceiling["amount"]) else: held = None elif no_free_member or free is True: held = True else: held = None charged_same = k.get("charged") is None if charged is None else _same(k.get("charged"), charged) if (_member(k, "max_cost", "amount") != ceiling["amount"] or _member(k, "max_cost", "currency") != ceiling["currency"] or k.get("kept") is not held or not charged_same): return False return True def _list_count(v): """§8.7: a count of a list, a whole number written as one from 0 to 2^64 − 1, or 0.""" if isinstance(v, Num) and v.literal_whole() and not v.text.startswith("-"): n = int(v.text) return n if n <= 2 ** 64 - 1 else 0 return 0 def split_mad(n): """§8.7: E|2B − n| for B binomial (n, 1/2), in doubles in the order written.""" if n == 0: return 0.0 j = (n - 1) // 2 if j < 4096: m = 1.0 for i in range(j): m = m * float(2 * i + 3) / float(2 * i + 2) return m jj = float(j) c = (1.0 - 1.0 / (8.0 * jj) + 1.0 / (128.0 * jj * jj) + 5.0 / (1024.0 * jj * jj * jj)) / math.sqrt(math.pi * jj) return (2.0 * jj + 1.0) * c def shadow_distance(a, b, shots): """§8.7 distance: the numerator, the denominator, the total variation, the Hellinger fidelity and the sampling bound, in order, or None when it cannot be taken.""" if not (isinstance(a, dict) and isinstance(b, dict)) or shots <= 0: return None s = float(shots) numerator, root, bound, total = 0, 0.0, 0.0, 0 for k in sorted(set(a) | set(b), key=lambda k: k.encode("utf-8")): x, y = _list_count(a.get(k)), _list_count(b.get(k)) # Sums of whole numbers exact; each product and quotient a double's. numerator += abs(x - y) root += math.sqrt(float(x) * float(y)) total += x + y bound += split_mad(x + y) if total > 2 * shots: return None denominator = 2 * shots return (numerator, denominator, float(numerator) / float(denominator), root * root / (s * s), min(1.0, 0.5 * bound / s)) def _whole_value(v): """A number whose value is whole and at least 0, as a whole number (at most 2^64 − 1).""" if isinstance(v, Num) and float(v.value).is_integer() and v.value >= 0: return min(int(v.value), 2 ** 64 - 1) return None def _shadow_count(v): """§8.7: a count of a shadow's list, a whole number written as one from 1 to 2^53 − 1.""" if isinstance(v, Num) and v.literal_whole() and not v.text.startswith("-"): n = int(v.text) if 1 <= n <= MAX_SAFE: return n return None def _shadow_budget(contract, provider_seconds): d = contract["deadline"] if d is None: return 300.0 if provider_seconds is None: return d return max(d - provider_seconds, 0.0) def _shadow_plan_holds(request, contract, p, result): """§8.7: the reasoning's shadow.""" plan = p.get("shadow") if not isinstance(plan, dict) or "route" not in plan: return False route = plan["route"] if route is None: return (plan.get("code") in ("budget", "memory", "none") and isinstance(plan.get("why"), str) and ("tried" not in plan or isinstance(plan["tried"], list))) if not (isinstance(route, str) and route.startswith("method:") and len(route) > 7): return False chosen = next((r for r in p["routes"] if r["route"] == p["choice"]), None) provider_seconds = _value_of(_member(chosen, "price", "time", "seconds")) if chosen else None budget = _shadow_budget(contract, provider_seconds) req = plan.get("request") price = plan.get("price") listed = next((r for r in p["routes"] if r["route"] == route), None) if listed is None or plan.get("class") != listed["class"]: return False if not (plan.get("class") in LADDER and _value_of(plan.get("budget_seconds")) == budget and _price_form(price, True) and _value_of(_member(price, "time", "seconds")) is not None and _value_of(price["time"]["seconds"]) <= budget): return False if not _same_keys(req, ("qasm", "shots", "seed", "method")): return False seed = request.get("seed") seed = int(seed.text) if isinstance(seed, Num) and seed.literal_whole() and not seed.text.startswith("-") else 1 seed = seed if seed <= 2 ** 64 - 1 else 1 want_seed = (seed + 2 ** 32) % 2 ** 53 given = req.get("seed") return (_same(req.get("qasm"), request.get("qasm")) and isinstance(req.get("qasm"), str) and _same(req.get("shots"), result.get("shots")) and isinstance(given, Num) and given.literal_whole() and not given.text.startswith("-") and int(given.text) == want_seed and req.get("method") == route[len("method:"):]) def _shadow_holds(request, contract, p, result): """§8.7 shadow: its plan, its form, what its plan and the job imply, its distance its counts'.""" s, plan = result["shadow"], p.get("shadow") if not isinstance(s, dict) or not _shadow_plan_holds(request, contract, p, result): return False ran = s.get("ran") if ran is False: if not (isinstance(s.get("code"), str) and isinstance(s.get("why"), str)): return False return s["code"] == plan.get("code") if plan.get("route") is None else s["code"] == "failed" if ran is not True or plan.get("route") is None: return False shots = _whole_value(result.get("shots")) counts = s.get("counts") if not isinstance(counts, dict) or shots is None: return False listed = [_shadow_count(v) for v in counts.values()] omitted = _whole_value(s.get("omitted_shots")) if any(n is None for n in listed) or omitted is None or sum(listed) + omitted != shots: return False if not (_whole(s.get("distinct_outcomes")) and s["distinct_outcomes"].value >= 0): return False # Its outcomes are a counts' form: of 0 and 1, as wide as the job's where the # provider's counts name one; with none omitted, as said. theirs = result.get("counts") width = len(next(iter(theirs), "")) if isinstance(theirs, dict) and theirs else len(next(iter(counts), "")) if any(len(k) != width or set(k) - {"0", "1"} for k in counts) or (omitted == 0 and s["distinct_outcomes"].value != len(counts)): return False d = s.get("distance") if not isinstance(d, dict): return False # By value: an omitted_shots of 0 however it is written. theirs, ours = _value_of(result.get("omitted_shots")), _value_of(s.get("omitted_shots")) if d.get("computed") is False: if not isinstance(d.get("why"), str) or (theirs == 0 and ours == 0): return False elif d.get("computed") is True: if "distance-unchecked" not in PLANTS: # PLANT want = shadow_distance(result.get("counts"), counts, shots) if want is None or theirs != 0 or ours != 0: return False for k, v in zip(("numerator", "denominator", "total_variation", "hellinger_fidelity", "sampling_tvd_bound"), want): if _value_of(d.get(k)) != float(v): return False else: return False cls = _member(s, "accuracy", "class") if not _class_of_method(plan["route"][len("method:"):], cls): return False return (s.get("route") == plan["route"] and isinstance(cls, str) and meets(plan.get("class"), cls) and _same(s.get("request"), plan.get("request")) and _same(s.get("shots"), result.get("shots"))) STOPPED_MEMBERS = ("method", "qubits", "gates", "accuracy", "stopped", "elapsed_ms", "planner", "energy", "engine", "schema", "receipt") def _stopped_holds(contract, result): """§8.7: a run stopped at its ceiling, on a contract that gives one, a reading at or past it, on a method's run, with no answer.""" s = result["stopped"] j = contract["joules"] if not _same_keys(s, ("at", "joules", "max_joules", "elapsed_ms", "read")) or j is None: return False x = _value_of(s.get("joules")) return (s.get("at") == "max_joules" and _value_of(s.get("max_joules")) == j and x is not None and x >= j and _whole(s.get("elapsed_ms")) and s["elapsed_ms"].value >= 0 and isinstance(s.get("read"), str) and result.get("method") != "provider" and _member(result, "accuracy", "class") == "none" and all(k in STOPPED_MEMBERS for k in result) and (_value_of(_member(result, "energy", "joules_micro")) is None or _value_of(_member(result, "energy", "joules_micro")) >= x * 1e6 - 1.0) and _value_of(result.get("elapsed_ms")) == _value_of(s.get("elapsed_ms"))) def check_contract(request, result, reasons): # §8.7. A job with no contract carries neither a reasoning nor a shadow. given = request.get("contract") planner = result.get("planner") if given is None: if "planner" in result: reasons.add("planner_form") if "shadow" in result: reasons.add("shadow") if "stopped" in result: reasons.add("stopped") return contract = read_contract(given) if contract is None: reasons.add("contract_form") return if not _planner_form(planner): reasons.add("planner_form") return if request.get("provider") is not None and contract["providers"] != "allowed": reasons.add("contract_provider") routes = planner["routes"] # The providers the host brought are its provider routes, in their order. brought = [r["route"][len("provider:"):] for r in routes if r["kind"] == "provider"] if planner["host"]["providers"] != brought: reasons.add("planner_form") return # What the job names, the question it asks and what auto picks: from the request # and the routes, never from what the reasoning says of itself. named = _request_names(request) if named is None and request.get("target") is not None: stated = planner.get("named") named = stated if isinstance(stated, str) and stated.startswith("method:") else None question = _question(request) ranks_ok = True for r in routes: if r["kind"] == "local" and r["route"][len("method:"):] in AUTO_RANKS: want = AUTO_RANKS[r["route"][len("method:"):]][QUESTIONS.index(question)] if _value_of(r["auto_rank"]) != want: ranks_ok = False auto = _auto(routes, request, named) class_of = dict((r["route"], r["class"]) for r in routes) if contract["exactness"] is not None: wanted, source = contract["exactness"], "contract" elif named is not None: wanted, source = class_of.get(named), "named" elif auto is not None: wanted, source = class_of.get(auto), "auto" else: wanted, source = None, None if (planner.get("named") != named or planner.get("question") != question or not ranks_ok or planner.get("auto") != auto or planner.get("wanted") != wanted or planner["wanted_from"] != source): reasons.add("planner_form") return job_bytes = planner["host"]["job_bytes"].value from_contract = source == "contract" def gate(r): return _gate(r, contract, request, named, wanted, from_contract, job_bytes) broken = False chosen = [r["route"] for r in routes if r["outcome"] == "chosen"] if "route-unchecked" not in PLANTS: # PLANT for r in routes: if _member(r, "rejected", "code") != gate(r) or not _states_itself(r, request): broken = True if len(chosen) != 1 or chosen[0] != planner["choice"]: broken = True if broken: reasons.add("planner_route") if result.get("method") == "provider": name = _member(result, "provider", "name") ran = "provider:" + name if isinstance(name, str) else None else: m = result.get("method") ran = "method:" + m if isinstance(m, str) else None if "choice-unchecked" not in PLANTS: # PLANT if (_picked(routes, auto, contract, lambda r: gate(r) is None) != planner["choice"] or ran != planner["choice"] or not _ran_as_routed(routes, planner["choice"], result)): reasons.add("planner_choice") if not _stable_holds(planner, routes, contract): reasons.add("planner_stable") if not _kept_holds(planner, contract, result): reasons.add("planner_kept") cls = _member(result, "accuracy", "class") short = wanted is not None and (not meets(wanted, cls) or (from_contract and wanted == "simulated" and _member(result, "accuracy", "approximate") is True)) # A method's result has a class its method has. method = result.get("method") if "stopped" in result: if not _stopped_holds(contract, result): reasons.add("stopped") elif short or (isinstance(method, str) and method != "provider" and not _class_of_method(method, cls)): reasons.add("contract_class") # Under a contract a provider's result is of the current form. if result.get("method") == "provider" and ("counts_source" not in result or "execution" not in result): reasons.add("contract_form") is_provider = planner["choice"].startswith("provider:") if is_provider != ("shadow" in result) or is_provider != ("shadow" in planner) or (is_provider and not _shadow_holds(request, contract, planner, result)): reasons.add("shadow") def contract_statement(result): """§8.7: what a verifier states of a job under a contract.""" p = result.get("planner") return { "choice": _plain(_member(p, "choice")), "wanted": _plain(_member(p, "wanted")), "class": _plain(_member(result, "accuracy", "class")), "stable_choice": _plain(_member(p, "stable", "choice")), "kept": _plain(_member(p, "kept")), "shadow_ran": _plain(_member(result, "shadow", "ran")), "shadow_total_variation": _plain(_member(result, "shadow", "distance", "total_variation")), } # ============================================ 7. a wasmQ job (quantum-wasmq §6.5) # # Written from wai/extensions/quantum-wasmq.md §6.5 (with §2.2, §6.2 and §6.4 for the # lists it names), by a reader who had not seen the reference. §8.4's `wasmq_form` # holds a job to those rules when its result's format is wai.quantum.wasmq.result/1. # Brought to §6.5 as it now stands (rule 18's call that stopped being one of the calls # made; the statement of outcome, problems and notes) by a reader who had not seen it; # and again for rules 20 to 35 (the ties between members: fuel, instances, the envelope's # size, the calls' count, the least charge and the transcript of a run where no call # returned) and rules 6, 8, 12, 14 and 18 as they now read, from the text alone. # # §6.5: a member is *present* when its object names it, whatever its value, null among # them ("has no fault", "has a callout", "may have fault" read so). Every test of a # member here is `name in obj` or `_get`, never `obj.get(name) is None`, so a member # that is null is there; the statement's notes read the body's members the same way. WASMQ_FORMAT = "wai.quantum.wasmq.result/1" WASMQ_PROFILE = "wai.quantum.wasmq/1" # §6.4: the result's energy, the one sentence it gives. WASMQ_ENERGY = "the runner reads no energy meter; fuel is the profile's measure of work" # §6.5 rule 9 (§6.4): the result's members; it may also have `fault`. WASMQ_RESULT_MEMBERS = frozenset(( "format", "profile", "status", "method", "qubits", "shots", "shots_run", "seed", "counts", "callouts", "fuel", "modules", "transcript_blake3", "accuracy", "energy", "receipt")) # §6.2: the reasons a fault names. WASMQ_FAULT_REASONS = ( "fuel_exhausted", "stack_exhausted", "unreachable", "memory_out_of_bounds", "table_out_of_bounds", "indirect_call_null", "indirect_call_type", "integer_divide_by_zero", "integer_overflow", "invalid_conversion_to_integer", "bad_result") WASMQ_PHASES = ("seed", "prior", "init", "call") WASMQ_RULES = 35 # quantum-wasmq §11: the second version. Its result's format decides that a job is held to # §11.6, which reads rules 4, 8, 11, 12 and 30 with the second version's names and adds 36. WASMQ2_FORMAT = "wai.quantum.wasmq.result/2" WASMQ2_PROFILE = "wai.quantum.wasmq/2" WASMQ2_METHODS = ("stabilizer", "exact") # §11.1 WASMQ2_EXACT_MAX_QUBITS = 26 # §11.3, rule 12 # §11.5: a reading's class (energy-measurement §2); an estimate is no reading. WASMQ2_READINGS = ("CalibratedInstrument", "OnChipCounter", "HwShunt") WASMQ2_FLOOR_UJ_PPM = 288676 # §11.5: energy-measurement §2.3's floor WASMQ2_RULES = 36 WASMQ_PROBLEMS_SHOWN = 64 # §6.5: the first 64 problems, then how many more _ABSENT = object() # a member not present: equal to nothing def _count(v): """§6.5: a number whose value is a whole number from 0 to 2^53 − 1, however it is written (1, 1.0 and 1e0 are one count; -0 is 0).""" return isinstance(v, Num) and v.value.is_integer() and 0 <= v.value <= MAX_SAFE def _count_in(v, low, high): return _count(v) and low <= v.value <= high def _n(v): """A count's value as an exact integer, so that a sum or a product is exact.""" return int(v.value) def _or_zero(v): """§6.5: a bound read "(0 when that is not a count)".""" return _n(v) if _count(v) else 0 def _text_is(v, *options): return isinstance(v, str) and v in options def _exactly(v, names): """§6.5: every one named and no other; a value that is not an object has none.""" return isinstance(v, dict) and set(v) == set(names) def _obj(v): """§6.5: a map that is not an object is read as an empty one, after its own rule.""" return v if isinstance(v, dict) else {} def _arr(v): """§6.5: a list that is not an array is read as an empty one, after its own rule.""" return v if isinstance(v, list) else [] def _get(v, name): """§6.5: a member's value when it is present (null among them), else _ABSENT.""" return v[name] if isinstance(v, dict) and name in v else _ABSENT def is_wasmq(result): """§6.5, §11.6: a result whose format is wai.quantum.wasmq.result/1, or /2, is a wasmQ job's.""" return _text_is(result.get("format"), WASMQ_FORMAT, WASMQ2_FORMAT) def wasmq_version(result): """§11.6: "What a job's result format is decides which version's rules hold it".""" return 2 if _text_is(result.get("format"), WASMQ2_FORMAT) else 1 def _figure_holds(f): """§11.5: a figure is the unmetered form, exactly {"unmetered": why} with why a string that is not empty; or a reading: joules_micro a count of at least 1, energy_provenance a reading's class, and energy_uncertainty whose relative_ppm and window_us are counts of at least 1 and whose relative_ppm times joules_micro is at least 288 676. A reading may say more.""" if not isinstance(f, dict): return False if "unmetered" in f: return len(f) == 1 and isinstance(f["unmetered"], str) and f["unmetered"] != "" joules = _get(f, "joules_micro") if not (_count(joules) and _n(joules) >= 1): return False if not _text_is(_get(f, "energy_provenance"), *WASMQ2_READINGS): return False u = _obj(_get(f, "energy_uncertainty")) ppm, window = _get(u, "relative_ppm"), _get(u, "window_us") if not (_count(ppm) and _n(ppm) >= 1 and _count(window) and _n(window) >= 1): return False return _n(joules) * _n(ppm) >= WASMQ2_FLOOR_UJ_PPM def wasmq_broken(request, result): """§6.5: the numbers of the rules a wasmQ job breaks; none when it keeps them all. C is the request's wasmq, run C's run, r the result and F r's fuel. What decides is what is sealed (the request, and the result less its receipt), but for rule 9's `receipt` member and rule 10's canon, which name the receipt itself.""" broken = set() def rule(number, holds): if not holds: broken.add(number) r = result body = dict((k, v) for k, v in r.items() if k != "receipt") c_given = _get(request, "wasmq") c = _obj(c_given) program_given, run_given = _get(c, "program"), _get(c, "run") program, run = _obj(program_given), _obj(run_given) budgets_given = _get(run, "fuel") budgets = _obj(budgets_given) # §6.5: "The budget per_call, per_job or per_instance is that member of run's fuel." per_call, per_job, per_instance = (_get(budgets, k) for k in ("per_call", "per_job", "per_instance")) modules_given, callouts_given = _get(c, "modules"), _get(c, "callouts") modules, callouts = _arr(modules_given), _arr(callouts_given) externs = [_get(co, "extern") for co in callouts] f_given = _get(r, "fuel") f = _obj(f_given) shots, shots_run, status = _get(r, "shots"), _get(r, "shots_run"), _get(r, "status") # 1. No number in the request, or in the result less its receipt, has a magnitude # past 2^53 − 1 (its value, the double it reads as). rule(1, all(abs(n.value) <= MAX_SAFE for part in (request, body) for n in _numbers(part))) # 2. The request: exactly wasmq and envelope_blake3, the latter a digest. rule(2, _exactly(request, ("wasmq", "envelope_blake3")) and _lower_hex(request["envelope_blake3"], 64)) # 3. C, its program, run and run's fuel: exactly the members §2.2 gives. rule(3, _exactly(c_given, ("profile", "program", "modules", "callouts", "run")) and _exactly(program_given, ("blake3", "bytes", "inputs")) and _exactly(run_given, ("shots", "seed", "method", "state", "fuel")) and _exactly(budgets_given, ("per_call", "per_job", "per_instance"))) # 4. C's profile: wai.quantum.wasmq/1, or under the second version /2 (§11.6). version = wasmq_version(r) rule(4, _text_is(_get(c, "profile"), WASMQ_PROFILE if version == 1 else WASMQ2_PROFILE)) # 5. The program: a digest; 1 to 2^20 bytes; inputs an object of whole numbers. # SPEC-GAP: [W2] "at most 2^53 − 1 in size": a magnitude; an input may be negative # (an int[k] input), so it is no count. inputs = _get(program, "inputs") rule(5, _lower_hex(_get(program, "blake3"), 64) and _count_in(_get(program, "bytes"), 1, 2 ** 20) and isinstance(inputs, dict) and all(isinstance(v, Num) and v.value.is_integer() and abs(v.value) <= MAX_SAFE for v in inputs.values())) # 6. The modules: a non-empty array, each module and each prior of its form, and the # modules' bytes that are counts adding up to at most 2^19. A module's bytes is a count # of at least 1 (the sum bounds each from above); a prior's bytes is a count, which # rule 31 bounds, not this rule. def prior_holds(p): return (_exactly(p, ("name", "blake3", "bytes")) and isinstance(p["name"], str) and _lower_hex(p["blake3"], 64) and _count(p["bytes"])) def module_holds(m): return (_exactly(m, ("name", "blake3", "bytes", "priors")) and isinstance(m["name"], str) and _lower_hex(m["blake3"], 64) and _count(m["bytes"]) and _n(m["bytes"]) >= 1 and isinstance(m["priors"], list) and all(prior_holds(p) for p in m["priors"])) sizes = [_get(m, "bytes") for m in modules] rule(6, isinstance(modules_given, list) and len(modules) > 0 and all(module_holds(m) for m in modules) and sum(_n(b) for b in sizes if _count(b)) <= 2 ** 19) # 7. The callouts: a non-empty array, each of its form, its module a count less than # the number of modules; no extern twice; every module's index named by a callout. def callout_holds(co): return (_exactly(co, ("extern", "module", "export")) and isinstance(co["extern"], str) and isinstance(co["export"], str) and _count(co["module"]) and _n(co["module"]) < len(modules)) named = set(_n(_get(co, "module")) for co in callouts if _count(_get(co, "module"))) extern_texts = [e for e in externs if isinstance(e, str)] rule(7, isinstance(callouts_given, list) and len(callouts) > 0 and all(callout_holds(co) for co in callouts) and len(set(extern_texts)) == len(extern_texts) and all(i in named for i in range(len(modules)))) # 8. run: shots 1 to 2^20, a seed, the method, the state, and each budget a count, # per_call and per_instance each at most 2^39 (rule 30 holds per_job to less). # §11.6: under the second version run's method is stabilizer or exact. methods = ("stabilizer",) if version == 1 else WASMQ2_METHODS rule(8, _count_in(_get(run, "shots"), 1, 2 ** 20) and _count(_get(run, "seed")) and _text_is(_get(run, "method"), *methods) and _text_is(_get(run, "state"), "shot", "job") and _count(per_job) and _count_in(per_call, 0, 2 ** 39) and _count_in(per_instance, 0, 2 ** 39)) # 9. r: exactly §6.4's members, and may have fault. rule(9, set(r) - {"fault"} == WASMQ_RESULT_MEMBERS) # 10. The receipt is an object whose canon is rfc8785. §6.5: "Only what is sealed (the # request, and the result less its receipt) and the form of its seal decide it": a # receipt that is not an object, or of the first form, breaks it. rule(10, _text_is(_get(_get(r, "receipt"), "canon"), "rfc8785")) # 11. r's constants, and its method, shots and seed equal to run's (numbers by value). # §11.6: under the second version, format and profile /2, the accuracy §11.4 gives # run's method (bit-exact for exact, exact for stabilizer), and nothing of the energy, # which rule 36 holds. # SPEC-GAP: [W23] "its accuracy the one §11.4 gives its method": read as run's method, # which the same rule holds r's to (where they differ the rule fails either way); when # it is neither of §11.1's methods, §11.4 gives no accuracy, and rule 8 says why: the # accuracy is then held to nothing. run_method = _get(run, "method") exact = version == 2 and _text_is(run_method, "exact") if version == 1: constants = (_text_is(_get(r, "format"), WASMQ_FORMAT) and _text_is(_get(r, "profile"), WASMQ_PROFILE) and _same(_get(r, "accuracy"), {"class": "exact"}) and _same(_get(r, "energy"), {"unmetered": WASMQ_ENERGY})) else: accuracy = {"class": "bit-exact" if exact else "exact"} constants = (_text_is(_get(r, "format"), WASMQ2_FORMAT) and _text_is(_get(r, "profile"), WASMQ2_PROFILE) and (not _text_is(run_method, *WASMQ2_METHODS) or _same(_get(r, "accuracy"), accuracy))) rule(11, constants and all(_same(_get(r, k), _get(run, k)) for k in ("method", "shots", "seed"))) # 12. r's qubits a count from 1 to 2^15 (a program declares a qubit at least); its # transcript_blake3 a digest. # §11.6: when the method is exact, at most 26 qubits. rule(12, _count_in(_get(r, "qubits"), 1, 2 ** 15) and _lower_hex(_get(r, "transcript_blake3"), 64) and not (exact and _count(_get(r, "qubits")) and _n(_get(r, "qubits")) > WASMQ2_EXACT_MAX_QUBITS)) # 13. F: exactly its four members; its budget run's fuel; used at most per_job. used, instances = _get(f, "used"), _get(f, "instances") rule(13, _exactly(f_given, ("used", "instances", "budget", "callouts")) and _same(_get(f, "budget"), budgets_given) and _count(used) and _n(used) <= _or_zero(per_job)) # 14. F's callouts: an object; each member named by an extern of C's callouts, with # exactly calls (at least 1), fuel and max (at most per_call and at most its own fuel), # and fuel a count: rule 20, not this rule, bounds it by its calls and their max. f_callouts_given = _get(f, "callouts") f_callouts = _obj(f_callouts_given) extern_set = set(extern_texts) # a list here would make this quadratic def entry_holds(name, e): return (name in extern_set and _exactly(e, ("calls", "fuel", "max")) and _count(e["calls"]) and _n(e["calls"]) >= 1 and _count(e["max"]) and _n(e["max"]) <= _or_zero(per_call) and _count(e["fuel"]) and _n(e["max"]) <= _n(e["fuel"])) rule(14, isinstance(f_callouts_given, dict) and all(entry_holds(k, v) for k, v in f_callouts.items())) # 15. F's instances and its callouts' fuel add up to used; their calls to r's callouts. # SPEC-GAP: [W5] "Each of them is a count": every number the rule names, F's # instances and used, r's callouts, and each member's fuel and calls. fuels = [_get(e, "fuel") for e in f_callouts.values()] calls = [_get(e, "calls") for e in f_callouts.values()] r_callouts = _get(r, "callouts") rule(15, all(_count(x) for x in [instances, used, r_callouts] + fuels + calls) and _n(instances) + sum(_n(x) for x in fuels) == _n(used) and sum(_n(x) for x in calls) == _n(r_callouts)) # 16. r's modules: as many as C's, each exactly name and blake3, equal to C's at its index. r_modules_given = _get(r, "modules") def r_module_holds(i, m): return (_exactly(m, ("name", "blake3")) and _lower_hex(m["blake3"], 64) and _same(m["name"], _get(modules[i], "name")) and _same(m["blake3"], _get(modules[i], "blake3"))) rule(16, isinstance(r_modules_given, list) and len(r_modules_given) == len(modules) and all(r_module_holds(i, m) for i, m in enumerate(r_modules_given))) # 17. F's instances at most M × S × per_instance: S, over C's modules, 2 and its priors; # M 1 for state job "whatever the status", for any other state shots_run, and 1 more # when status is fault. s = sum(2 + len(_arr(_get(m, "priors"))) for m in modules) if _text_is(_get(run, "state"), "job"): m_factor = 1 else: m_factor = _or_zero(shots_run) + (1 if _text_is(status, "fault") else 0) rule(17, _count(instances) and _n(instances) <= m_factor * s * _or_zero(per_instance)) # 18. status ok: no fault, and every shot run; status fault: the fault of §6.2's form. if _text_is(status, "ok"): rule(18, "fault" not in r and _count(shots_run) and _count(shots) and _n(shots_run) == _n(shots)) elif _text_is(status, "fault"): rule(18, _fault_holds(_get(r, "fault"), shots, shots_run, modules, externs, f_callouts, per_instance)) else: rule(18, False) # any other status breaks the form # 19. r's counts: an object of outcomes of 0 and 1 (the empty name among them), all of # one length, each at least 1, adding up to shots_run. counts_given = _get(r, "counts") counts = _obj(counts_given) rule(19, isinstance(counts_given, dict) and all(_OUTCOME.fullmatch(k) for k in counts) and len(set(len(k) for k in counts)) <= 1 and all(_count(v) and _n(v) >= 1 for v in counts.values()) and _count(shots_run) and sum(_n(v) for v in counts.values()) == _n(shots_run)) # Rules 20 to 35 tie members to each other. In them *the fault* is r's fault when r's # status is fault and that is an object, and there is none otherwise; a rule about the # fault holds when there is none. A *call's fault* is one whose phase is call, a # *lifecycle fault* "one that has a phase other than call": a phase of null is present # (§6.5), so a lifecycle fault's; a fault that names no phase is neither. fault_given = _get(r, "fault") fault = fault_given if _text_is(status, "fault") and isinstance(fault_given, dict) else None phase, reason = _get(fault, "phase"), _get(fault, "reason") fault_fuel, fault_shot = _get(fault, "fuel"), _get(fault, "shot") call_fault = fault is not None and _text_is(phase, "call") lifecycle_fault = fault is not None and phase is not _ABSENT and not _text_is(phase, "call") state_job = _text_is(_get(run, "state"), "job") # 20. Each member of F's callouts: s 1 when the fault is a call's fault whose callout is # that member's name, else 0; e the fault's fuel when s is 1 (0 when it is no count), # else 0. T, its fuel less e (the fuel of its calls that returned), is not less than 0, # and is from k to k × max, k its calls less s (0 when that is below 0); and when max # is more than e, T is at least max + k − 1. calls, fuel and max are counts. def returned_holds(name, member): stopped = 1 if call_fault and _same(_get(fault, "callout"), name) else 0 calls, fuel, top = _get(member, "calls"), _get(member, "fuel"), _get(member, "max") if not (_count(calls) and _count(fuel) and _count(top)): return False stopped_fuel = _or_zero(fault_fuel) if stopped else 0 # e returned = _n(fuel) - stopped_fuel # T returning = max(_n(calls) - stopped, 0) # k return (returned >= 0 and returning <= returned <= returning * _n(top) and (_n(top) <= stopped_fuel or returned >= _n(top) + returning - 1)) rule(20, all(returned_holds(name, member) for name, member in f_callouts.items())) # 21. F's instances is a count of at least W × P + E, the least making the instances took # outside a stopped call. # P: over every prior of every one of C's modules, 3 and the prior's bytes (0 when no # count), and 1 more when the fault is a lifecycle fault in phase seed or init. # W: r's shots_run (0 when no count), 1 more when there is a call's fault, and with # state job that or 1, whichever is less. # E: when the fault is a lifecycle fault, the same sum of 3 and the bytes over the priors # of each module before the one it names (the first of C's modules with that name), # and, in phase init, over that module's own; 0 otherwise, and when no module has it. # SPEC-GAP: [W19] "E ... the same sum, of 3 and its bytes": read as the sum over priors # alone, without P's 1 more for a fault in seed or init, as "of 3 and its bytes" says. def passing_of(priors): return sum(3 + _or_zero(_get(p, "bytes")) for p in priors) all_priors = [p for m in modules for p in _arr(_get(m, "priors"))] passing = passing_of(all_priors) + (1 if lifecycle_fault and _text_is(phase, "seed", "init") else 0) made_whole = _or_zero(shots_run) + (1 if call_fault else 0) if state_job: made_whole = min(made_whole, 1) stopped_priors = [] # the priors E counts: those the stopped set passed whole if lifecycle_fault: named = next((i for i, m in enumerate(modules) if _same(_get(fault, "module"), _get(m, "name"))), None) if named is not None: upto = named + 1 if _text_is(phase, "init") else named stopped_priors = [p for m in modules[:upto] for p in _arr(_get(m, "priors"))] least_instances = made_whole * passing + passing_of(stopped_priors) rule(21, _count(instances) and _n(instances) >= least_instances) # 22. A call's fault's module equals the name of C's module whose index is the module of # each of C's callouts whose extern is the fault's callout (rule 7 allows one); it # fails when there is no such callout, or no such module. def callout_module_name(co): index = _get(co, "module") if _count(index) and _n(index) < len(modules): return _get(modules[_n(index)], "name") return _ABSENT # no such module: equal to nothing stopped_in = ([co for co in callouts if _same(_get(co, "extern"), _get(fault, "callout"))] if call_fault else []) rule(22, not call_fault or (len(stopped_in) > 0 and all(_same(_get(fault, "module"), callout_module_name(co)) for co in stopped_in))) # 23. A fault whose phase is prior has as its module the name of one of C's modules # whose priors is not empty (a priors that is no array read as an empty one). rule(23, fault is None or not _text_is(phase, "prior") or any(len(_arr(_get(m, "priors"))) > 0 and _same(_get(fault, "module"), _get(m, "name")) for m in modules)) # 24. A fault whose reason is bad_result has the phase call or prior. rule(24, fault is None or not _text_is(reason, "bad_result") or _text_is(phase, "call", "prior")) # 25. A lifecycle fault's fuel is a count, and F's instances (a count) is at least it # added to rule 21's W × P + E. rule(25, not lifecycle_fault or (_count(fault_fuel) and _count(instances) and _n(instances) >= _n(fault_fuel) + least_instances)) # 26. When run's state is job, a lifecycle fault's shot is the count 0. first_shot = _count_in(fault_shot, 0, 0) rule(26, not (lifecycle_fault and state_job) or first_shot) # 27. A lifecycle fault whose shot is the count 0 comes with r's callouts the count 0. rule(27, not (lifecycle_fault and first_shot) or _count_in(r_callouts, 0, 0)) # 28. A fuel_exhausted fault used its whole limit: with budget call its fuel is a count # equal to the budget per_call, with instance to per_instance (each 0 when no count); # with run, F's used is a count equal to the budget per_job (a count), and the fault's # fuel is a count, less than its own limit: per_call in a call's fault, per_instance in # a lifecycle fault, each read as 0 when it is not a count ("a fault with no phase has # no limit here, and breaks rule 18"). # SPEC-GAP: [W18] the rule says what the whole limit is for the budgets call, instance # and run only; a fault of fuel_exhausted with no budget, a budget of null or of # another value (rule 18 then fails) is held to nothing here. budget = _get(fault, "budget") if fault is None or not _text_is(reason, "fuel_exhausted"): whole_limit = True elif _text_is(budget, "call"): whole_limit = _count(fault_fuel) and _n(fault_fuel) == _or_zero(per_call) elif _text_is(budget, "instance"): whole_limit = _count(fault_fuel) and _n(fault_fuel) == _or_zero(per_instance) elif _text_is(budget, "run"): # Its own limit: per_call in a call's fault, per_instance in a lifecycle fault, each # 0 when no count (a budget of null among them); a fault with no phase has none. # (`limited` is a flag of its own: a budget of null reads as Python's None.) limited = call_fault or lifecycle_fault own_limit = per_call if call_fault else per_instance whole_limit = (_count(used) and _count(per_job) and _n(used) == _n(per_job) and _count(fault_fuel) and (not limited or _n(fault_fuel) < _or_zero(own_limit))) else: whole_limit = True rule(28, whole_limit) # 29. When r's counts has a name, the longest, in characters (Unicode code points), is at # most 2^20 long, and run's shots (0 when no count) times that length at most 2^28 # (counts read as an empty object when it is no object, after rule 19 has failed). longest = max((len(name) for name in counts), default=None) rule(29, longest is None or (longest <= 2 ** 20 and _or_zero(_get(run, "shots")) * longest <= 2 ** 28)) # 30. The part of a run's work a receipt shows, at most 2^42: # S × 2·n·w + I × Σ (4096 × (1 + 2p) + b) + 131072 × Σ b + 4097 × K + 8 × the budget # per_job, S run's shots, n r's qubits, w ⌈n/32⌉ or 1 when that is 0, I 1 for state job # and S otherwise, each sum over C's modules (p its number of priors, b its bytes), K # r's callouts; every number that is not a count read as 0. shots_asked = _or_zero(_get(run, "shots")) qubits = _or_zero(_get(r, "qubits")) tableau_words = -(-qubits // 32) or 1 instances_counted = 1 if state_job else shots_asked code = [_or_zero(_get(m, "bytes")) for m in modules] instance_work = sum(4096 * (1 + 2 * len(_arr(_get(m, "priors")))) + b for m, b in zip(modules, code)) # §11.6, §11.7: under the exact method a shot's fresh state is S x 2·2^n, not S x 2·n·w # (2·2^64 stands for a state of more qubits: either is past any bound, and neither is # made here). if exact: fresh = shots_asked * (2 << min(qubits, 64)) else: fresh = shots_asked * 2 * qubits * tableau_words work = (fresh + instances_counted * instance_work + 131072 * sum(code) + 4097 * _or_zero(r_callouts) + 8 * _or_zero(per_job)) rule(30, work <= 2 ** 42) # 31. The envelope the contract names is at most 2^27 bytes: 20 bytes of magic and # lengths; the manifest, §2.1's members in order with no space, 192 bytes and the # decimal digits of r's qubits and of run's shots and seed (each 0 when no count); # C in RFC 8785 form; and the frames (the program's bytes, each module's and each # prior's, each 0 when no count), added. # SPEC-GAP: [W20] "C in RFC 8785 form": a request with no wasmq member (rule 2 then # fails) has no C, read as no bytes; any other value of wasmq, an object or not, is # written in its canonical text (§8.2) and counted in its UTF-8 bytes. manifest = 192 + sum(len(str(_or_zero(v))) for v in (_get(r, "qubits"), _get(run, "shots"), _get(run, "seed"))) contract = 0 if c_given is _ABSENT else len(text_of(c_given, True).encode("utf-8")) frames = (_or_zero(_get(program, "bytes")) + sum(code) + sum(_or_zero(_get(p, "bytes")) for p in all_priors)) rule(31, 20 + manifest + contract + frames <= 2 ** 27) # 32. r's callouts is at most 2^21 × H (each 0 when no count), H r's shots_run and 1 more # when there is a call's fault: the shots that ran steps. ran_steps = _or_zero(shots_run) + (1 if call_fault else 0) rule(32, _or_zero(r_callouts) <= 2 ** 21 * ran_steps) # 33. Each prior passed whole fits one lifecycle call's limit: 3 and its bytes (0 when no # count) at most the budget per_instance (0 when no count), for every prior of every # one of C's modules when W (rule 21) is at least 1, and for each prior E counts # otherwise. passed_whole = all_priors if made_whole >= 1 else stopped_priors rule(33, all(3 + _or_zero(_get(p, "bytes")) <= _or_zero(per_instance) for p in passed_whole)) # 34. A fault's fuel, when it is a count, is at least what its reason shows was charged: # 1 for every reason but fuel_exhausted, 2 for bad_result, 788 for stack_exhausted. # SPEC-GAP: [W21] "1 for every reason but fuel_exhausted": read of the reason the fault # has, whatever its value; one §6.2 does not name, or one not a string (null among # them), shows 1 (rule 18 fails for it). A fault that has no reason member shows # nothing, and is held to no least here (rule 18 fails for it). if fault is None or reason is _ABSENT or _text_is(reason, "fuel_exhausted"): least_charged = 0 elif _text_is(reason, "bad_result"): least_charged = 2 elif _text_is(reason, "stack_exhausted"): least_charged = 788 else: least_charged = 1 rule(34, not _count(fault_fuel) or _n(fault_fuel) >= least_charged) # 35. When no call returned (r's callouts the count 0, or the count 1 with a call's # fault), r's transcript_blake3 is BLAKE3 over the bytes wai:wasmq-transcript\x01 and, # when there is a fault, the bytes fault, its shot (u64), its reason's UTF-8 bytes and # its fuel (u64), little-endian (shot and fuel 0 when no count, the reason no bytes # when it is no string). # SPEC-GAP: [W22] "\x01" read as the one byte 0x01 (as §8.2 names its domain byte), not # the four characters; "the bytes fault" as the five ASCII bytes of the word. if _count(r_callouts) and (_n(r_callouts) == 0 or (_n(r_callouts) == 1 and call_fault)): transcript = b"wai:wasmq-transcript\x01" if fault is not None: transcript += (b"fault" + struct.pack("= _n(fuel) def check_wasmq(request, result, reasons): """§8.4 wasmq_form: a wasmQ job's request or result breaks a rule of quantum-wasmq §6.5. Returns the numbers of the rules it breaks, none for another job.""" if "wasmq-unchecked" in PLANTS: # PLANT: skip the wasmQ rules return [] broken = wasmq_broken(request, result) if is_wasmq(result) else [] if broken: reasons.add("wasmq_form") return broken # §6.5: "problems, each rule the job breaks, in words": one entry a rule, in this file's # words (another verifier's are its own; the words are no part of the verdict). WASMQ_RULE_WORDS = { 1: "a number in the request, or in the result less its receipt, has a magnitude past 2^53 - 1", 2: "the request is not exactly wasmq and envelope_blake3, envelope_blake3 a digest", 3: "the contract, its program, its run or run's fuel has not exactly the members §2.2 gives", 4: "the contract's profile is not wai.quantum.wasmq/1", 5: "the program's blake3, bytes or inputs break their form", 6: "the contract's modules break their form, or their bytes add up past 2^19", 7: "the contract's callouts break their form, name an extern twice, or leave a module unnamed", 8: "run's shots, seed, method, state or a budget breaks its form", 9: "the result has not exactly the members of §6.4 (and may have fault)", 10: "the receipt is not an object whose canon is rfc8785", 11: "the result's format, profile, accuracy or energy is not §6.4's, or its method, shots " "or seed is not run's", 12: "the result's qubits is not a count from 1 to 2^15, or its transcript_blake3 is no digest", 13: "the result's fuel has not exactly used, instances, budget and callouts, its budget is " "not run's fuel, or used is past the budget per_job", 14: "a member of fuel's callouts is no extern of the contract, or its calls, fuel and max " "break their form or bounds", 15: "fuel's instances and its callouts' fuel do not add up to used, or their calls to the " "result's callouts", 16: "the result's modules are not the contract's, name and blake3 at each index", 17: "fuel's instances are past M x S x the budget per_instance", 19: "the counts are not an object of outcomes of 0 and 1, of one length, each at least 1, " "adding up to shots_run", 20: "a member of fuel's callouts has a fuel of its returned calls (its fuel less the " "stopped call's) below 0, outside 1 to max for each call that returned, or below max " "and 1 for each other when the most was a returned call's", 21: "fuel's instances are no count of at least W x P + E, the least that making the " "instances took outside a stopped call", 22: "a call's fault names another module than its callout's, or no callout or module of " "the contract", 23: "a fault in phase prior names no module of the contract that has a prior", 24: "a fault of bad_result is in another phase than call or prior", 25: "a lifecycle fault's fuel is no count, or with rule 21's W x P + E is past fuel's " "instances", 26: "with state job, a lifecycle fault's shot is not the count 0", 27: "a lifecycle fault at shot 0 comes with the result's callouts other than the count 0", 28: "a fault of fuel_exhausted did not use its whole limit (call, instance, or the run's " "per_job used up below the call's own)", 29: "the counts' longest outcome is past 2^20 bits, or run's shots times its length past 2^28", 30: "the work the receipt shows (tableaux, instances, compiling, calls, per_job) is past " "2^42", 31: "the envelope the contract names (magic and lengths, manifest, contract, frames) is " "past 2^27 bytes", 32: "the result's callouts are past 2^21 for each shot that ran steps", 33: "a prior passed whole does not fit within per_instance (3 and its bytes)", 34: "a fault's fuel is below what its reason shows was charged (1, 2 for bad_result, 788 " "for stack_exhausted)", 35: "no call returned, and the transcript_blake3 is not the one such a run gives", } # The words of the rules the second version reads with its own names (§11.6), and its 36th. WASMQ2_RULE_WORDS = { 4: "the contract's profile is not wai.quantum.wasmq/2", 8: "run's shots, seed, method (stabilizer or exact), state or a budget breaks its form", 11: "the result's format or profile is not the second version's, its accuracy not the one its " "method has, or its method, shots or seed is not run's", 12: "the result's qubits is not a count from 1 to 2^15 (at most 26 by the exact method), or " "its transcript_blake3 is no digest", 30: "the work the receipt shows (fresh states, instances, compiling, calls, per_job) is past " "2^42", 36: "the energy is not exactly run and callouts, each a figure: the unmetered form with its " "reason, or a reading of at least 1 microjoule with its class and its uncertainty, for " "each callout the run called and no other", } def _rule_words(number, result): if wasmq_version(result) == 2 and number in WASMQ2_RULE_WORDS: return "rule %d: %s" % (number, WASMQ2_RULE_WORDS[number]) if number != 18: return "rule %d: %s" % (number, WASMQ_RULE_WORDS[number]) status = _get(result, "status") if _text_is(status, "ok"): words = "the status is ok, but the result has a fault, or not every shot ran" elif _text_is(status, "fault"): words = ("the status is fault, but the fault breaks §6.2's form or disagrees with the run " "(its reason, shot, phase, module, fuel, callout or budget)") else: words = "the status is neither ok nor fault" return "rule 18: " + words def _first_and_more(items, shown=WASMQ_PROBLEMS_SHOWN): """§6.5: the first 64, and then how many more.""" # SPEC-GAP: [W11] "the first 64 of them and then how many more": how many more is # one more entry of the list, "and N more", not a member of its own. One entry a # rule gives at most 35, so a job never reaches it; the self-test calls it alone. items = list(items) if len(items) <= shown: return items return items[:shown] + ["and %d more" % (len(items) - shown)] def _words(v): """A value of the body or the result, written for a note.""" return json.dumps(_plain(v), ensure_ascii=False, separators=(",", ":")) def wasmq_notes(job, result): """quantum-wasmq §6.4, §6.5: where the body's unsealed members differ from what is sealed, or are missing. A note is no part of the verdict.""" # SPEC-GAP: [W12] §6.4: the body's status is done when the result's status is ok and # fault otherwise, so the body's status is held to that word, "otherwise" taken as # it stands (a result's status that is absent, or no string, carries fault); its # method to the result's method, as JSON values are equal (a result with no method # leaves any method in the body differing). A body member that is null is present # (§6.5), so it differs; only one the body does not name is missing. notes = [] status, method = _get(result, "status"), _get(result, "method") carried = "done" if _text_is(status, "ok") else "fault" for name, wanted, sealed in (("status", carried, status), ("method", method, method)): said = _get(job, name) if said is _ABSENT: notes.append("the host's unsealed %s is missing" % name) elif not _same(said, wanted): note = "the host's unsealed %s says %s; the sealed result %s" % ( name, _words(said), "has none" if sealed is _ABSENT else "says " + _words(sealed)) if name == "status" and not _same(sealed, wanted): # the sealed word is not the body's (ok carries done): say which it carries note += ", and the body carries %s for that" % _words(wanted) notes.append(note) # SPEC-GAP: [W13] §6.4: "or any other member of the body": nothing sealed answers it, # so each member beyond the four is noted whatever its value, in the canonical # text's order of names. for name in sorted(set(job) - {"request", "result", "status", "method"}, key=_utf16): notes.append("the body's member %s is the host's word; nothing seals it" % _words(name)) return notes def wasmq_statement(job, result, broken): """quantum-wasmq §6.5, §8.4: what a verifier states beside a wasmQ job's verdict: outcome, problems and notes. None of it changes the verdict.""" # SPEC-GAP: [W10] "outcome, the sealed result's status": given as that string, and # as null when the status is absent or no string, so that the outcome is a word. status = _get(result, "status") return { "outcome": status if isinstance(status, str) else None, "problems": _first_and_more(_rule_words(n, result) for n in broken), "notes": wasmq_notes(job, result), } # ============================= 7b. an energy-landscape job (quantum-landscape §5.4) # # Written from wai/extensions/quantum-landscape.md §5.4, whose rules are numbered. §8.4's # `landscape_form` holds a job to them when its result's protocol or schema is # wai.quantum.landscape/1. Every rule is read from the job alone: no program is read here. # # A job whose result's protocol or schema is wai.quantum.landscape/2 is of the second # version, and is held to the same rules as wai/extensions/quantum-landscape-2.md §5.4 # changes them: rules 2, 3, 6, 8 and 10 there, written here from that list. LANDSCAPE = "wai.quantum.landscape/1" L_SETTLE = "wai.quantum.landscape/settle" L_SAMPLE = "wai.quantum.landscape/sample" L_KERNELS = (L_SETTLE, L_SAMPLE) LANDSCAPE_2 = "wai.quantum.landscape/2" L2_SETTLE = "wai.quantum.landscape2/settle" L2_SAMPLE = "wai.quantum.landscape2/sample" L_PARITIES = ("reference", "bit-exact", "statistical", "uncertified") L_VERDICTS = ("solved", "missed", "failed", "unchecked") L_MODES = ("settle", "quench", "sample") L_CAPACITY = ("cells", "couplings", "table_entries", "uncertain_span", "sweeps", "chains_per_call") L_SIDE = ("field", "field_bound", "cost") L_FLOOR = (("cells", 32), ("couplings", 992), ("table_entries", 31), ("uncertain_span", 61), ("sweeps", 5000)) L_FLOOR_SIDE = (("field", 40), ("field_bound", 41), ("cost", 8)) L_PROVIDER = "wai.quantum.provider/1" _L_DIGITS = re.compile(r"[0-9]+") _L_DECIMAL = re.compile(r"[0-9]+(?:\.[0-9]+)?") _L_ENERGY = re.compile(r"-?[0-9]+") _L_HEX16 = re.compile(r"[0-9a-f]{16}") _L_HEX64 = re.compile(r"[0-9a-f]{64}") _L_NAME = re.compile(r"[a-z0-9._-]+") _INF = float("inf") def is_landscape(result): """§5.4: a job whose result's protocol or schema is wai.quantum.landscape/1, or, for the second version (quantum-landscape-2 §5.4), wai.quantum.landscape/2.""" return result.get("protocol") in (LANDSCAPE, LANDSCAPE_2) or result.get("schema") in (LANDSCAPE, LANDSCAPE_2) def is_landscape_2(result): """quantum-landscape-2 §5.4: a job is of the second version when its result's protocol or schema is wai.quantum.landscape/2.""" return result.get("protocol") == LANDSCAPE_2 or result.get("schema") == LANDSCAPE_2 def _l_given(o, name): """§5.4: in the request, a member given as null is absent.""" return o.get(name) if isinstance(o, dict) else None def _l_value(v): return v.value if isinstance(v, Num) else None def _l_whole_in(v, low, high): return isinstance(v, Num) and v.value.is_integer() and low <= v.value <= high def _l_text(v): return isinstance(v, str) and v != "" def _l_exactly(v, names): return isinstance(v, dict) and set(v) == set(names) def _l_seed(v): """Rule 3: a whole number from 0 to 2^64 - 1, or a string of 1 to 20 ASCII digits whose value is at most that; its value, or None.""" if isinstance(v, str): if len(v) <= 20 and _L_DIGITS.fullmatch(v) and int(v) <= 2 ** 64 - 1: return int(v) return None if isinstance(v, Num) and v.value.is_integer() and 0 <= v.value < 2 ** 64: return int(v.value) return None def _l_temperature(v): """Rule 3: a number, or a string [0-9]+(.[0-9]+)? of at most 40 characters, whose value is 0, or finite and at least 0.000001; its value, or None.""" if isinstance(v, str): if len(v) > 40 or not _L_DECIMAL.fullmatch(v): return None t = float(v) elif isinstance(v, Num): t = v.value else: return None return t if math.isfinite(t) and (t == 0 or t >= 1e-6) else None def _l_request_seed(req): """The seed a request asks for: 1 where it gives none; None for one of no form.""" v = _l_given(req, "seed") return 1 if v is None else _l_seed(v) def _l_cells(v): """Rule 10: a state of 1 to 4096 characters, each +, - or 0, as cells; or None.""" if not isinstance(v, str) or not 1 <= len(v) <= 4096 or any(c not in "+-0" for c in v): return None return [1 if c == "+" else -1 if c == "-" else 0 for c in v] def _l_fnv(cells): """§3.2: FNV-1a over the cells, each the byte s + 1.""" h = 0xCBF29CE484222325 for c in cells: h ^= c + 1 h = (h * 0x100000001B3) & 0xFFFFFFFFFFFFFFFF return "%016x" % h def landscape_op(r): """Rule 4: the answer's operation, read from its members.""" if "lines" in r: return "replay" if "rows" in r and "target" in r: return "compare" if "rows" in r: return "sweep" if "state" in r: return "run" return None def _l_stated(m, single): """Each kernel the member names with the parity it states for it, where the parity is a string ("" for a kernel that is not one).""" if not isinstance(m, dict): return [] if single: p, k = m.get("parity"), m.get("kernel") return [(k if isinstance(k, str) else "", p)] if isinstance(p, str) else [] out = [] ks = m.get("kernels") for k in ks if isinstance(ks, list) else []: p = k.get("parity") if isinstance(k, dict) else None if isinstance(p, str): kk = k.get("kernel") out.append((kk if isinstance(kk, str) else "", p)) return out def landscape_broken(request, r): """quantum-landscape §5.4: the numbers of the rules a landscape job breaks.""" broken = set() def rule(n, holds): if not holds: broken.add(n) # The version's names: its protocol and its two kernels (quantum-landscape-2 §3, §4). second = is_landscape_2(r) name, settle, sample = (LANDSCAPE_2, L2_SETTLE, L2_SAMPLE) if second else (LANDSCAPE, L_SETTLE, L_SAMPLE) kernels = (settle, sample) rec = r.get("receipt") rule(1, isinstance(rec, dict) and rec.get("canon") == "rfc8785") eng = r.get("engine") # Rule 2, and the second version's: the protocol and the schema are each the version's name. rule(2, r.get("protocol") == name and r.get("schema") == name and isinstance(eng, dict) and eng.get("name") == "wai-quantum" and isinstance(eng.get("version"), str)) if not isinstance(request, dict): rule(3, False) else: prog = request.get("program") rule(3, isinstance(prog, str) and len(prog.encode("utf-8")) <= 4194304) g = lambda k: _l_given(request, k) rule(3, g("seed") is None or _l_seed(g("seed")) is not None) rule(3, g("temperature") is None or _l_temperature(g("temperature")) is not None) rule(3, g("seeds") is None or _l_whole_in(g("seeds"), 1, 100000)) ts = g("temperatures") rule(3, ts is None or (isinstance(ts, list) and 1 <= len(ts) <= 64 and all(_l_temperature(t) is not None for t in ts))) rule(3, g("parity") is None or g("parity") in ("bit-exact", "statistical")) if second: # The second version's rule 3: the request's protocol is its name, present. rule(3, g("protocol") == LANDSCAPE_2) else: rule(3, g("protocol") is None or g("protocol") == LANDSCAPE) rule(3, g("provider") is None or _l_text(g("provider"))) rule(5, _l_text(r.get("label"))) _l_provider_rule(request, r, rule) op = landscape_op(r) if op is None: rule(4, False) return broken single = op in ("run", "replay") m = r.get("member") pairs = _l_stated(m, single) mid = m.get("id") if isinstance(m, dict) else None reference = mid == "cpu:reference" # Rule 6. required = ("id", "class", "kernel", "parity") if single else ("id", "class", "kernels") rule(6, isinstance(m, dict) and all(k in m for k in required) and all(k in required or k in ("capacity", "demoted") for k in m)) cls = m.get("class") if isinstance(m, dict) else None cls = cls if cls in ("cpu", "gpu", "fpga") else None rule(6, cls is not None) rule(6, cls is not None and isinstance(mid, str) and len(mid) <= 64 and mid.startswith(cls + ":") and bool(_L_NAME.fullmatch(mid[len(cls) + 1:]))) if single: rule(6, m.get("kernel") in kernels if isinstance(m, dict) else False) rule(6, m.get("parity") in L_PARITIES if isinstance(m, dict) else False) else: ks = m.get("kernels") if isinstance(m, dict) else None rule(6, isinstance(ks, list) and len(ks) > 0 and all(_l_exactly(k, ("kernel", "parity")) and k["kernel"] in kernels and k["parity"] in L_PARITIES for k in ks) and len(set(k["kernel"] for k in ks)) == len(ks)) if op == "compare": rule(6, isinstance(ks, list) and len(ks) == 1 and isinstance(ks[0], dict) and ks[0].get("kernel") == sample) rule(6, all((p == "reference") == reference for _, p in pairs)) rule(6, all(p != "statistical" or k == sample for k, p in pairs)) # The plant landscape2-unchecked holds a second-version job to its names only. strict_2 = second and "landscape2-unchecked" not in PLANTS if strict_2: # The second version's rule 6: no parity is statistical. rule(6, all(p != "statistical" for _, p in pairs)) # Rule 7. if isinstance(m, dict) and "demoted" in m: rule(7, isinstance(m["demoted"], str) and all(p == "uncertified" for _, p in pairs)) # Rule 8. The second version's: the member states no capacity. if strict_2: rule(8, not (isinstance(m, dict) and "capacity" in m)) if isinstance(m, dict) and "capacity" in m: c = m["capacity"] rule(8, not reference) number = lambda v: _l_whole_in(v, 0, _INF) side = lambda v: isinstance(v, dict) and len(v) > 0 and all(k in L_SIDE and number(x) for k, x in v.items()) rule(8, isinstance(c, dict) and len(c) > 0 and all(side(x) if k in ("at_zero", "above_zero") else (k in L_CAPACITY and number(x)) for k, x in c.items())) if any(p in ("bit-exact", "statistical") for _, p in pairs): def under(o, floor): return any(isinstance(o, dict) and isinstance(o.get(k), Num) and o[k].value < f for k, f in floor) sub = lambda k: c.get(k) if isinstance(c, dict) else None rule(8, not under(c, L_FLOOR) and not under(sub("at_zero"), L_FLOOR_SIDE) and not under(sub("above_zero"), L_FLOOR_SIDE)) # Rule 9. bit_exact = any(p == "bit-exact" for _, p in pairs) if "audit" in r: a = r["audit"] rule(9, bit_exact and isinstance(a, dict) and isinstance(a.get("checked"), list) and len(a["checked"]) > 0) else: rule(9, not bit_exact) if "refusals" in r: f = r["refusals"] rule(9, isinstance(f, list) and len(f) > 0 and all(isinstance(x, dict) and isinstance(x.get("member"), str) and isinstance(x.get("why"), str) for x in f)) if op == "run": _l_run_rule(request, r, m, rule, name, settle, sample) elif op == "replay": _l_replay_rule(request, r, rule) else: _l_rows_rule(op, r, pairs, rule, settle, sample) return broken def _l_run_rule(request, r, m, rule, name=LANDSCAPE, settle=L_SETTLE, sample=L_SAMPLE): """Rule 10: a run, of the version whose protocol is `name` and whose kernels are `settle` and `sample`.""" prog = request.get("program") if isinstance(request, dict) else None rule(10, isinstance(prog, str) and r.get("program_digest") == blake3(prog.encode("utf-8")).hex()) seed = r.get("seed") want = _l_request_seed(request) rule(10, want is not None and isinstance(seed, str) and str(want) == seed) mode = r.get("mode") if r.get("mode") in L_MODES else None kernel = m.get("kernel") if isinstance(m, dict) else None rule(10, mode is not None and kernel == (settle if mode == "settle" else sample)) t = _l_value(r.get("temperature")) rule(10, t is not None and mode is not None and (t > 0 if mode == "sample" else t == 0)) asked = _l_given(request, "temperature") if asked is not None: tv = _l_temperature(asked) rule(10, tv is not None and t is not None and tv == t) restarts = _l_value(r.get("restarts")) if _l_whole_in(r.get("restarts"), 1, 100000) else None rule(10, restarts is not None and (mode != "settle" or restarts == 1)) sweeps = _l_value(r.get("sweeps")) if _l_whole_in(r.get("sweeps"), 1, 1000000) else None rule(10, sweeps is not None) cells = _l_cells(r.get("state")) rule(10, cells is not None and _l_value(r.get("variables")) == len(cells)) e = _l_value(r.get("energy")) energy = e if e is not None and e.is_integer() and -2 ** 63 <= e < 2 ** 63 else None rule(10, energy is not None) rule(10, cells is not None and r.get("state_hash") == _l_fnv(cells)) replay = None if (isinstance(seed, str) and _L_DIGITS.fullmatch(seed) and int(seed) <= 2 ** 64 - 1 and isinstance(prog, str) and mode is not None and (mode != "sample" or t is not None) and restarts is not None and sweeps is not None and cells is not None and energy is not None): pb = prog.encode("utf-8") # The digest begins with the version's own name and a zero byte (quantum-landscape-2 §3). data = name.encode() + b"\0" + struct.pack("= 0 else: form = False rule(10, form and metered_holds) else: rule(10, isinstance(j, dict) and j.get("kind") == "priced" and metered_holds) verdict = r.get("verdict") if r.get("verdict") in L_VERDICTS else None rule(10, verdict is not None) truth = r.get("truth", _ABSENT) lowest = _l_value(truth.get("lowest")) if isinstance(truth, dict) else None rule(10, truth is None or (isinstance(truth, dict) and lowest is not None)) reached = r.get("reached", _ABSENT) if not isinstance(truth, dict) and reached is None: consistent = verdict != "missed" elif isinstance(truth, dict) and isinstance(reached, bool): consistent = (reached == (energy is not None and lowest is not None and e == lowest)) and verdict != "unchecked" \ and (verdict in ("solved", "failed") if reached else verdict in ("missed", "failed")) else: consistent = False rule(10, consistent) def _l_replay_rule(request, r, rule): """Rule 11: a replay.""" given = _l_given(request, "seeds") want = 20 if given is None else (given.value if _l_whole_in(given, 1, 100000) else None) rule(11, want is not None and _l_value(r.get("seeds")) == want) first = _l_request_seed(request) text = r.get("lines") holds = False if isinstance(text, str) and want is not None and first is not None and text.endswith("\n"): lines = text[:-1].split("\n") holds = len(lines) == int(want) width = None for k, line in enumerate(lines if holds else []): f = line.split(" ") if len(f) != 7: holds = False break cells = _l_cells(f[2]) if cells is not None and width is None: width = len(cells) if not (f[0] == str((first + k) % 2 ** 64) and _L_HEX16.fullmatch(f[1]) and cells is not None and len(cells) == width and _L_ENERGY.fullmatch(f[3]) and f[4] in L_VERDICTS and _L_DIGITS.fullmatch(f[5]) and _L_HEX16.fullmatch(f[6])): holds = False break rule(11, holds) def _l_rows_rule(op, r, pairs, rule, settle=L_SETTLE, sample=L_SAMPLE): """Rule 12: a sweep or a comparison, of the version whose kernels are `settle` and `sample`.""" rows = r.get("rows") ok = isinstance(rows, list) and len(rows) > 0 and all(isinstance(x, dict) for x in rows) rule(12, ok) def parity_of(k): for kk, p in pairs: if kk == k: return p return None def row_holds(row): if op == "sweep": k = row.get("kernel") if isinstance(row.get("kernel"), str) else None p = parity_of(k) if k is not None else None mode = row.get("mode") if row.get("mode") in L_MODES else None return p is not None and row.get("parity") == p and mode is not None and (mode == "settle") == (k == settle) c = row.get("classical") if c is True: return "parity" in row and row["parity"] is None if c is False: p = parity_of(sample) return p is not None and row.get("parity") == p return False rule(12, ok and all(row_holds(x) for x in rows)) if op == "compare": rule(12, "target" in r and _l_whole_in(r["target"], -_INF, _INF)) def _l_provider_rule(request, r, rule): """Rule 13: a provider's job.""" named = _l_given(request, "provider") added = [k in r for k in ("provider", "job", "cost")] if named is None: rule(13, not any(added)) return rule(13, all(added)) p = r.get("provider") prov = p.get("provenance") if isinstance(p, dict) else None provenance = isinstance(prov, str) and (prov == "silicon" or prov.split(":", 1)[0] in ("simulator", "emulator")) rule(13, _l_exactly(p, ("name", "kind", "protocol", "device", "provenance", "describe")) and isinstance(named, str) and p.get("name") == named and p.get("kind") in ("http", "process") and p.get("protocol") == L_PROVIDER and _l_text(p.get("device")) and provenance and isinstance(p.get("describe"), str) and bool(_L_HEX64.fullmatch(p["describe"]))) j = r.get("job") rule(13, _l_exactly(j, ("id", "polls")) and _l_text(j.get("id")) and _l_whole_in(j.get("polls"), 0, _INF)) c = r.get("cost") x = c.get("charged", _ABSENT) if isinstance(c, dict) else _ABSENT charged = x is None or (_l_exactly(x, ("amount", "currency")) and isinstance(x["amount"], str) and bool(_L_DECIMAL.fullmatch(x["amount"])) and _l_text(x["currency"])) free = c.get("free") if isinstance(c, dict) else None confirmed = c.get("confirmed") if isinstance(c, dict) else None rule(13, _l_exactly(c, ("free", "estimate", "charged", "confirmed")) and isinstance(free, bool) and isinstance(confirmed, bool) and confirmed != free and isinstance(c.get("estimate"), dict) and charged) def check_landscape(request, result, reasons): """§8.4 landscape_form: an energy-landscape job that breaks a rule of quantum-landscape §5.4.""" if not is_landscape(result) or "landscape-unchecked" in PLANTS: return None broken = landscape_broken(request, result) if broken: reasons.add("landscape_form") return broken # ===================================================================== 8. a job def _verdict(reasons, key=None, form=None, time=None): v = {"valid": not reasons, "reasons": sorted(reasons), "key": key, "form": form} if form is not None: # §8.2: what a receipt of its form seals of its time. if time is None: v["time"] = {"sealed": False} else: v["time"] = {"sealed": True, "issued_ms": time[0], "not_after_ms": time[1]} return v def judge(raw): """One job's text to its verdict (without "file"), held to the reader's trust list and time where HOLD gives them (§8.8).""" try: job = read_json(raw) except Unreadable: return _verdict(["unreadable"]) if not (isinstance(job, dict) and isinstance(job.get("request"), dict) and isinstance(job.get("result"), dict)): return _verdict(["not_a_job"]) # §8.2: only request and result are sealed; nothing else in the body decides (a # wasmQ job's statement reads the rest for its notes, quantum-wasmq §6.5). request, result = job["request"], job["result"] if result.get("format") == SET_FORMAT: return hold(judge_set(request, result)) return hold(judge_job(request, result, job)) # ============================================== 8a. whose key, and when (§8.8) KEYS_FORMAT = "wai.quantum.receipt-keys/1" TRANSITION_FORMAT = "wai.quantum.key-transition/1" TRANSITION_DOMAIN = b"wai:quantum-key-transition\x01" class TrustRefused(Exception): """A trust list that does not read, or is not of its form (§8.8): it judges nothing.""" def transition_holds(t): """§8.8: a rotation's statement, signed by both the keys it names: each signature Ed25519, strictly (§8.2), over BLAKE3(the domain ‖ the statement's canonical text).""" if not isinstance(t, dict): return False st = t.get("statement") if not isinstance(st, dict) or st.get("format") != TRANSITION_FORMAT: return False digest = blake3(TRANSITION_DOMAIN + text_of(st, True).encode("utf-8")) for who, signed in (("retiring", "retiring_signature"), ("successor", "successor_signature")): if not _lower_hex(st.get(who), 64) or not _lower_hex(t.get(signed), 128): return False key = bytes.fromhex(st[who]) a = key_point(key) if a is None or not signature_holds(a, key, digest, bytes.fromhex(t[signed])): return False return True def read_trust(raw): """§8.8: a trust list from its text, read strictly (§8.2) and held to its form, as {key hex: (not_before_ms, not_after_ms, revoked_from_ms)}, each a whole number or None. Raises TrustRefused, with the reason, for anything else.""" try: doc = read_json(raw) except Unreadable as e: raise TrustRefused("it does not read (%s)" % e.detail) if not isinstance(doc, dict) or doc.get("format") != KEYS_FORMAT: raise TrustRefused("its format is not %s" % KEYS_FORMAT) if "algorithm" in doc and doc["algorithm"] != "ed25519": raise TrustRefused("its algorithm is not ed25519") if not isinstance(doc.get("keys"), list): raise TrustRefused("it has no `keys` array") keys = {} for i, entry in enumerate(doc["keys"]): key = entry.get("key") if isinstance(entry, dict) else None if not _lower_hex(key, 64): raise TrustRefused("keys[%d].key is not 64 lower-case hex digits" % i) if key in keys: raise TrustRefused("keys[%d]: the key is listed twice" % i) times = [] for name in ("not_before_ms", "not_after_ms", "revoked_from_ms"): v = entry.get(name) if v is not None: v = _ms(v) if v is None: raise TrustRefused("keys[%d].%s is not a whole number of milliseconds, or null" % (i, name)) times.append(v) t = entry.get("transition") if t is not None: st = t.get("statement") if isinstance(t, dict) else None if not (isinstance(st, dict) and st.get("retiring") == key and transition_holds(t)): raise TrustRefused("keys[%d].transition does not name this key as the one retiring, " "signed by both its keys" % i) keys[key] = tuple(times) return keys def held_reasons(key, time, trust, at_ms, skew_ms): """§8.8: the reasons for a receipt of its form that names `key` and seals `time` ((issued_ms, not_after_ms) or None), held to a trust list and a time, each or None.""" reasons = set() issued = None if time is None else time[0] if trust is not None: if key not in trust: reasons.add("key_untrusted") else: not_before, not_after, revoked_from = trust[key] untimed_passes = "untimed-anywhere" in PLANTS # PLANT def at_or_after(limit): # With no time sealed, a receipt can be shown to precede no moment. if limit is None: return False if issued is None: return not untimed_passes if "window-end-inside" in PLANTS: # PLANT return issued > limit return issued >= limit if (not_before is not None and issued is not None and issued < not_before) \ or at_or_after(not_after): reasons.add("key_window") if revoked_from is not None and (issued is None and not untimed_passes or issued is not None and issued >= revoked_from): reasons.add("key_revoked") if at_ms is not None and time is not None: if time[1] is not None and at_ms >= time[1]: reasons.add("expired") if issued > at_ms + skew_ms: reasons.add("issued_later") return reasons def hold(verdict): """§8.8: a job's verdict, its receipt held to what HOLD gives: the reasons that apply added, and what it was held to stated. A verdict with no form (a reason reported alone, or receipt_form) names no key and no time, and is held to nothing.""" trust, at_ms, skew_ms = HOLD["trust"], HOLD["at_ms"], HOLD["skew_ms"] if verdict.get("form") is None or (trust is None and at_ms is None): return verdict t = verdict["time"] time = (t["issued_ms"], t["not_after_ms"]) if t["sealed"] else None reasons = set(verdict["reasons"]) | held_reasons(verdict["key"], time, trust, at_ms, skew_ms) verdict["reasons"] = sorted(reasons) verdict["valid"] = not reasons if trust is not None: if verdict["key"] in trust: b, a, r = trust[verdict["key"]] verdict["trust"] = {"listed": True, "not_before_ms": b, "not_after_ms": a, "revoked_from_ms": r} else: verdict["trust"] = {"listed": False} if at_ms is not None: verdict["checked_at_ms"] = at_ms verdict["skew_ms"] = skew_ms return verdict def judge_job(request, result, job=None): """§8.4: a job's request and result, already read, to its verdict. `job` is the body they were read from: a wasmQ job judged from its body states beside its verdict what quantum-wasmq §6.5 says; a set's item (no body of its own) states nothing.""" provider = result.get("method") == "provider" broken = None if "receipt" not in result: verdict = _verdict(["no_receipt"]) else: reasons = set() body = dict((k, v) for k, v in result.items() if k != "receipt") key, form, time = check_seal(request, result["receipt"], body, reasons) check_inexact(request, body, form, reasons) if provider: check_provider(request, result, reasons) else: check_class(result, False, False, reasons) check_contract(request, result, reasons) # §8.4: a wasmQ job's result is held to wasmq_form whatever its method, and to # the provider rules too when its method is provider. broken = check_wasmq(request, result, reasons) # §8.4: an energy-landscape job's to landscape_form (quantum-landscape §5.4). check_landscape(request, result, reasons) verdict = _verdict(reasons, key, form, time) if provider: verdict["provider"] = provider_statement(result) if "planner" in result: verdict["planner"] = contract_statement(result) # §8.4, quantum-wasmq §6.5: a judged wasmQ job (not no_receipt, nor reported alone # before it) states its outcome, its problems and the notes on its unsealed body. # SPEC-GAP: [W14] a set's item that is a wasmQ job states none: the set's verdict is # one line, the set (format wai.quantum.set/1) is no wasmQ job, and an item's own # reasons are folded into set_item. if broken is not None and job is not None and is_wasmq(result): verdict["wasmq"] = wasmq_statement(job, result, broken) return verdict # ===================================================================== 9. a set (§8.6) SET_FORMAT = "wai.quantum.set/1" _MERKLE_LEAF = b"moq-jwp:merkle-leaf\x01" _MERKLE_NODE = b"moq-jwp:merkle-node\x01" def judge_set(request, result): """§8.6: a set's request and result, already read, to its verdict. The seal is over the request and the head (the result less items and receipt); the provider rules do not apply to a head.""" if "receipt" not in result: return _verdict(["no_receipt"]) reasons = set() head = dict((k, v) for k, v in result.items() if k not in ("items", "receipt")) key, form, time = check_seal(request, result["receipt"], head, reasons) check_inexact(request, head, form, reasons) if "set-seal-only" not in PLANTS: # PLANT: nothing of the items or the root check_set(request, result, reasons) # §8.8: a set is placed in time by its own receipt. return _verdict(reasons, key, form, time) def _item_formed(i, item): """§8.6 set_items, the first sentence: item i's own form. An item is read for its index, request, result, error and path; anything else it holds is unsealed.""" if not isinstance(item, dict): return False index = item.get("index") if not (_whole(index) and index.value == i and isinstance(item.get("request"), dict)): return False # §8.6: exactly one of the members result and error present, whatever its value. if ("result" in item) == ("error" in item): return False if "result" in item and not isinstance(item["result"], dict): return False if "error" in item and not isinstance(item["error"], str): return False path = item.get("path") return isinstance(path, list) and all(_lower_hex(h, 64) for h in path) def _items_given(request, items): """§8.6: whether the items are the ones the request gives.""" programs, sweep = request.get("programs"), request.get("sweep") # null is none base = dict((k, v) for k, v in request.items() if k not in ("programs", "sweep", "dry_run")) # SPEC-GAP: [N42] "neither" read as: neither a programs that is an array nor a # sweep that is an object; "both" as: both members there and not null. A programs # that is no array, or a sweep that is no object, gives no items. if programs is not None and sweep is not None: return not items if isinstance(programs, list): if len(programs) != len(items): return False for program, item in zip(programs, items): wanted = dict(base) if isinstance(program, str): wanted["qasm"] = program elif isinstance(program, dict): wanted.update(program) # each member replacing one of the same name else: # SPEC-GAP: [N43] a program neither a string nor an object gives no item. return False if not _same(item["request"], wanted): return False return True if isinstance(sweep, dict): # SPEC-GAP: [N44] a sweep value that is no non-empty array: the items are not the # ones the request gives, whatever they are. An empty sweep's product is 1. product = 1 for values in sweep.values(): if not (isinstance(values, list) and values): return False product *= len(values) if product > len(items): return False if product != len(items): return False # §8.6: each item's request less qasm is the request less programs, sweep, # dry_run and qasm; its qasm a string (the program written out at its point, # which §8 does not check). base.pop("qasm", None) for item in items: asked = item["request"] if not isinstance(asked.get("qasm"), str): return False if not _same(dict((k, v) for k, v in asked.items() if k != "qasm"), base): return False return True return not items def item_leaf(item): """§8.6: an item's leaf, the canonical form's digest of its request and its result less its receipt, or of its request and {"error": the error}.""" q = text_of(item["request"], True).encode("utf-8") if "result" in item: body = dict((k, v) for k, v in item["result"].items() if k != "receipt") else: body = {"error": item["error"]} return seal_digest(2, q, text_of(body, True).encode("utf-8")) def _leaf_hash(leaf): return blake3(_MERKLE_LEAF + leaf) def _node_hash(left, right): return blake3(_MERKLE_NODE + left + right) def merkle_levels(hashes): """Each level of the tree from the leaves' hashes up; a level of odd length pairs its last hash with itself.""" levels = [list(hashes)] while len(levels[-1]) > 1: level = levels[-1] levels.append([_node_hash(level[j], level[j + 1] if j + 1 < len(level) else level[j]) for j in range(0, len(level), 2)]) return levels def merkle_path(levels, position): """The siblings from a leaf up (the self-test makes paths with it).""" path = [] for level in levels[:-1]: sibling = position + 1 if position % 2 == 0 else position - 1 path.append(level[sibling] if sibling < len(level) else level[position]) position //= 2 return path def _halvings(n): count = 0 while n > 1: n = (n + 1) // 2 count += 1 return count def _root_holds(root, items): """§8.6 set_root: root is the Merkle root of the leaves, and each path leads to it.""" if not _lower_hex(root, 64) or not items: return False # (no items is set_items', and not checked here) hashes = [_leaf_hash(item_leaf(item)) for item in items] want = bytes.fromhex(root) if merkle_levels(hashes)[-1][0] != want: return False depth = _halvings(len(items)) for position, (item, h) in enumerate(zip(items, hashes)): # §8.6: a path of any other length does not lead to the root. if len(item["path"]) != depth: return False at = position for sibling in item["path"]: other = bytes.fromhex(sibling) h = _node_hash(h, other) if at % 2 == 0 else _node_hash(other, h) at //= 2 if h != want: return False return True def check_set(request, result, reasons): """§8.6 set_items, set_item, set_root.""" items = result.get("items") # set_items: a non-empty array of well-formed items; reported so, the next two # are not checked. if not (isinstance(items, list) and items and all(_item_formed(i, it) for i, it in enumerate(items))): reasons.add("set_items") return count = result.get("count") if not (isinstance(count, Num) and count.value == len(items)) or not _items_given(request, items): reasons.add("set_items") if not all(_item_holds(item, result["receipt"]) for item in items): reasons.add("set_item") if not _root_holds(result.get("root"), items): reasons.add("set_root") def _item_holds(item, set_receipt): """§8.6 set_item, for one item.""" if "error" in item: # §8.6: an item with an error: its request writes no whole number its leaf # could not seal, as inexact_number reads one in a canonical receipt, whatever # the set's form, since a leaf is the canonical form's digest. return not writes_inexact(item["request"], "rfc8785") item_result = item["result"] if item_result.get("format") == SET_FORMAT: return False # an item is one job verdict = judge_job(item["request"], item_result) if verdict["reasons"]: return False # §8.6: a valid item's receipt names the set's receipt's `key` member as it # stands; one the set's receipt does not have is another. set_key = set_receipt.get("key") if isinstance(set_receipt, dict) else None return isinstance(set_key, str) and verdict["key"] == set_key def verdict_for(name, raw): try: v = judge(raw) except (RecursionError, MemoryError, Exception) as e: # Never a traceback. This should not happen; §8.4 has no reason for it. sys.stderr.write("receipt_verify: internal error on %s (%s): reported as unreadable\n" % (name, type(e).__name__)) v = {"valid": False, "reasons": ["unreadable"], "key": None, "form": None} out = {"file": name} out.update(v) return out def _read(path): try: with open(path, "rb") as f: return f.read() except (OSError, ValueError, MemoryError): return None def _usage(): sys.stderr.write("usage: receipt_verify.py [--plant NAME]... [--trust KEYS.json] [--at MS [--skew-ms MS]]\n" " (FILE... | --lines FILE)\n" " receipt_verify.py --self-test [ES_NUMBER_FILE]\n" " receipt_verify.py --wasmq-cases OUT.jsonl [ES_NUMBER_FILE]\n") return 2 def main(argv): if not argv or argv[0] in ("-h", "--help"): return _usage() if argv[0] == "--self-test": return self_test(argv[1:]) if argv[0] == "--wasmq-cases": return write_wasmq_cases(argv[1:]) verdicts, ok, i = [], True, 0 while i < len(argv): arg = argv[i] if arg in ("--plant", "--lines", "--trust", "--at", "--skew-ms"): if i + 1 >= len(argv): return _usage() value = argv[i + 1] i += 2 if arg == "--trust": raw = _read(value) try: if raw is None: raise TrustRefused("it cannot be read") HOLD["trust"] = read_trust(raw) except TrustRefused as e: sys.stderr.write("receipt_verify: the trust list %s: %s\n" % (value, e)) return 2 continue if arg in ("--at", "--skew-ms"): if not re.fullmatch(r"0|[1-9][0-9]*", value) or int(value) > MAX_SAFE: return _usage() HOLD["at_ms" if arg == "--at" else "skew_ms"] = int(value) continue if arg == "--plant": if value not in PLANTS_KNOWN: return _usage() PLANTS.add(value) sys.stderr.write("receipt_verify: planted fault %s: verdicts are wrong by design\n" % value) continue raw = _read(value) if raw is None: verdicts.append({"file": value, "valid": False, "reasons": ["unreadable"], "key": None, "form": None}) continue lines = raw.split(b"\n") if lines and lines[-1] == b"": lines.pop() if not lines: sys.stderr.write("receipt_verify: no job in %s\n" % value) ok = False for n, line in enumerate(lines, 1): verdicts.append(verdict_for("%s:%d" % (value, n), line)) else: i += 1 raw = _read(arg) if raw is None: verdicts.append({"file": arg, "valid": False, "reasons": ["unreadable"], "key": None, "form": None}) else: verdicts.append(verdict_for(arg, raw)) try: for v in verdicts: sys.stdout.write(json.dumps(v) + "\n") sys.stdout.flush() except (OSError, ValueError): return 1 return 0 if ok and all(v["valid"] for v in verdicts) else 1 # =============================================================== 10. self-test _BLAKE3_VECTORS = ( # BLAKE3's test vectors: byte i is i mod 251 (0, "af1349b9f5f9a1a6a0404dea36dcc9499bcb25c9adc112b7cc9a93cae41f3262"), (1, "2d3adedff11b61f14c886e35afa036736dcd87a74d27b5c1510225d0f592e213"), (1023, "10108970eeda3eb932baac1428c7a2163b0e924c9a9e25b35bba72b28f70bd11"), (1024, "42214739f095a406f3fc83deb889744ac00df831c10daa55189b5d121c855af7"), (1025, "d00278ae47eb27b34faecf67b4fe263f82d5412916c1ffd97c8cb7fb814b8444"), (2048, "e776b6028c7cd22a4d0ba182a8bf62205d2ef576467e838ed6f2529b85fba24a"), ) _BLAKE3_ABC = "6437b3ac38465133ffb63b75273a8db548c558465d79db03fd359c6cd5bd9d85" _RFC8032_VECTORS = ( # RFC 8032 §7.1 TEST 1, 2, 3 ("9d61b19deffd5a60ba844af492ec2cc44449c5697b326919703bac031cae7f60", "d75a980182b10ab7d54bfed3c964073a0ee172f3daa62325af021a68f707511a", "", "e5564300c360ac729086e2cc806e828a84877f1eb8e5d974d873e065224901555fb8821590a33bacc61e39701cf9b46bd25bf5f0595bbe24655141438e7a100b"), ("4ccd089b28ff96da9db6c346ec114e0f5b8a319f35aba624da8cf6ed4fb8a6fb", "3d4017c3e843895a92b70aa74d1b7ebc9c982ccf2ec4968cc0cd55f12af4660c", "72", "92a009a9f0d4cab8720e820b5f642540a2b27b5416503f8fb3762223ebdb69da085ac1e43e15996e458f3613d0f11d8c387b2eaeb4302aeeb00d291612bb0c00"), ("c5aa8df43f9f837bedb7442f31dcb7b166d38535076f094b85ce3a2e0b4458f7", "fc51cd8e6218a1a38da47ed00230f0580816ed13ba3303ac5deb911548908025", "af82", "6291d657deec24024827e69c3abe01a30ce548a284743a445e3680d7db5ac3ac18ff9b538d16f290ae67f760984dc6594a7c15e9716ed28dc027beceea1ec40a"), ) _SMALL_ORDER = ( # identity, order 2, the two of order 4 "0100000000000000000000000000000000000000000000000000000000000000", "ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f", "0000000000000000000000000000000000000000000000000000000000000000", "0000000000000000000000000000000000000000000000000000000000000080", ) _CANONICAL_VECTORS = ( # RFC 8785 §3.2.2, §3.2.3, and numbers ('{"numbers":[333333333.33333329,1E30,4.50,2e-3,0.000000000000000000000000001],' '"string":"\\u20ac$\\u000F\\u000aA\'\\u0042\\u0022\\u005c\\\\\\"\\/",' '"literals":[null,true,false]}', '{"literals":[null,true,false],"numbers":[333333333.3333333,1e+30,4.5,0.002,1e-27],' '"string":"\u20ac$\\u000f\\nA\'B\\"\\\\\\\\\\"/"}'), ('{"\\u20ac":1,"\\r":2,"\\ufb33":3,"1":4,"\\ud83d\\ude00":5,"\\u0080":6,"\\u00f6":7}', '{"\\r":2,"1":4,"\u0080":6,"\u00f6":7,"\u20ac":1,"\U0001f600":5,"\ufb33":3}'), ('[-0, 0.0, 1.0, 1e21, 1e-7, 123e-9, 5e-324, 1e-400, 1.7976931348623157e308]', '[0,0,1,1e+21,1e-7,1.23e-7,5e-324,0,1.7976931348623157e+308]'), ) _FIRST_FORM_VECTORS = ( ("[1.0,1,-0,0.0,1e16,1e15,0.00001,0.000001,1.5e300,18446744073709551615," "18446744073709551616,-9223372036854775808,-9223372036854775809,2.5,-1.5e-7]", "[1.0,1,-0.0,0.0,1e+16,1000000000000000.0,0.00001,1e-6,1.5e+300,18446744073709551615," "1.8446744073709552e+19,-9223372036854775808,-9.223372036854776e+18,2.5,-1.5e-7]"), # §8.2: a positive exponent with its sign, a negative one as before. ("[1e16,1.5e300,1e-7,1e15]", "[1e+16,1.5e+300,1e-7,1000000000000000.0]"), ) _UNREADABLE_VECTORS = ( (b'{"a":1,"a":2}', "duplicate"), (b'{"a":1,"\\u0061":2}', "duplicate"), (b'["\\ud800"]', "surrogate"), (b'["\\ud800x"]', "surrogate"), (b'["\\udc00\\ud800"]', "surrogate"), (b'["a\x01"]', "control"), (b'[1e400]', "number_overflow"), (b'[-1e400]', "number_overflow"), (str(2 ** 1024 - 2 ** 970).encode(), "number_overflow"), (b'\xef\xbb\xbf{}', "bom"), (b'["\xed\xa0\x80"]', "utf8"), (b'["\xc0\xaf"]', "utf8"), (b'{"a":1,}', "syntax"), (b'[01]', "syntax"), (b'[NaN]', "syntax"), (b'{} {}', "syntax"), (b'', "syntax"), (b'[' * 128 + b']' * 128, "depth"), ) _READABLE_VECTORS = ( b'[' * 127 + b']' * 127, str(2 ** 1024 - 2 ** 970 - 1).encode(), b'[1e-400, "\\ufffe", "\\ufdd0", "\xef\xbf\xbf"]', ) def _seal(seed, request_text, result_text, form="rfc8785", receipt_extra=None, envelope="", time_text=None): """A job body sealed here, for the self-test only; with `time_text`, the text of a `time` the receipt seals (§8.2), written in the receipt as given.""" request, result = read_json(request_text.encode()), read_json(result_text.encode()) canonical = form == "rfc8785" if time_text is None: digest = seal_digest(2 if canonical else 1, text_of(request, canonical).encode(), text_of(result, canonical).encode()) else: digest = seal_digest(3, text_of(request, True).encode(), text_of(result, True).encode(), text_of(read_json(time_text.encode()), True).encode()) public, sig = _ed25519_sign(seed, digest) receipt = {"alg": "ed25519", "key": public.hex(), "digest": digest.hex(), "signature": sig.hex()} if canonical: receipt["canon"] = "rfc8785" receipt.update(receipt_extra or {}) receipt_text = json.dumps(receipt, separators=(",", ":")) if time_text is not None: receipt_text = receipt_text[:-1] + ',"time":' + time_text + "}" body = '{%s"request":%s,"result":%s,"receipt":%s}}' % ( envelope, request_text, result_text[:-1], receipt_text) return body.encode() _PROVIDER_REQUEST = '{"qasm":"OPENQASM 3.0;\\nqubit[1] q;\\nbit[1] c;\\nx q[0];\\nc = measure q;\\n","provider":"lab","shots":4}' _PROVIDER_QASM3 = "OPENQASM 3.0;\nbit[1] c;\nx $0;\nc[0] = measure $0;\n" def _provider_result(**changes): r = { "method": "provider", "qubits": 1, "gates": 1, "accuracy": {"class": "simulated", "note": "counts a simulator returned"}, "provider": {"name": "lab", "kind": "process", "protocol": "wai.quantum.provider/1", "device": "reference", "provenance": "simulator:the reference simulator", "qubits": 2, "basis": "rzsxxcz", "describe": "ab" * 32}, "calibration": "snap-1", "compiled": {"basis": "rzsxxcz", "qasm3": _PROVIDER_QASM3, "program": blake3(_PROVIDER_QASM3.encode()).hex(), "hash": "BLAKE3 of qasm3", "native_gates": 1, "two_qubit_gates": 0, "swaps": 0, "layout": [0], "final_layout": [0], "checked": "checked here", "placement": {}}, "job": {"id": "j-1", "polls": 0}, "counts": {"1": 4}, "distinct_outcomes": 1, "omitted_shots": 0, "shots": 4, "counts_source": "shots", "execution": {"stated_by": "provider", "mitigation": "off", "twirling": "none", "decoupling": "none", "remapping": "off", "optimisation": "off", "verbatim": True}, "ideal": {"computed": True, "total_variation_distance": 0, "hellinger_fidelity": 1}, "cost": {"free": True, "estimate": {"free": True}, "charged": None, "confirmed": False}, "energy": {"unmetered": "the work ran at the provider"}, "engine": {"name": "wai-quantum", "version": "0.9.0"}, "schema": "wai.quantum.job-result/1", } for path, value in changes.items(): node = r parts = path.split("__") for part in parts[:-1]: node = node[part] if value is _DELETE: node.pop(parts[-1], None) else: node[parts[-1]] = value return json.dumps(r, separators=(",", ":")) _DELETE = object() def _contract_job(seed=None, extra_routes=(), **changes): """§8.7: the provider job above, named under a contract that allows it and wants a simulator's counts, with its reasoning and its shadow, for the self-test only: (request text, result text). Every outcome is written here, not computed.""" request = json.loads(_PROVIDER_REQUEST) request["contract"] = {"exactness": "simulated", "providers": "allowed"} if seed is not None: request["seed"] = seed job_bytes = 1 << 30 facts = {"job_bytes": job_bytes, "routes": [ {"route": "method:exact", "class": "bit-exact", "seconds": None, "memory_bytes": None, "work": None}]} digest = blake3(text_of(read_json(json.dumps(facts).encode()), True).encode("utf-8")).hex() shadow_request = {"qasm": request["qasm"], "shots": 4, "seed": ((1 if seed is None else seed) + 2 ** 32) % 2 ** 53, "method": "exact"} free_now = {"money": {"free": True}, "time": {"seconds": 1.5, "basis": "provider"}, "memory_bytes": None, "work": None, "energy": {"joules": None, "why": "no provider states it"}, "leaves_out": ["energy"]} planner = { "format": "wai.quantum.planner/1", "wanted": "simulated", "wanted_from": "contract", "named": "provider:lab", "question": "counts", "auto": None, "host": {"job_bytes": job_bytes, "providers": ["lab"] + [r["provider"] for r in extra_routes]}, "routes": [ {"route": "method:exact", "kind": "local", "method": "exact", "class": "bit-exact", "host_dependent": False, "auto_rank": 20, "price": None, "outcome": "rejected", "rejected": {"code": "not_named", "why": "the job names another route"}}, {"route": "provider:lab", "kind": "provider", "provider": "lab", "class": "simulated", "host_dependent": True, "price": free_now, "outcome": "chosen"}, ] + list(extra_routes), "choice": "provider:lab", "why": "the route the job names", "stable": {"scope": "the host-independent routes", "routes": ["method:exact"], "digest": digest, "choice": False}, "kept": {}, "shadow": {"route": "method:exact", "class": "bit-exact", "budget_seconds": 300, "price": {"money": {"free": True}, "time": {"seconds": 0.001, "basis": "nominal"}, "memory_bytes": 1024, "work": 8, "energy": {"joules": None, "why": "none"}, "leaves_out": []}, "request": shadow_request}, } # By hand: 8 shots of "1" pooled, E|2B - 8| = (3/2)(5/4)(7/6) = 2.1875; half of it over 4. n, d, tv, hf, bound = 0, 8, 0.0, 1.0, 0.2734375 shadow = {"ran": True, "route": "method:exact", "request": shadow_request, "shots": 4, "accuracy": {"class": "bit-exact"}, "counts": {"1": 4}, "distinct_outcomes": 1, "omitted_shots": 0, "distance": {"computed": True, "numerator": n, "denominator": d, "total_variation": tv, "hellinger_fidelity": hf, "sampling_tvd_bound": bound}} result = json.loads(_provider_result()) result["planner"], result["shadow"] = planner, shadow both = {"request": request, "result": result} for path, value in changes.items(): node = both parts = path.split("__") for part in parts[:-1]: node = node[int(part)] if isinstance(node, list) else node[part] last = int(parts[-1]) if isinstance(node, list) else parts[-1] if value is _DELETE: node.pop(last) else: node[last] = value return json.dumps(both["request"], separators=(",", ":")), json.dumps(both["result"], separators=(",", ":")) def _lr(name, cls, rank, outcome, code=None, seconds=0.001, memory=1024, joules=None, host_dependent=False, priced=True, watch="a test's reading"): """A local route, every member written out, for the self-test only.""" r = {"route": "method:" + name, "kind": "local", "method": name, "class": cls, "host_dependent": host_dependent, "auto_rank": rank, "outcome": outcome, "price": {"money": {"free": True}, "time": {"seconds": seconds, "basis": "nominal"}, "memory_bytes": memory, "work": 8, "energy": {"joules": joules, "basis": "a test"} if joules is not None else {"joules": None, "why": "none"}, "leaves_out": []} if priced else None} if priced and watch is not None: r["price"]["energy"]["watch"] = watch if code: r["rejected"] = {"code": code, "why": "said so"} return r def _local_contract_job(contract, routes, choice, auto, stable_choice, kept, request_extra=None, energy=None, providers=(), result_class="bit-exact"): """§8.7: a job under a contract run on one of the engine's methods, for the self-test only: (request text, result text). Every outcome, the choice, auto and stable.choice are written by the caller, never computed here.""" request = {"qasm": "OPENQASM 3.0;\nqubit[1] q;\nbit[1] c;\nx q[0];\nc = measure q;\n", "shots": 4, "contract": contract} request.update(request_extra or {}) job_bytes = 1 << 30 covered = [r for r in routes if r["kind"] == "local" and r["host_dependent"] is False] facts = {"job_bytes": job_bytes, "routes": [{"route": r["route"], "class": r["class"], "seconds": (r["price"] or {}).get("time", {}).get("seconds"), "memory_bytes": (r["price"] or {}).get("memory_bytes"), "work": (r["price"] or {}).get("work")} for r in covered]} digest = blake3(text_of(read_json(json.dumps(facts).encode()), True).encode("utf-8")).hex() wanted = contract.get("exactness") planner = { "format": "wai.quantum.planner/1", "wanted": wanted, "wanted_from": "contract" if wanted else None, "named": None, "question": "counts", "auto": auto, "host": {"job_bytes": job_bytes, "providers": list(providers)}, "routes": routes, "choice": choice, "why": "the cheapest", "kept": kept, "stable": {"scope": "the host-independent routes", "routes": [r["route"] for r in covered], "digest": digest, "choice": stable_choice}, } result = {"method": choice[len("method:"):], "qubits": 1, "gates": 1, "accuracy": {"class": result_class}, "counts": {"1": 4}, "elapsed_ms": 3, "planner": planner, "energy": energy if energy is not None else {"unmetered": "a test"}, "engine": {"name": "wai-quantum", "version": "0.9.0"}, "schema": "wai.quantum.job-result/1"} return json.dumps(request, separators=(",", ":")), json.dumps(result, separators=(",", ":")) def _has_num(o): if isinstance(o, Num): return True if isinstance(o, dict): return any(_has_num(v) for v in o.values()) if isinstance(o, list): return any(_has_num(v) for v in o) return False def _dump(o): """JSON text of a self-test value, a Num written by its own text.""" if not _has_num(o): return json.dumps(o) return _first_text(o) def _first_text(o): if isinstance(o, Num): return o.text if isinstance(o, dict): return "{" + ",".join(json.dumps(k) + ":" + _first_text(v) for k, v in o.items()) + "}" if isinstance(o, list): return "[" + ",".join(_first_text(v) for v in o) + "]" return json.dumps(o) def _seal_set(seed, request, head, items, receipt_extra=None, form="rfc8785"): """A set sealed here over its request and head, for the self-test only.""" canonical = form == "rfc8785" drop_key, upper_key = head.pop("_drop_key", False), head.pop("_upper_key", False) q = text_of(read_json(_dump(request).encode()), canonical).encode() t = text_of(read_json(_dump(head).encode()), canonical).encode() digest = seal_digest(2 if canonical else 1, q, t) public, sig = _ed25519_sign(seed, digest) result = dict(head, items=items) receipt = {"alg": "ed25519", "key": public.hex(), "digest": digest.hex(), "signature": sig.hex()} if canonical: receipt["canon"] = "rfc8785" result["receipt"] = dict(receipt, **(receipt_extra or {})) if drop_key: del result["receipt"]["key"] if upper_key: result["receipt"]["key"] = result["receipt"]["key"].upper() return ("{\"request\":%s,\"result\":%s}" % (_dump(request), _dump(result))).encode() _ITEM_RESULT = ('{"method":"statevector","qubits":1,"gates":1,"accuracy":{"class":"exact"},' '"counts":{"1":10}}') def _set_body(seed, request, item_requests, errors=(), before_root=None, after_root=None, head_extra=None, item_result=_ITEM_RESULT, item_seed=None, form="rfc8785"): """A set of items made and sealed here, each item a job sealed with the same seed. before_root changes the items before the leaves are taken; after_root changes the head and items after the root and paths are made, before the set is sealed.""" items = [] for i, asked in enumerate(item_requests): if i in errors: items.append({"index": i, "request": asked, "error": "it failed"}) else: job = json.loads(_seal(item_seed or seed, _dump(asked), item_result).decode()) items.append({"index": i, "request": asked, "result": job["result"]}) if before_root: before_root(items) hashes = [_leaf_hash(item_leaf(read_json(_dump(item).encode()))) for item in items] levels = merkle_levels(hashes) if hashes else [[]] for i, item in enumerate(items): item["path"] = [h.hex() for h in merkle_path(levels, i)] head = {"format": SET_FORMAT, "count": len(items), "root": levels[-1][0].hex() if hashes else "00" * 32} head.update(head_extra or {}) if after_root: after_root(head, items) return _seal_set(seed, request, head, items, form=form) # ---------------------------------------------- the wasmQ cases (quantum-wasmq §6.5) # # The self-test's wasmQ jobs, each made and sealed here, with the reasons §8.4 gives it and # the rules of quantum-wasmq §6.5 it breaks, both written by hand from the text, never from # this file's verdict. `--wasmq-cases` writes the same bytes and reasons, so that another # verifier is held to what the text says, not to what this one does. _WASMQ_SEED = bytes(range(32)) # the self-test's key (its `seed`), every case's _WASMQ_FORM = ["wasmq_form"] _WASMQ_DONE = '"status":"done","method":"stabilizer",' _WASMQ_FAULTED = '"status":"fault","method":"stabilizer",' _WASMQ_SEALED_LINE = '; the sealed result says ' _WASMQ_UNCHECKED_NAME = "plant wasmq-unchecked: strict verdict" def _wasmq_parts(fault): """The request and result of a wasmQ job that keeps every rule of §6.5: a run of 32 shots, state shot; or, with `fault`, one of 8 shots, state job, stopped in shot 2's call of decode64 by a fault of the call's fuel. The numbers the ties of rules 20 to 35 ask: the run's instances, 3000, are at least W × P = 32 × (3 + 7) = 320 (rule 21); each member of its callouts has fuel from calls to calls × max, and at least max and 1 for each other call (rule 20); its prior's 3 + 7 fits per_instance (rule 33). The fault's run has W = 1 (state job), P = 10, at most its instances 400; the stopped call used per_call, 400 (rule 28), and decode64's two calls that returned used 600, from 2 to 2 × 400 (rule 20, its max not more than the stopped call's 400); decode64 is the extern of callout 0, whose module 0 is the decoder (rule 22). In both a call returned, so rule 35 leaves the transcript free. Either's work (rule 30) is some 2^37, and its envelope (rule 31) some 2^15 bytes.""" budget = {"per_call": 400 if fault else 10000000, "per_job": 17179869184, "per_instance": 100000000} asked = {"wasmq": { "profile": WASMQ_PROFILE, "program": {"blake3": "a1" * 32, "bytes": 1104, "inputs": {"rounds": 3, "offset": -2}}, "modules": [{"name": "decoder", "blake3": "b2" * 32, "bytes": 39442, "priors": [{"name": "checks", "blake3": "c3" * 32, "bytes": 7}]}, {"name": "planner", "blake3": "d4" * 32, "bytes": 2048, "priors": []}], "callouts": [{"extern": "decode64", "module": 0, "export": "decode64"}, {"extern": "plan", "module": 1, "export": "plan"}], "run": {"shots": 8 if fault else 32, "seed": 1234, "method": "stabilizer", "state": "job" if fault else "shot", "fuel": dict(budget)}}, "envelope_blake3": "e5" * 32} made = { "format": WASMQ_FORMAT, "profile": WASMQ_PROFILE, "status": "ok", "method": "stabilizer", "qubits": 17, "shots": 32, "shots_run": 32, "seed": 1234, "counts": {"0101": 30, "1100": 2}, "callouts": 34, "fuel": {"used": 9500, "instances": 3000, "budget": dict(budget), "callouts": {"decode64": {"calls": 32, "fuel": 6400, "max": 200}, "plan": {"calls": 2, "fuel": 100, "max": 60}}}, "modules": [{"name": "decoder", "blake3": "b2" * 32}, {"name": "planner", "blake3": "d4" * 32}], "transcript_blake3": "f6" * 32, "accuracy": {"class": "exact"}, "energy": {"unmetered": WASMQ_ENERGY}} if fault: # state job: stopped in shot 2's call of decode64 made.update(status="fault", shots=8, shots_run=2, counts={"0101": 1, "1100": 1}, callouts=3, fault={"reason": "fuel_exhausted", "shot": 2, "phase": "call", "module": "decoder", "fuel": 400, "callout": "decode64", "budget": "call"}) made["fuel"].update(used=1400, instances=400, callouts={"decode64": {"calls": 3, "fuel": 1000, "max": 400}}) return asked, made def _wasmq_clone(v): """A change's value copied, so that a case never changes another's.""" if isinstance(v, dict): return dict((k, _wasmq_clone(x)) for k, x in v.items()) if isinstance(v, list): return [_wasmq_clone(x) for x in v] return v _WASMQ_TRANSCRIPT = object() # a result's transcript_blake3: the one rule 35 gives def _wasmq_u64(v): """A count's 8 bytes, little-endian; 0 for what is no count (rule 35).""" x = v.value if isinstance(v, Num) else v if isinstance(x, bool) or not isinstance(x, (int, float)) or x != int(x) or not 0 <= x <= 2 ** 53 - 1: x = 0 return int(x).to_bytes(8, "little") def _wasmq_transcript(made): """§6.4, rule 35: the transcript of a run in which no call returned, written here from §6.4's words: BLAKE3 over "wai:wasmq-transcript" and the byte 1, then, after a fault, "fault", its shot (u64), its reason's UTF-8 bytes and its fuel (u64), little-endian.""" data = "wai:wasmq-transcript".encode("ascii") + bytes([1]) fault = made.get("fault") if made.get("status") == "fault" and isinstance(fault, dict): reason = fault.get("reason") data += ("fault".encode("ascii") + _wasmq_u64(fault.get("shot")) + (reason.encode("utf-8") if isinstance(reason, str) else b"") + _wasmq_u64(fault.get("fuel"))) return blake3(data).hex() def _wasmq_job(fault=False, request=None, result=None, envelope=_WASMQ_DONE, **seal_options): """A wasmQ job sealed here, each change a path (members joined by "__") and its value, applied in order. A result's transcript_blake3 of _WASMQ_TRANSCRIPT is replaced, once every change is made, by the transcript §6.4 gives the run (rule 35).""" asked, made = _wasmq_parts(fault) for target, changes in ((asked, request), (made, result)): for path, value in (changes or {}).items(): node, parts = target, path.split("__") for part in parts[:-1]: node = node[int(part)] if isinstance(node, list) else node[part] last = int(parts[-1]) if isinstance(node, list) else parts[-1] if value is _DELETE: del node[last] elif isinstance(node, list) and last == len(node): node.append(_wasmq_clone(value)) else: node[last] = _wasmq_clone(value) if made.get("transcript_blake3") is _WASMQ_TRANSCRIPT: made["transcript_blake3"] = _wasmq_transcript(made) return _seal(_WASMQ_SEED, _dump(asked), _dump(made), envelope=envelope, **seal_options) def _wasmq_changed_after(raw, change): """A job changed after its seal.""" job = json.loads(raw.decode()) change(job) return json.dumps(job).encode() def _wasmq_statement(outcome, problems=(), notes=()): return {"outcome": outcome, "problems": list(problems), "notes": list(notes)} def _landscape_job(request=None, **changes): """An energy-landscape run sealed here, for the self-test only: built from quantum-landscape §3 and §5.4 (not by any engine), every rule holding, then each member of `changes` set on its result (None removes it).""" request = request or {"program": "vars 2\nagree 0 1\nminimize\n"} prog = request["program"].encode("utf-8") cells, energy, sweeps = [0, 0], 0, 60 data = LANDSCAPE.encode() + b"\0" + struct.pack("d", bytes.fromhex(hexbits))[0]) != want: check("es number %s" % hexbits, False) check("es number table, %d lines" % lines, lines > 0) # Seals of both forms, made here, and what breaks them (§8.4). req = '{"qasm":"OPENQASM 3.0;\\nqubit[1] q;\\nbit[1] c;\\nx q[0];\\nc = measure q;\\n","shots":10}' res = ('{"method":"statevector","qubits":1,"gates":1,"accuracy":{"class":"exact"},' '"counts":{"1":10},"expectations":[{"observable":"Z0","coeff":1.0,"value":-1.0}]}') for form in ("rfc8785", "first"): body = _seal(seed, req, res, form) v = judge(body) check("%s seals" % form, v["reasons"] == [] and v["form"] == form and v["key"] is not None) check("%s tampered: digest_mismatch alone" % form, reasons_of(body.replace(b'"1":10', b'"1":11')) == ["digest_mismatch"]) relabelled = (body.replace(b'"canon":"rfc8785",', b"").replace(b',"canon":"rfc8785"', b"") if form == "rfc8785" else body.replace(b'"alg":"ed25519"', b'"alg":"ed25519","canon":"rfc8785"')) check("%s relabelled" % form, reasons_of(relabelled) == ["digest_mismatch"]) check("%s upper-case key" % form, reasons_of(body.replace( v["key"].encode(), v["key"].upper().encode())) == ["receipt_form"]) check("%s envelope not read" % form, reasons_of(body.replace( b'{"request"', b'{"status":"failed","method":"other","id":7,"request"')) == []) body = _seal(seed, req, res) check("canon null names no form", reasons_of(body.replace(b'"canon":"rfc8785"', b'"canon":null')) == ["receipt_form"]) check("alg other", reasons_of(body.replace(b'"alg":"ed25519"', b'"alg":"ed448"')) == ["receipt_form"]) check("unknown receipt member ignored", reasons_of(body.replace(b'"alg":', b'"x":"y","alg":')) == []) check("canonical survives re-spelling and order", reasons_of(body.replace( b'"coeff":1.0', b'"coeff":1e0').replace(b'"qubits":1,"gates":1', b'"gates":1, "qubits":1')) == []) first = _seal(seed, req, res, "first") check("first form refuses member order", reasons_of(first.replace( b'"qubits":1,"gates":1', b'"gates":1,"qubits":1')) == ["digest_mismatch"]) check("first form refuses re-spelling", reasons_of(first.replace(b'"coeff":1.0', b'"coeff":1')) == ["digest_mismatch"]) big = _seal(seed, req.replace('"shots":10', '"shots":10,"seed":9007199254740993'), res) check("inexact_number", reasons_of(big) == ["inexact_number"]) check("first form seals a u64 by its digits", reasons_of( _seal(seed, req.replace('"shots":10', '"shots":10,"seed":9007199254740993'), res, "first")) == []) check("first form past u64 is sealed as a double", reasons_of( _seal(seed, req.replace('"shots":10', '"shots":10,"seed":18446744073709551617'), res, "first")) == ["inexact_number"]) check("first form 2^64 is a double, exactly", reasons_of( _seal(seed, req.replace('"shots":10', '"shots":10,"seed":18446744073709551616'), res, "first")) == []) check("first form below -2^63", reasons_of( _seal(seed, req.replace('"shots":10', '"shots":10,"seed":-9223372036854775809'), res, "first")) == ["inexact_number"]) def seeded(seed_text, form="rfc8785"): return _seal(seed, req.replace('"shots":10', '"shots":10,"seed":%s' % seed_text), res, form) check("2^60 in its canonical spelling", reasons_of(seeded("1152921504606847000")) == []) check("-2^60 in its canonical spelling", reasons_of(seeded("-1152921504606847000")) == []) check("2^60's double, in another spelling", reasons_of(seeded("1152921504606847001")) == ["inexact_number"]) check("2^60 + 1, inexact", reasons_of(seeded("1152921504606846977")) == ["inexact_number"]) check("2^53 + 1 is no double's canonical text", reasons_of(seeded("9007199254740993")) == ["inexact_number"]) check("under 10^21, read as 10^21: no canonical whole spelling", reasons_of( seeded("999999999999999999999")) == ["inexact_number"]) check("first form: 2^65 canonical, past its integers", reasons_of( seeded("36893488147419103000", "first")) == []) check("first form: past its integers, not canonical", reasons_of( seeded("36893488147419103001", "first")) == ["inexact_number"]) check("receipt_form reads numbers as canonical", reasons_of( _seal(seed, req.replace('"shots":10', '"shots":10,"seed":9007199254740993'), res, "first") .replace(b'"alg":"ed25519"', b'"alg":"ed448"')) == ["inexact_number", "receipt_form"]) check("inexact_number not in the receipt", reasons_of( _seal(seed, req, res, receipt_extra={"x": 0}).replace(b'"x":0', b'"x":9007199254740993')) == []) check("other method may not be simulated", reasons_of(_seal(seed, req, res.replace( '"exact"', '"simulated"'))) == ["provider_class"]) check("unknown class is not a reason", reasons_of(_seal(seed, req, res.replace('"exact"', '"novel"'))) == []) check("a sign-off repeats the class of the job it signs off", reasons_of(_seal(seed, req, res.replace( '"exact"', '"measured"').replace('{', '{"format":"wai.quantum.signoff/1",', 1))) == []) check("no_receipt alone", reasons_of(b'{"request":{},"result":{"method":"provider"}}') == ["no_receipt"]) check("not_a_job", reasons_of(b'{"request":[],"result":{}}') == ["not_a_job"]) # The identity key with R = [S]B holds for every digest unless the key rules refuse it. anything = _seal(seed, req, res) forged = json.loads(anything.decode()) forged["result"]["receipt"]["key"] = _SMALL_ORDER[0] forged["result"]["receipt"]["signature"] = (_encode_point(_mul(5, _B)) + (5).to_bytes(32, "little")).hex() forged = json.dumps(forged).encode() check("identity key: bad_key", reasons_of(forged) == ["bad_key"]) # §8.2: R of small order, in a signature whose equation holds, so that only the # rules on R can refuse it: R the identity, k = SHA-512(R ‖ A ‖ digest) mod l, # S = k·a mod l, a the clamped scalar of the demo seed. demo = bytes([42] * 32) demo_scalar = (int.from_bytes(hashlib.sha512(demo).digest()[:32], "little") & ((1 << 254) - 8)) | (1 << 254) demo_key = _encode_point(_mul(demo_scalar, _B)) demo_digest = seal_digest(2, text_of(read_json(req.encode()), True).encode(), text_of(read_json(res.encode()), True).encode()) def small_r_body(r_bytes): k = int.from_bytes(hashlib.sha512(r_bytes + demo_key + demo_digest).digest(), "little") % _L s_value = k * demo_scalar % _L holds = _same_point(_mul(s_value, _B), _add(_IDENTITY, _mul(k, _decode_point(demo_key)))) signature = r_bytes + s_value.to_bytes(32, "little") return holds, _seal(demo, req, res, receipt_extra={"signature": signature.hex()}) identity_holds, identity_r_body = small_r_body(bytes.fromhex(_SMALL_ORDER[0])) alias_r = (_P + 1).to_bytes(32, "little") # the identity again, spelt y = p + 1 alias_holds, alias_r_body = small_r_body(alias_r) check("identity R: the equation holds", identity_holds) check("identity R: bad_signature", reasons_of(identity_r_body) == ["bad_signature"]) check("identity R spelt y = p + 1: refused by its decoding", _decode_point(alias_r) is None) check("identity R spelt y = p + 1: the equation holds", alias_holds) check("identity R spelt y = p + 1: bad_signature", reasons_of(alias_r_body) == ["bad_signature"]) # A provider's stated result (§8.1, §8.3, §8.4). def provider_body(request=_PROVIDER_REQUEST, **changes): return _seal(seed, request, _provider_result(**changes)) names = {"0": "Q0"} nobody = {"stated_by": "nobody", "mitigation": "unknown", "twirling": "unknown", "decoupling": "unknown", "remapping": "unknown", "optimisation": "unknown", "verbatim": None} two_to_53, two_to_54 = 2 ** 53, 2 ** 54 prx_row = ROWS["prx-circuits"][0][2] processor_row, simulator_row = ROWS["cloud-tasks"][0][2], ROWS["cloud-tasks"][1][2] noise_row = dict(ROWS["native-turns"][1][2], sent={ "fields": ROWS["native-turns"][1][2]["sent"]["fields"], "settings": {"/input/gateset": "native", "/settings/error_mitigation/debiasing": False, "/noise/model": "a device's model"}}) cases = ( ("stated provider result", provider_body(), []), ("class measured on a simulator", provider_body(accuracy__class="measured"), ["provider_class"]), ("approximate false", provider_body(accuracy__approximate=False), ["provider_class"]), ("approximate true", provider_body(accuracy__approximate=True), []), ("silicon is measured", provider_body(provider__provenance="silicon", accuracy__class="measured"), []), ("request names another", provider_body(provider__name="other"), ["request_provider"]), ("request shots", provider_body(request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":5')), ["request_shots"]), ("default 1024 shots", provider_body(request=_PROVIDER_REQUEST.replace(',"shots":4', '')), ["request_shots"]), ("counts sum", provider_body(counts={"1": 3}), ["counts"]), ("zero count", provider_body(counts={"1": 4, "0": 0}, distinct_outcomes=2), ["counts"]), ("describe missing", provider_body(provider__describe=_DELETE), ["provider_members"]), ("estimate null", provider_body(cost__estimate=None), ["provider_members"]), ("counts_source of another row", provider_body(provider__kind="prx-circuits"), ["counts_source", "execution"]), ("http: client-stated", provider_body(provider__kind="http", execution=dict( prx_row)), ["execution"]), ("verbatim with remapping on", provider_body(execution__remapping="on"), ["execution"]), ("execution extra member", provider_body(execution__extra="x"), ["execution"]), ("provider may say unknown", provider_body(execution__twirling="unknown"), []), ("provider may not say default", provider_body(execution__twirling="default"), ["execution"]), ("nobody", provider_body(execution=nobody), []), ("nobody on a kind with rows", provider_body(provider__kind="cloud-tasks", execution=nobody), []), ("nobody on sampler-v2", provider_body(provider__kind="sampler-v2", execution=nobody), []), ("nobody on a kind with rows, its source still the rows'", provider_body( provider__kind="prx-circuits", execution=nobody), ["counts_source"]), ("provider on a kind with rows", provider_body(provider__kind="cloud-tasks"), ["execution"]), ("cloud-tasks processor row on silicon", provider_body( provider__kind="cloud-tasks", provider__provenance="silicon", accuracy__class="measured", compiled__qubit_names=names, execution=dict(processor_row, note="sent verbatim")), []), ("cloud-tasks processor row on a simulator", provider_body( provider__kind="cloud-tasks", compiled__qubit_names=names, execution=dict(processor_row)), ["execution"]), ("cloud-tasks simulator row on an emulator", provider_body( provider__kind="cloud-tasks", provider__provenance="emulator", compiled__qubit_names=names, execution=dict(simulator_row)), []), ("cloud-tasks simulator row on silicon", provider_body( provider__kind="cloud-tasks", provider__provenance="silicon", accuracy__class="measured", compiled__qubit_names=names, execution=dict(simulator_row)), ["execution"]), ("row with its fields reordered", provider_body( provider__kind="cloud-tasks", compiled__qubit_names=names, execution=dict( simulator_row, sent={"fields": list(reversed(_CLOUD_TASKS_FIELDS)), "settings": {}})), ["execution"]), # §8.4 compiled.qubit_names ("qubit_names required: cloud-tasks by client", provider_body( provider__kind="cloud-tasks", execution=dict(simulator_row)), ["provider_members"]), ("qubit_names required: prx-circuits by client", provider_body( provider__kind="prx-circuits", counts_source="vendor_counts", execution=dict(prx_row)), ["provider_members"]), ("qubit_names given: prx-circuits by client", provider_body( provider__kind="prx-circuits", counts_source="vendor_counts", compiled__qubit_names=names, execution=dict(prx_row)), []), ("qubit_names optional elsewhere, and held when given", provider_body(compiled__qubit_names=names), []), ("qubit_names null is given", provider_body(compiled__qubit_names=None), ["provider_members"]), ("qubit_names an array", provider_body(compiled__qubit_names=["Q0"]), ["provider_members"]), ("qubit_names leading zero", provider_body(compiled__qubit_names={"0": "Q0", "01": "Q1"}), ["provider_members"]), ("qubit_names key not an index", provider_body(compiled__qubit_names={"0": "Q0", "x": "Q1"}), ["provider_members"]), ("qubit_names empty name", provider_body(compiled__qubit_names={"0": ""}), ["provider_members"]), ("qubit_names name not a string", provider_body(compiled__qubit_names={"0": 7}), ["provider_members"]), ("qubit_names without a layout entry", provider_body(compiled__qubit_names={"1": "Q1"}), ["provider_members"]), ("qubit_names without a final_layout entry", provider_body( compiled__final_layout=[1], compiled__qubit_names=names), ["provider_members"]), ("qubit_names holds more than the layouts", provider_body(compiled__qubit_names={"0": "Q0", "5": "Q5"}), []), ("qubit_names: an entry however written", provider_body( compiled__layout=[1.0], compiled__final_layout=[1e0], compiled__qubit_names={"0": "Q0", "1": "Q1"}), []), ("qubit_names: an entry in full", provider_body( compiled__layout=[1e21], compiled__final_layout=[1e21], compiled__qubit_names={"0": "Q0", "1000000000000000000000": "Q"}), []), ("qubit_names: not as a number's text", provider_body( compiled__layout=[1e21], compiled__final_layout=[1e21], compiled__qubit_names={"0": "Q0", "1e+21": "Q"}), ["provider_members"]), ("qubit_names not read in the earlier form", provider_body( counts_source=_DELETE, execution=_DELETE, accuracy__class="measured", compiled__qubit_names=None), []), # §8.4: a whole number however large; only a count's value has a ceiling; a sum exact. ("a whole number however large", provider_body(job__polls=1e300, compiled__swaps=two_to_53), []), ("a count past its ceiling", provider_body( request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":%d' % two_to_53), counts={"1": two_to_53}, shots=two_to_53), ["counts"]), ("shots past a count's ceiling", provider_body( request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":%d' % two_to_54), counts={"00": two_to_53 - 1, "01": two_to_53 - 1, "10": 2}, distinct_outcomes=3, shots=two_to_54), []), ("a sum exact, not a double's", provider_body( request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":%d' % two_to_54), counts={"00": two_to_53 - 1, "01": two_to_53 - 1, "10": 3}, distinct_outcomes=3, shots=two_to_54), ["counts"]), # §8.4: "the request's" is by value. ("the request's shots by value", provider_body( request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":4.0')), []), ("two equal strings are the same", provider_body( request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":"4"'), shots="4"), ["counts"]), ("a string is not a number", provider_body( request=_PROVIDER_REQUEST.replace('"shots":4', '"shots":"4"')), ["request_shots"]), ("native-turns with noise", provider_body(provider__kind="native-turns", counts_source="probabilities", execution=noise_row), []), ("native-turns with noise on silicon", provider_body( provider__kind="native-turns", counts_source="probabilities", provider__provenance="silicon", accuracy__class="measured", execution=noise_row), ["execution"]), ("native-turns without noise on silicon", provider_body( provider__kind="native-turns", counts_source="probabilities", provider__provenance="silicon", accuracy__class="measured", execution=dict(ROWS["native-turns"][0][2])), []), ("a later kind's settings names", provider_body(provider__kind="later", execution=dict( prx_row, twirling="off", sent={"fields": ["a", "b~c"], "settings": { "/b~0c/x": 1, "any_name": True}})), []), ("a settings key ''", provider_body(provider__kind="later", execution=dict( prx_row, twirling="off", sent={"fields": ["a"], "settings": {"": 1}})), ["execution"]), ("a pointer outside the fields", provider_body(provider__kind="later", execution=dict( prx_row, twirling="off", sent={"fields": ["a"], "settings": {"/z": 1}})), ["execution"]), ("a pointer's rest not read", provider_body(provider__kind="later", execution=dict( prx_row, twirling="off", sent={"fields": ["a"], "settings": {"/a/~2": 1}})), []), ("negative omitted_shots", provider_body(omitted_shots=-1, counts={"1": 5}), ["counts"]), ("negative swaps", provider_body(compiled__swaps=-1), ["provider_members"]), ("compiled program hash", provider_body(compiled__program="00" * 32), ["compiled_program"]), ("upper-case program hash", provider_body(compiled__program=blake3( _PROVIDER_QASM3.encode()).hex().upper()), ["provider_members"]), ("confirmed on a free run", provider_body(cost__confirmed=True), ["cost_confirmation"]), # §8.1, §8.4: a provider's own record takes a submit as the confirmation of a # run that is not free, and of no other. ("a provider's own record, confirmed by the submit", provider_body( cost__free=False, cost__confirmed=True, cost__confirmed_by="submit"), []), ("a free run confirmed by the submit", provider_body(cost__confirmed_by="submit"), ["cost_confirmation"]), ("confirmed_by of no value", provider_body( cost__free=False, cost__confirmed=True, cost__confirmed_by="person"), ["cost_confirmation"]), ("confirmed_by null", provider_body( cost__free=False, cost__confirmed=True, cost__confirmed_by=None), ["cost_confirmation"]), ("confirmed_by beside confirmed null", provider_body( cost__free=False, cost__confirmed=None, cost__confirmed_by="submit"), ["cost_confirmation", "provider_members"]), ("earlier form must be measured", provider_body(counts_source=_DELETE, execution=_DELETE), ["provider_class"]), ("earlier form, measured", provider_body(counts_source=_DELETE, execution=_DELETE, accuracy__class="measured", provider__describe=_DELETE), []), ) for name, raw_case, want in cases: check(name, reasons_of(raw_case) == want) # §8.4: qubit_names holds every index qasm3 acts on. def with_qasm3(text, names_given): return provider_body(compiled__qasm3=text, compiled__program=blake3(text.encode()).hex(), compiled__qubit_names=names_given) names_short = with_qasm3("x $0;\ncz $0, $1;\n", {"0": "Q0"}) for name, raw_case, want in ( ("qasm3 acts on an index not named", names_short, ["provider_members"]), ("qasm3's indices named", with_qasm3("x $0;\ncz $0, $1;\n", {"0": "Q0", "1": "Q1"}), []), ("qasm3 $01 names 1", with_qasm3("x $0;\nx $01;\n", {"0": "Q0", "1": "Q1"}), []), ("qasm3 $12 names 12", with_qasm3("x $0;\nx $12;\n", {"0": "Q0", "1": "Q1"}), ["provider_members"]), ("qasm3: a $ with no digit names none", with_qasm3("x $0;\n// $ and $x\n", {"0": "Q0"}), []), ("qasm3 with names absent", with_qasm3("x $0;\ncz $0, $1;\n", _DELETE), []), ("qasm3: a long run of zeros", with_qasm3("x $" + "0" * 5000 + ";\n", {"0": "Q0"}), [])): check(name, reasons_of(raw_case) == want) # §8.6: a set's receipt. program_a = "OPENQASM 3.0;\nqubit[1] q;\nbit[1] c;\nx q[0];\nc = measure q;\n" program_b = "OPENQASM 3.0;\nqubit[1] q;\nbit[1] c;\nc = measure q;\n" programs_request = {"programs": [program_a, {"qasm": program_b, "shots": 5}], "shots": 10, "dry_run": False} programs_items = [{"shots": 10, "qasm": program_a}, {"shots": 5, "qasm": program_b}] def programs_of(n): return ({"programs": [program_a] * n, "shots": 10}, [{"shots": 10, "qasm": program_a}] * n) sweep_request = {"qasm": "OPENQASM 3.0;\ninput angle t;\nqubit[1] q;\nrx(t) q[0];\n", "shots": 10, "sweep": {"t": [0.5, 1], "u": [1, 2, 3]}} sweep_items = [{"shots": 10, "qasm": "OPENQASM 3.0;\nqubit[1] q;\nrx(%d) q[0];\n" % i} for i in range(6)] def set_of(n, **kw): asked, items = programs_of(n) return _set_body(seed, asked, items, **kw) def drop(member): return lambda head, items: head.pop(member) def wrong_root(head, items): head["root"] = "ab" * 32 def tamper_count(items): items[0]["result"]["counts"] = {"1": 11} def tamper_after(head, items): items[0]["result"]["counts"] = {"1": 11} def swap_path(head, items): items[0]["path"][0] = "cd" * 32 def longer_path(head, items): items[0]["path"].append(head["root"]) def index_off(head, items): items[1]["index"] = 7 def both(head, items): items[0]["error"] = "and an error" def upper_path(head, items): items[0]["path"][0] = items[0]["path"][0].upper() def unsealed_members(head, items): for i, item in enumerate(items): item.update(status="done", method="statevector", why="a fixture", point={"t": i}) def drop_key(head, items): head["_drop_key"] = True # _seal_set removes it, and the receipt's key def upper_key(head, items): head["_upper_key"] = True def head_provider(head, items): head.update({"method": "provider", "accuracy": {"class": "measured"}}) set_cases = ( ("set of programs", _set_body(seed, programs_request, programs_items), []), ("set of one", set_of(1), []), ("set of three, one an error", _set_body(seed, programs_of(3)[0], programs_of(3)[1], errors=(1,)), []), ("set of five", set_of(5), []), ("set of a sweep", _set_body(seed, sweep_request, sweep_items), []), ("set: sweep null is none", _set_body(seed, dict(programs_request, sweep=None), programs_items), []), ("set: count wrong", set_of(2, head_extra={"count": 3}), ["set_items"]), ("set: count missing", set_of(2, after_root=drop("count")), ["set_items"]), ("set: count 2.0 is 2", set_of(2, head_extra={"count": 2.0}), []), ("set: items emptied", set_of(2, after_root=lambda head, items: items.clear()), ["set_items"]), ("set: an index off stops the next two", set_of(2, after_root=lambda h, it: (index_off(h, it), tamper_after(h, it))), ["set_items"]), ("set: result and error both", set_of(2, after_root=both), ["set_items"]), ("set: a path digit upper-case", set_of(2, after_root=upper_path), ["set_items"]), ("set: an item not the program's", _set_body( seed, programs_request, [programs_items[0], dict(programs_items[1], shots=6)]), ["set_items"]), ("set: an item more than the programs", _set_body(seed, programs_request, programs_items + programs_items[:1]), ["set_items"]), ("set: programs and sweep both", _set_body(seed, dict(programs_request, sweep={"t": [1]}), programs_items), ["set_items"]), ("set: neither, and no items", _set_body(seed, {"shots": 10}, []), ["set_items"]), ("set: a sweep value empty", _set_body(seed, dict(sweep_request, sweep={"t": [], "u": [1]}), sweep_items[:0]), ["set_items"]), ("set: a sweep item's request otherwise", _set_body( seed, sweep_request, sweep_items[:5] + [dict(sweep_items[5], shots=11)]), ["set_items"]), ("set: a sweep of the wrong count", _set_body(seed, sweep_request, sweep_items[:5]), ["set_items"]), ("set: an item tampered before its leaf", set_of(2, before_root=tamper_count), ["set_item"]), ("set: an item tampered after the root", set_of(2, after_root=tamper_after), ["set_item", "set_root"]), ("set: the root another", set_of(2, after_root=wrong_root), ["set_root"]), ("set: a path's sibling another", set_of(3, after_root=swap_path), ["set_root"]), ("set: a path too long", set_of(2, after_root=longer_path), ["set_root"]), ("set: an item inexact", set_of(1, item_result=_ITEM_RESULT.replace('"gates":1', '"gates":9007199254740993')), ["set_item"]), ("set: its request inexact", _set_body( seed, dict(programs_of(1)[0], dry_run=Num("9007199254740993", 2.0 ** 53)), programs_of(1)[1]), ["inexact_number"]), ("set: no provider rules on a head", set_of(1, after_root=head_provider), []), ("set: an error item writes 2^53 + 1", _set_body( seed, dict(programs_of(1)[0], seed=2 ** 53), [dict(programs_of(1)[1][0], seed=Num("9007199254740993", 2.0 ** 53))], errors=(0,)), ["set_item"]), ("set: an error item writes 2^60 canonically", _set_body( seed, dict(programs_of(1)[0], seed=2 ** 60), [dict(programs_of(1)[1][0], seed=Num("1152921504606847000", 2.0 ** 60))], errors=(0,)), []), ("set: first form, an error item's u64 read as canonical", _set_body( seed, dict(programs_of(1)[0], seed=2 ** 53), [dict(programs_of(1)[1][0], seed=Num("9007199254740993", 2.0 ** 53))], errors=(0,), form="first"), ["set_item"]), ("set: first form, an error item's exact u64", _set_body( seed, dict(programs_of(1)[0], seed=2 ** 53), [dict(programs_of(1)[1][0], seed=2 ** 53)], errors=(0,), form="first"), []), ("set: first form, an error item past u64", _set_body( seed, dict(programs_of(1)[0], seed=2 ** 64), [dict(programs_of(1)[1][0], seed=Num("18446744073709551617", 2.0 ** 64))], errors=(0,), form="first"), ["set_item"]), ("set: first form sealed", set_of(2, form="first"), []), ("set: an item signed by another key", set_of(2, item_seed=bytes([7] * 32)), ["set_item"]), ("set: an item's result a set's", set_of(1, item_result=_ITEM_RESULT.replace( '"method"', '"format":"wai.quantum.set/1","method"')), ["set_item"]), ("set: an item's unsealed members", set_of(2, after_root=unsealed_members), []), ("set: an item's unsealed members changed", set_of(2, after_root=lambda h, it: ( unsealed_members(h, it), it[0].update(status="failed", method=7, why=None, point=[]))), []), ("set: an item receipt's own extra member", set_of(2, after_root=lambda h, it: ( it[0]["result"]["receipt"].update(note="ignored", x=[1, 2]))), []), ("set: its receipt with no key", set_of(1, after_root=drop_key), ["receipt_form", "set_item"]), ("set: its key in upper case", set_of(1, after_root=upper_key), ["receipt_form", "set_item"]), ) for name, raw_case, want in set_cases: check(name, reasons_of(raw_case) == want) sealed_set = set_of(2) check("set: the head tampered", reasons_of(sealed_set.replace(b'"count": 2', b'"count": 3')) == ["digest_mismatch", "set_items"]) unlisted = json.loads(sealed_set.decode()) del unlisted["result"]["items"] check("set: items missing", reasons_of(json.dumps(unlisted).encode()) == ["set_items"]) check("set: no receipt, alone", reasons_of(json.dumps( {"request": {}, "result": {"format": SET_FORMAT, "items": 5}}).encode()) == ["no_receipt"]) # quantum-wasmq §6.5: the wasmQ jobs of _wasmq_tables, each judged once: its reasons, the # rules it breaks, and its statement's problems, one entry a rule, in order, there # exactly when wasmq_form is reported (another job states nothing). Each rule from 2 to # the last is broken alone by one case at least; rule 1 cannot be (see the table). def rules_of(raw): job = read_json(raw) return wasmq_broken(job["request"], job["result"]) def problem_rules(v): return [int(p.split(":", 1)[0][len("rule "):]) for p in v["wasmq"]["problems"]] wasmq_cases, statement_cases, verdict_cases = _wasmq_tables() unstated = [] for name, raw_case, want, rules in wasmq_cases: v = judge(raw_case) check(name, v["reasons"] == want) if rules is None: held = "wasmq" not in v else: check(name + ": its rules", rules_of(raw_case) == rules) held = ("wasmq" in v and problem_rules(v) == rules and all(p.startswith("rule ") for p in v["wasmq"]["problems"]) and ("wasmq_form" in v["reasons"]) == bool(rules)) if not held: unstated.append(name) alone = set(rules[0] for _, _, want, rules in wasmq_cases if want == ["wasmq_form"] and len(rules) == 1) # Rule 27 is never broken alone: a lifecycle fault at shot 0 has shots_run 0 (rule 18), so # rule 32 holds the callouts to 0 (and rule 15 to a count) as rule 27 does. check("wasmq: each of rules 2 to %d but 27 broken alone" % WASMQ_RULES, alone == set(range(2, WASMQ_RULES + 1)) - {27}) check("wasmq statement: its problems are the rules broken, in all %d cases%s" % ( len(wasmq_cases), (": " + ", ".join(unstated)) if unstated else ""), not unstated) exported = [name for name, _, _ in wasmq_case_lines()] check("wasmq: the %d cases --wasmq-cases writes have distinct names" % len(exported), len(set(exported)) == len(exported)) for name, raw_case, want, alone_verdict in verdict_cases: v = judge(raw_case) check(name, v == _verdict(want) if alone_verdict else v["reasons"] == want) for name, raw_case, want, want_statement in statement_cases: v = judge(raw_case) check("wasmq statement: " + name, v["reasons"] == want and v.get("wasmq") == want_statement) check("wasmq statement: method provider states its provider too", "provider" in judge(_wasmq_job(result={"method": "provider"}))) check("wasmq statement: the first 64 problems, then how many more", _first_and_more(["p%d" % i for i in range(70)]) == ["p%d" % i for i in range(64)] + ["and 6 more"] and _first_and_more(["p"] * 64) == ["p"] * 64 and _first_and_more([]) == []) wasmq_asked, wasmq_made = _wasmq_parts(False) check("wasmq statement: a set holding a wasmQ job states none", "wasmq" not in judge(_set_body( _WASMQ_SEED, {"programs": [wasmq_asked]}, [wasmq_asked], item_result=_dump(wasmq_made)))) check("wasmq statement: another job states none", "wasmq" not in judge(body)) # The scan of sent.settings against sent.fields is linear. Every key names the last # field, so a scan of the list walks all of it each time (tens of seconds). many_fields = ["f%06d" % i for i in range(50000)] many_settings = dict(("/%s/k%d" % (many_fields[-1], i), i) for i in range(50000)) many = dict(prx_row, twirling="off", sent={"fields": many_fields, "settings": many_settings}) started = time.perf_counter() many_hold = execution_rules_hold(many) check("50,000 fields and 50,000 settings, within 3 s", many_hold and time.perf_counter() - started < 3.0) # Each plant changes a verdict a differential would compare. def held(raw, trust=None, at_ms=None, skew_ms=0): """A job's verdict, its receipt held to a trust list (its text) and a time (§8.8).""" before = dict(HOLD) HOLD.update(trust=None if trust is None else read_trust(trust), at_ms=at_ms, skew_ms=skew_ms) try: return judge(raw) finally: HOLD.update(before) def planted(plant, raw, holding=None): if holding is not None: PLANTS.add(plant) try: return held(raw, **holding)["reasons"] finally: PLANTS.discard(plant) PLANTS.add(plant) try: return judge(raw)["reasons"] finally: PLANTS.discard(plant) # §8.7: a job under a contract, as it is and broken one way at a time. def contract_body(job_seed=None, extra_routes=(), **changes): return _seal(seed, *_contract_job(seed=job_seed, extra_routes=extra_routes, **changes)) def local_body(contract, routes, choice, auto, stable_choice, kept, **kw): return _seal(seed, *_local_contract_job(contract, routes, choice, auto, stable_choice, kept, **kw)) def stopped_body(**changes): request, result = _local_contract_job({"exactness": "exact", "max_joules": 2}, [ _lr("exact", "bit-exact", 20, "chosen", joules=1.0), _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, {"energy": {"max_joules": 2, "joules": 2.5, "kept": False}}, result_class="none") both = {"request": json.loads(request), "result": json.loads(result)} del both["result"]["counts"] both["result"]["stopped"] = {"at": "max_joules", "joules": 2.5, "max_joules": 2, "elapsed_ms": 3, "read": "a test's reading"} for path, value in changes.items(): node = both parts = path.split("__") for part in parts[:-1]: node = node[part] if value is _DELETE: del node[parts[-1]] else: node[parts[-1]] = value return _seal(seed, json.dumps(both["request"], separators=(",", ":")), json.dumps(both["result"], separators=(",", ":"))) def energy_routes(statevector): return local_body({"exactness": "exact", "max_joules": 2}, [ _lr("exact", "bit-exact", 20, "chosen", joules=1.0), statevector, _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, {"energy": {"max_joules": 2, "joules": 2.0, "kept": True}}, energy={"joules_micro": 2000000}) def read_and_not(): r = _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0) r["price"]["energy"]["unwatched"] = "and yet" return r check("a stop on a provider's run, which nothing here reads", "stopped" in reasons_of(stopped_body(result__method="provider"))) def contract_edited(edit): request, text = _contract_job(seed=None, extra_routes=()) body = {"request": json.loads(request), "result": json.loads(text)} edit(body) return _seal(seed, json.dumps(body["request"], separators=(",", ":")), json.dumps(body["result"], separators=(",", ":"))) def chosen(b): return next(r for r in b["result"]["planner"]["routes"] if r["route"] == b["result"]["planner"]["choice"]) check("a run sealed at a cost its route does not state", reasons_of(contract_edited( lambda b: b["result"]["cost"].update(free=False, confirmed=True, estimate={"free": False, "amount": "50", "currency": "USD"}))) == ["planner_choice"]) check("the route chosen names another device than ran", reasons_of(contract_edited(lambda b: chosen(b).update(device="elsewhere"))) == ["planner_choice"]) check("members alike by value: 7 and 7.0, -0 and 0", _alike(Num("7", 7.0), Num("7.0", 7.0)) and _alike(Num("-0", -0.0), Num("0", 0.0))) check("a boolean is no number, and null is absent", not _alike(True, Num("1", 1.0)) and _alike(None, None) and not _alike("a", None)) check("lists and objects alike member by member", _alike([Num("7", 7.0)], [Num("7.0", 7.0)]) and _alike({"a": Num("-0", -0.0), "b": None}, {"a": Num("0", 0.0)}) and not _alike([True], [Num("1", 1.0)]) and not _alike({"a": "x"}, {"a": "y"})) check("an earlier-form provider result under a contract", "contract_form" in reasons_of(contract_edited( lambda b: [b["result"].pop(k) for k in ("counts_source", "execution")]))) check("the route chosen names the device that ran", reasons_of(contract_edited(lambda b: chosen(b).update(device=b["result"]["provider"]["device"]))) == []) def timed_by_host(kept): request, text = _local_contract_job({"exactness": "exact", "deadline_seconds": 60}, base(), "method:exact", "method:exact", True, kept) result = json.loads(text) del result["elapsed_ms"] return _seal(seed, request, json.dumps(result, separators=(",", ":"))) contract_ok = contract_body() check("a contract job's reasoning and shadow", reasons_of(contract_ok) == []) for name, raw_case, want in ( ("a contract that does not read", contract_body(request__contract={"exactness": "nearly"}), ["contract_form"]), ("a reasoning dropped", contract_body(result__planner=_DELETE), ["planner_form"]), ("a digest not the routes'", contract_body(result__planner__stable__digest="00" * 32), ["planner_stable"]), ("a choice said to be the host's own", contract_body(result__planner__stable__choice=True), ["planner_stable"]), ("a kept the contract does not ask", contract_body(result__planner__kept={"deadline": {}}), ["planner_kept"]), ("a class short of what is wanted", contract_body(result__accuracy__approximate=True), ["contract_class"]), ("a shadow on another seed", contract_body(result__shadow__request__seed=4), ["shadow"]), ("a shadow's omitted_shots of 0.0", contract_body(result__shadow__omitted_shots=0.0), []), ("a distance not computed, every shot listed", contract_body( result__shadow__distance={"computed": False, "why": "said so"}), ["shadow"]), ("the least it can come to, on a free route", contract_body( result__planner__routes__1__price__money={"free": True, "at_least": False}), ["planner_form"]), ("a named provider under never", contract_body(request__contract__providers="never"), ["contract_provider", "planner_choice", "planner_route"]), ("a shadow request with a noise model", contract_body( result__planner__shadow__request__noise={"depolarizing_2q": 0.2}, result__shadow__request__noise={"depolarizing_2q": 0.2}), ["shadow"]), ("a route with no watch, said to meet a ceiling", energy_routes(_lr("statevector", "exact", 30, "met", memory=2048, joules=1.0, watch=None)), ["planner_route"]), ("a watched route said to have no reading", energy_routes(_lr("statevector", "exact", 30, "rejected", "energy_unwatched", memory=2048, joules=1.0)), ["planner_route"]), ("a watch that is no sentence", local_body({"exactness": "exact", "max_joules": 2}, [ _lr("exact", "bit-exact", 20, "chosen", joules=1.0), _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0, watch=True), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, {"energy": {"max_joules": 2, "joules": 2.0, "kept": True}}, energy={"joules_micro": 2000000}), ["planner_form"]), ("a run stopped past no ceiling it has", stopped_body(result__stopped__max_joules=9), ["stopped"]), ("a run stopped under its ceiling", stopped_body(result__stopped__joules=1.5, result__planner__kept__energy__joules=1.5), ["stopped"]), ("a stopped run that gives an answer", stopped_body(result__counts={"1": 4}), ["stopped"]), ("a stopped run said to have kept its ceiling", stopped_body(result__planner__kept__energy__kept=True), ["planner_kept"]), ("a run stopped with no ceiling", stopped_body(request__contract={"exactness": "exact"}), ["planner_kept", "planner_stable", "stopped"]), ("a run stopped with no contract", stopped_body(request__contract=_DELETE), ["planner_form", "stopped"]), ("a reading exactly at the ceiling stops a run", stopped_body(result__stopped__joules=2, result__planner__kept__energy__joules=2), []), ("a stopped run that claims a class", stopped_body(result__accuracy__class="exact"), ["stopped"]), ("a stop that does not say what read it", stopped_body(result__stopped__read=7), ["stopped"]), ("a stop at a time that is no whole number", stopped_body(result__stopped__elapsed_ms=1.5), ["stopped"]), ("a stop with a member its form does not have", stopped_body(result__stopped__note="more"), ["stopped"]), ("a stop at something other than the energy ceiling", stopped_body(result__stopped__at="deadline"), ["stopped"]), ("an estimate exactly at the ceiling refuses nothing", energy_routes(_lr("statevector", "exact", 30, "met", memory=2048, joules=2.0)), []), ("a route said both to be read and to have no reading", energy_routes(read_and_not()), ["planner_form"]), # By hand: "1" 4 and 1 times, 5 pooled, E|2B - 5| = 1.875; half of it over 4. ("a shadow's counts short of its shots, the distance what they give", contract_body( result__shadow__counts={"1": 1}, result__shadow__distance={"computed": True, "numerator": 3, "denominator": 8, "total_variation": 0.375, "hellinger_fidelity": 0.25, "sampling_tvd_bound": 0.234375}), ["shadow"]), # By hand: "1" 4 and "x" 4 times, each pooled 4, E|2B - 4| = 1.5 twice; half of it over 4. ("a shadow's outcomes that are not bits, the distance what they give", contract_body( result__shadow__counts={"x": 4}, result__shadow__distance={"computed": True, "numerator": 8, "denominator": 8, "total_variation": 1.0, "hellinger_fidelity": 0.0, "sampling_tvd_bound": 0.375}), ["shadow"]), ("a shadow that says more outcomes than it lists", contract_body(result__shadow__distinct_outcomes=7), ["shadow"]), ("a shadow's class its method does not have", contract_body( result__planner__routes__0__route="method:mps", result__planner__routes__0__method="mps", result__planner__routes__0__class="heuristic", result__planner__routes__0__auto_rank=60, result__planner__stable__routes=["method:mps"], result__planner__shadow__route="method:mps", result__planner__shadow__class="heuristic", result__planner__shadow__request__method="mps", result__shadow__route="method:mps", result__shadow__request__method="mps"), ["planner_stable", "shadow"]), ("host.providers that are not its provider routes", contract_body(result__planner__host__providers=["someone-else"]), ["planner_form"]), ("a provider that states its memory", contract_body(result__planner__routes__1__price__memory_bytes=1024), ["planner_form"]), ("a provider's route said not to depend on the host", contract_body(result__planner__routes__1__host_dependent=False), ["planner_route"]), ("a method on no GPU said to depend on the host", contract_body(result__planner__routes__0__host_dependent=True), ["planner_route", "planner_stable"]), ("a built-in route stated a class it does not have", contract_body(result__planner__routes__0__class="exact"), ["planner_route", "planner_stable", "shadow"]), ("a method's result of a class it does not have", local_body({"exactness": "exact"}, [ _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {}, result_class="exact"), ["contract_class"]), ("a method's memory that is not stated", local_body({"exactness": "exact"}, [ _lr("exact", "bit-exact", 20, "chosen"), dict(_lr("statevector", "exact", 30, "met"), price={"money": {"free": True}, "time": {"seconds": 0.001, "basis": "nominal"}, "memory_bytes": None, "work": 8, "energy": {"joules": None, "why": "none"}, "leaves_out": []}), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {}), ["planner_form"]), ("a shadow planned at a class its route is not listed with", contract_body(result__planner__shadow__class="heuristic"), ["shadow"]), ("a time past what a price states", contract_body(result__planner__routes__1__price__time__seconds=1e306), ["planner_form"]), ): check(name, reasons_of(raw_case) == want) # §8.7, rule by rule: each case is valid, and a verifier that bends the rule it # holds to gives it a reason. Every outcome is written here by hand. approx = {"route": "provider:approx", "kind": "provider", "provider": "approx", "class": "simulated", "host_dependent": True, "approximate": True, "outcome": "rejected", "rejected": {"code": "class", "why": "approximate"}, "price": {"money": {"free": True}, "time": {"seconds": 1.0, "basis": "provider"}, "memory_bytes": None, "work": None, "energy": {"joules": None, "why": "none"}, "leaves_out": ["energy"]}} sim = dict(approx, provider="sim", route="provider:sim", outcome="met") del sim["approximate"], sim["rejected"] sim["price"] = dict(approx["price"], time={"seconds": 0.0, "basis": "provider"}) def base(cls_of_sv_single="class", **kw): return [_lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048, **kw), _lr("statevector_single", "single", 40, "rejected", cls_of_sv_single, host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)] routed = dict(request__provider=_DELETE, result__planner__named=None, result__planner__routes__0__rejected__code="class") ceiling = {"exactness": "simulated", "providers": "allowed", "max_cost": {"amount": "1", "currency": "USD"}} kept_free = {"cost": {"max_cost": {"amount": "1", "currency": "USD"}, "charged": None, "kept": True}} def provider_route(name, money, code, seconds=1.0): return {"route": "provider:" + name, "kind": "provider", "provider": name, "class": "simulated", "host_dependent": True, "outcome": "rejected", "rejected": {"code": code, "why": "said so"}, "price": {"money": money, "time": {"seconds": seconds, "basis": "provider"}, "memory_bytes": None, "work": None, "energy": {"joules": None, "why": "none"}, "leaves_out": ["energy"]}} sim_never = provider_route("sim", {"free": True}, "providers", seconds=0.0) for name, raw_case, want in ( ("the least it can come to is not within a ceiling", contract_body( extra_routes=(provider_route("least", {"free": False, "amount": "0.1", "currency": "USD", "at_least": True}, "cost_at_least"),), request__contract=ceiling, result__planner__kept=kept_free, **routed), []), ("a ceiling in another currency is not met", contract_body( extra_routes=(provider_route("euro", {"free": False, "amount": "0.1", "currency": "EUR"}, "cost_currency"),), request__contract=ceiling, result__planner__kept=kept_free, **routed), []), ("a cost with no ceiling is not met", contract_body( extra_routes=(provider_route("paid", {"free": False, "amount": "0.1", "currency": "USD"}, "cost_no_ceiling"),), **routed), []), ("a charge the result does not state", contract_body( request__contract=ceiling, result__planner__kept={"cost": dict(kept_free["cost"], charged={"amount": "0", "currency": "USD"})}, **routed), ["planner_kept"]), ("a planned shadow said not to have run", contract_body(result__shadow={"ran": False, "code": "none", "why": "said so"}), ["shadow"]), ("a plan's code that no plan has", contract_body( result__planner__shadow={"route": None, "code": "failed", "why": "said so"}, result__shadow={"ran": False, "code": "failed", "why": "said so"}), ["shadow"]), ("a provider under never, beside a local route", local_body({"exactness": "any"}, [ _lr("exact", "bit-exact", 20, "chosen", seconds=0.0001), _lr("statevector", "exact", 30, "met", seconds=0.0001, memory=2048), _lr("statevector_single", "single", 40, "rejected", "cannot", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "met", seconds=0.0001, memory=4096), sim_never], "method:exact", "method:exact", False, {}, providers=("sim",)), []), ("a time not known does not meet a deadline", local_body({"exactness": "exact", "deadline_seconds": 60}, [ _lr("exact", "bit-exact", 20, "chosen"), dict(_lr("statevector", "exact", 30, "rejected", "deadline_unknown"), price=dict(_lr("statevector", "exact", 30, "met")["price"], time={"seconds": None, "why": "not known"})), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), []), ("a deadline a host's timer kept, the result stating no time of its own", timed_by_host({"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), []), ("the matrix product state's route stated exact", local_body({"exactness": "exact", "deadline_seconds": 60}, base()[:3] + [_lr("mps", "exact", 60, "met", memory=4096)], "method:exact", "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), ["planner_route"]), ("a method the host registered, said not to depend on the host", local_body({"exactness": "exact", "deadline_seconds": 60}, base() + [_lr("turbo", "bit-exact", None, "met")], "method:exact", "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), ["planner_route"]), ("the same, said to depend on it", local_body({"exactness": "exact", "deadline_seconds": 60}, base() + [_lr("turbo", "bit-exact", None, "met", host_dependent=True)], "method:exact", "method:exact", False, {"deadline": {"seconds": 60, "elapsed_ms": 3, "kept": True}}), []), ("a deadline's time that is not the result's", local_body({"exactness": "exact", "deadline_seconds": 60}, base(), "method:exact", "method:exact", True, {"deadline": {"seconds": 60, "elapsed_ms": 4, "kept": True}}), ["planner_kept"]), ("auto said to be another route", local_body({"exactness": "exact"}, base(), "method:exact", "method:statevector", True, {}), ["planner_form"]), ("a built-in method's rank not its own", local_body({"exactness": "exact"}, [ _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048), _lr("statevector_single", "single", 0, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {}), ["planner_form"]), ("a local route that costs money", local_body({"exactness": "exact"}, [ _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=2048), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), dict(_lr("mps", "heuristic", 60, "rejected", "class", memory=4096), price=dict(_lr("mps", "heuristic", 60, "met")["price"], money={"free": False, "unknown": "a host's word"}))], "method:exact", "method:exact", True, {}), ["planner_form"]), ("a ceiling past 64 characters", local_body({"exactness": "exact", "max_cost": {"amount": "1" * 65, "currency": "USD"}}, base(), "method:exact", "method:exact", True, {"cost": {"max_cost": {"amount": "1" * 65, "currency": "USD"}, "charged": None, "kept": True}}), ["contract_form"]), ): check("rule: " + name, reasons_of(raw_case) == want) # The distance in its order, by hand: three shots of "1" against "0" twice and "1" # once. R = sqrt(3), and R*R/(S*S) is 0.33333333333333326, where (R/S)^2 is not. three = contract_body( request__shots=3, result__shots=3, result__counts={"1": 3}, result__planner__shadow__request__shots=3, result__shadow__request__shots=3, result__shadow__shots=3, result__shadow__counts={"0": 2, "1": 1}, result__shadow__distinct_outcomes=2, result__shadow__distance={"computed": True, "numerator": 4, "denominator": 6, "total_variation": 4 / 6, "hellinger_fidelity": 0.33333333333333326, "sampling_tvd_bound": 0.4166666666666667}) check("rule: the Hellinger fidelity in its order", reasons_of(three) == []) for name, raw_case in ( # Routed, no provider named: the approximate one is quicker, and not met. ("an approximate simulator does not meet simulated", contract_body( extra_routes=(approx,), request__provider=_DELETE, result__planner__named=None, result__planner__routes__0__rejected__code="class")), ("the shadow's seed wraps at 2^53", contract_body(job_seed=2 ** 53 - 2)), ("single does not meet bounded", local_body({"exactness": "bounded"}, base(), "method:exact", "method:exact", True, {})), ("a job's memory at its cap", local_body({"exactness": "exact"}, [ _lr("exact", "bit-exact", 20, "chosen"), _lr("statevector", "exact", 30, "met", memory=1 << 30), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096)], "method:exact", "method:exact", True, {})), ("a GPU's method off the CPU", local_body({"exactness": "single"}, base("fabric"), "method:exact", "method:exact", True, {}, request_extra={"fabric": "cpu"})), ("energy at its ceiling, and a host's estimate", local_body({"exactness": "exact", "max_joules": 2}, [ _lr("exact", "bit-exact", 20, "chosen", joules=1.0), _lr("statevector", "exact", 30, "met", memory=2048, joules=1.0), _lr("statevector_single", "single", 40, "rejected", "class", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "rejected", "class", memory=4096, joules=1.0)], "method:exact", "method:exact", False, {"energy": {"max_joules": 2, "joules": 2.0, "kept": True}}, energy={"joules_micro": 2000000})), ("a route no reading can stop, refused under a ceiling", energy_routes(_lr("statevector", "exact", 30, "rejected", "energy_unwatched", memory=2048, joules=1.0, watch=None))), ("an estimate past the ceiling refuses a watched route", energy_routes(_lr("statevector", "exact", 30, "rejected", "energy", memory=2048, joules=3.0))), ("a run stopped at its ceiling, and said so", stopped_body()), ("an approximate simulator named, under a contract that names no class", contract_body( request__contract={"providers": "allowed"}, result__planner__wanted_from="named", result__planner__routes__1__approximate=True)), ("a local route before a provider's at one time", local_body({"exactness": "any", "providers": "allowed"}, [ _lr("exact", "bit-exact", 20, "chosen", seconds=0.0001), _lr("statevector", "exact", 30, "met", seconds=0.0001, memory=2048), _lr("statevector_single", "single", 40, "rejected", "cannot", host_dependent=True, priced=False), _lr("mps", "heuristic", 60, "met", seconds=0.0001, memory=4096), sim], "method:exact", "method:exact", False, {}, providers=("sim",))), ): check("rule: " + name, reasons_of(raw_case) == []) unnamed_route = contract_body(result__planner__routes__0__outcome="met", result__planner__routes__0__rejected=_DELETE) another_answered = contract_body(result__provider__name="other") distance_said = contract_body(result__shadow__distance__numerator=1) # §8.2: a receipt that seals a time. The time is inside the digest (the domain's # byte 3, and its canonical text after the result's), and of one form. demo_key = _ed25519_sign(demo, b"")[0].hex() time_150 = '{"issued_ms":150,"not_after_ms":400}' timed_150 = _seal(demo, req, res, time_text=time_150) v = judge(timed_150) check("time: sealed, valid and stated", v["reasons"] == [] and v["time"] == { "sealed": True, "issued_ms": 150, "not_after_ms": 400}) check("time: none sealed, valid and said", judge(body)["reasons"] == [] and judge(body)["time"] == {"sealed": False}) check("time: no end sealed", judge(_seal(demo, req, res, time_text='{"issued_ms":0}'))["time"] == { "sealed": True, "issued_ms": 0, "not_after_ms": None}) check("time: written another way, the same time and digest", judge(_seal(demo, req, res, time_text='{"not_after_ms":4.0e2,"issued_ms":1.5E2}'))["time"] == v["time"] and reasons_of(timed_150.replace(b'"issued_ms":150', b'"issued_ms":15e1')) == []) check("time: the largest, 2^53 - 1", reasons_of(_seal( demo, req, res, time_text='{"issued_ms":9007199254740990,"not_after_ms":9007199254740991}')) == []) check("time: changed", reasons_of(timed_150.replace(b'"issued_ms":150', b'"issued_ms":151')) == ["digest_mismatch"]) check("time: its end taken off", reasons_of(timed_150.replace(b',"not_after_ms":400', b'')) == ["digest_mismatch"]) check("time: taken off", reasons_of(timed_150.replace(b',"time":' + time_150.encode(), b'')) == ["digest_mismatch"]) time_put_on = body.replace(b'"signature":', b'"time":{"issued_ms":150},"signature":') check("time: put on a receipt that sealed none", reasons_of(time_put_on) == ["digest_mismatch"]) check("time: sealed under the byte 2, as a receipt with no time", reasons_of(_seal(demo, req, res, receipt_extra={"time": {"issued_ms": 150}})) == ["digest_mismatch"]) for bad, why in ( ("null", "null"), ("150", "a number"), ('"2026-11-11T12:00:00Z"', "a string"), ("[150]", "an array"), ("{}", "no issue"), ('{"not_after_ms":400}', "an end and no issue"), ('{"issued_ms":null}', "a null issue"), ('{"issued_ms":-1}', "before 1970"), ('{"issued_ms":1.5}', "a fraction"), ('{"issued_ms":"150"}', "a string for the issue"), ('{"issued_ms":true}', "a boolean"), ('{"issued_ms":9007199254740992}', "past 2^53 - 1"), ('{"issued_ms":150,"not_after_ms":150}', "an end at the issue"), ('{"issued_ms":150,"not_after_ms":149}', "an end before the issue"), ('{"issued_ms":150,"not_after_ms":null}', "a null end"), ('{"issued_ms":150,"clock":"host"}', "another member")): v = judge(_seal(demo, req, res, time_text=bad)) check("time: receipt_form, %s" % why, v["reasons"] == ["receipt_form"] and v["key"] is None and "time" not in v) check("time: -0 is 0", judge(_seal(demo, req, res, time_text='{"issued_ms":-0}'))["time"]["issued_ms"] == 0 and reasons_of(_seal(demo, req, res, time_text='{"issued_ms":-0}')) == []) check("time: none on the first form", reasons_of( _seal(demo, req, res, form="first", receipt_extra={"time": {"issued_ms": 150}})) == ["receipt_form"]) # §8.8: held to a trust list and to a time, each rule at its bound. def trust_list(members, key=demo_key): return ('{"format":"wai.quantum.receipt-keys/1","algorithm":"ed25519","keys":[{"key":"%s",%s}]}' % (key, members)).encode() untimed = _seal(demo, req, res) def issued_at(ms): return _seal(demo, req, res, time_text='{"issued_ms":%d}' % ms) for name, raw, members, want in ( ("a key with no end takes a receipt of no time", untimed, '"not_before_ms":null', []), ("a key with a beginning takes a receipt of no time", untimed, '"not_before_ms":100', []), ("before its window", issued_at(99), '"not_before_ms":100', ["key_window"]), ("at its window's beginning", issued_at(100), '"not_before_ms":100,"not_after_ms":200', []), ("in its window's last moment", issued_at(199), '"not_before_ms":100,"not_after_ms":200', []), ("at its window's end", issued_at(200), '"not_before_ms":100,"not_after_ms":200', ["key_window"]), ("no time, and a window that ends", untimed, '"not_after_ms":200', ["key_window"]), ("before its revocation", issued_at(149), '"revoked_from_ms":150', []), ("at its revocation", issued_at(150), '"revoked_from_ms":150', ["key_revoked"]), ("no time, and a revoked key", untimed, '"revoked_from_ms":150', ["key_revoked"]), ("revoked from the start", issued_at(0), '"revoked_from_ms":0', ["key_revoked"]), ("outside its window and revoked", issued_at(300), '"not_after_ms":200,"revoked_from_ms":250', ["key_revoked", "key_window"]), ("a null end is no end", issued_at(300), '"not_after_ms":null,"revoked_from_ms":null', []), ("times written another way", issued_at(150), '"not_before_ms":1.5e2,"not_after_ms":151.0', [])): check("trust: %s" % name, held(raw, trust=trust_list(members))["reasons"] == want) other = "11" * 32 v = held(timed_150, trust=trust_list('"not_before_ms":null', key=other)) check("trust: a key the list does not name", v["reasons"] == ["key_untrusted"] and not v["valid"] and v["trust"] == {"listed": False}) v = held(timed_150, trust=trust_list('"not_before_ms":100,"not_after_ms":200'), at_ms=399) check("trust: what it was held to is stated", v["reasons"] == [] and v["trust"] == { "listed": True, "not_before_ms": 100, "not_after_ms": 200, "revoked_from_ms": None} and v["checked_at_ms"] == 399 and v["skew_ms"] == 0) check("trust: not held, nothing stated", "trust" not in judge(timed_150) and "checked_at_ms" not in judge(timed_150)) check("at: before its end", held(timed_150, at_ms=399)["reasons"] == []) check("at: at its end", held(timed_150, at_ms=400)["reasons"] == ["expired"]) check("at: at its issue", held(timed_150, at_ms=150)["reasons"] == []) check("at: before its issue", held(timed_150, at_ms=149)["reasons"] == ["issued_later"]) check("at: before its issue, within the skew", held(timed_150, at_ms=149, skew_ms=1)["reasons"] == []) check("at: before its issue, past the skew", held(timed_150, at_ms=140, skew_ms=9)["reasons"] == ["issued_later"]) check("at: no end sealed does not expire", held(issued_at(150), at_ms=MAX_SAFE)["reasons"] == []) check("at: no time sealed is held to none", held(untimed, at_ms=0)["reasons"] == []) check("held: beside the seal's own reasons", held( timed_150.replace(b'"issued_ms":150', b'"issued_ms":160'), trust=trust_list('"not_after_ms":155'), at_ms=450)["reasons"] == ["digest_mismatch", "expired", "key_window"]) check("held: a reason reported alone is held to nothing", held( b"[]", trust=trust_list('"not_after_ms":200'), at_ms=0) == { "valid": False, "reasons": ["not_a_job"], "key": None, "form": None}) check("held: a receipt not of its form is held to nothing", held( _seal(demo, req, res, time_text="null"), trust=trust_list('"not_after_ms":200'), at_ms=0)["reasons"] == ["receipt_form"]) good_list = trust_list('"not_before_ms":null,"not_after_ms":5e3,"current":false,"note":"kept"') check("trust list: read", read_trust(good_list) == {demo_key: (None, 5000, None)}) for name, raw in ( ("another format", good_list.replace(b"receipt-keys/1", b"receipt-keys/2")), ("no keys", good_list.replace(b'"keys"', b'"key_list"')), ("a key in upper case", good_list.replace(demo_key.encode(), demo_key.upper().encode())), ("a short key", good_list.replace(demo_key.encode(), demo_key[1:].encode())), ("a time with a fraction", good_list.replace(b"5e3", b"5000.5")), ("a time before 1970", good_list.replace(b"5e3", b"-1")), ("a time past 2^53 - 1", good_list.replace(b"5e3", b"9007199254740992")), ("a time as a string", good_list.replace(b"5e3", b'"5000"')), ("a revocation that is no time", good_list.replace(b'"note":"kept"', b'"revoked_from_ms":true')), ("a member named twice", good_list.replace(b'"note"', b'"key"')), ("a key listed twice", good_list.replace(b"]}", b',{"key":"' + demo_key.encode() + b'"}]}')), ("a transition that is not signed", good_list.replace(b'"note":"kept"', b'"transition":{"statement":{}}')), ("another algorithm", good_list.replace(b'"algorithm":"ed25519"', b'"algorithm":"p256"')), ("a null algorithm", good_list.replace(b'"algorithm":"ed25519"', b'"algorithm":null')), ("an entry that is no object", good_list.replace(b"]}", b",7]}")), ("not an object", b"[]"), ("two values", good_list + good_list), ("not UTF-8", good_list.replace(b"kept", b"\xff"))): try: read_trust(raw) refused = False except TrustRefused: refused = True check("trust list: refused, %s" % name, refused) # A rotation's statement on a list: it names the entry's key as the one retiring, # and both keys signed it. successor_seed = bytes(range(32, 64)) successor_key = _ed25519_sign(successor_seed, b"")[0].hex() statement = '{"format":"wai.quantum.key-transition/1","retiring":"%s","successor":"%s","at_ms":7}' % ( demo_key, successor_key) t_digest = blake3(TRANSITION_DOMAIN + text_of(read_json(statement.encode()), True).encode()) transition = '"transition":{"statement":%s,"retiring_signature":"%s","successor_signature":"%s"}' % ( statement, _ed25519_sign(demo, t_digest)[1].hex(), _ed25519_sign(successor_seed, t_digest)[1].hex()) check("trust list: a transition both keys signed", read_trust( trust_list('"not_after_ms":7,' + transition)) == {demo_key: (None, 7, None)}) for name, raw in ( ("on its successor's entry", trust_list('"not_before_ms":7,' + transition, key=successor_key)), ("changed after it was signed", trust_list('"not_after_ms":7,' + transition.replace('"at_ms":7', '"at_ms":8'))), ("its signatures exchanged", trust_list('"not_after_ms":7,' + transition.replace( "retiring_signature", "x").replace("successor_signature", "retiring_signature").replace( '"x"', '"successor_signature"')))): try: read_trust(raw) refused = False except TrustRefused: refused = True check("trust list: a transition refused, %s" % name, refused) simulator_measured = provider_body(accuracy__class="measured") duplicated = body.replace(b'{"request"', b'{"why":"a","why":"b","request"') plant_cases = ( ("lenient-key", forged, ["bad_key"], []), ("no-alg", body.replace(b'"alg":"ed25519"', b'"alg":"ed448"'), ["receipt_form"], []), ("last-duplicate", duplicated, ["unreadable"], []), ("no-inexact", big, ["inexact_number"], []), ("measured-simulator", simulator_measured, ["provider_class"], []), ("whole-cap", provider_body(job__polls=two_to_53), [], ["provider_members"]), ("lax-small-order-r", identity_r_body, ["bad_signature"], []), ("no-canonical-spelling", seeded("1152921504606847000"), [], ["inexact_number"]), ("set-seal-only", set_of(2, head_extra={"count": 3}), ["set_items"], []), ("names-layout-only", names_short, ["provider_members"], []), ("route-unchecked", unnamed_route, ["planner_route"], []), ("choice-unchecked", another_answered, ["planner_choice", "request_provider"], ["request_provider"]), ("distance-unchecked", distance_said, ["shadow"], []), ("wasmq-unchecked", _wasmq_unchecked_job(), ["wasmq_form"], []), ("landscape-unchecked", _landscape_job(state_hash="0000000000000000"), ["landscape_form"], []), ("landscape2-unchecked", _landscape_job_2(sample=True, joules={"kind": "priced", "pj": 3, "metered": None}), ["landscape_form"], []), ("time-outside-digest", time_put_on, ["digest_mismatch"], []), ("window-end-inside", timed_150, ["key_window"], [], {"trust": trust_list('"not_after_ms":150')}), ("untimed-anywhere", untimed, ["key_revoked", "key_window"], [], {"trust": trust_list('"not_after_ms":150,"revoked_from_ms":0')}), ) for case in plant_cases: plant, raw, strict, lenient = case[:4] holding = case[4] if len(case) > 4 else None check("plant %s: strict verdict" % plant, (reasons_of(raw) if holding is None else held(raw, **holding)["reasons"]) == strict) check("plant %s: planted verdict" % plant, planted(plant, raw, holding) == lenient) check("every plant is tested", set(c[0] for c in plant_cases) == set(PLANTS_KNOWN)) # An energy-landscape job (quantum-landscape §5.4): one that holds every rule, and one # change at each rule that can be made alone, each that rule's landscape_form. check("landscape: a run that holds every rule", reasons_of(_landscape_job()) == []) for name, job in ( ("rule 2, its schema", _landscape_job(schema="wai.quantum.job-result/1")), ("rule 3, a seed of no form", _landscape_job(request={"program": "vars 2\nagree 0 1\nminimize\n", "seed": "1x"})), ("rule 4, no operation", _landscape_job(state=None)), ("rule 5, an empty label", _landscape_job(label="")), ("rule 6, a reference that is not cpu:reference", _landscape_job(member={"id": "gpu:x", "class": "gpu", "kernel": L_SETTLE, "parity": "reference"})), ("rule 7, demoted at a grade", _landscape_job(member={"id": "fpga:x", "class": "fpga", "kernel": L_SETTLE, "parity": "uncertified", "demoted": 1})), ("rule 8, under the floor", _landscape_job(member={"id": "fpga:x", "class": "fpga", "kernel": L_SETTLE, "parity": "bit-exact", "capacity": {"cells": 31}}, audit={"checked": [{}]})), ("rule 9, bit-exact with no audit", _landscape_job(member={"id": "fpga:x", "class": "fpga", "kernel": L_SETTLE, "parity": "bit-exact"})), ("rule 10, another replay digest", _landscape_job(replay="0" * 64)), ("rule 10, reached where the energy is not the lowest", _landscape_job(reached=True)), ("rule 13, a provider's members on a job that names none", _landscape_job(job={"id": "x", "polls": 0})), ): check("landscape: %s" % name, reasons_of(job) == ["landscape_form"]) check("landscape: an audit with a grade that earns it", reasons_of(_landscape_job(member={"id": "fpga:x", "class": "fpga", "kernel": L_SETTLE, "parity": "bit-exact", "capacity": {"cells": 64}}, audit={"checked": [{}]})) == []) # The second version (quantum-landscape-2 §5.4): a settle and a sampling run that hold # every rule, and one change at each rule that version changes, each landscape_form. check("landscape/2: a settle that holds every rule, its joules priced", reasons_of(_landscape_job_2()) == []) check("landscape/2: a sampling run that holds every rule, its joules unpriced", reasons_of(_landscape_job_2(sample=True)) == []) second_program = "vars 2\ncost -1\nagree 0 1\nminimize\n" first_digest = blake3(LANDSCAPE.encode() + b"\0" + struct.pack("