open-standards/wai/wai-quantum-py/notebooks/bell-receipt.ipynb
Transaction Science 073c5909aa
Some checks failed
wai-quantum docs, course and locales / does this change touch it (push) Successful in 17s
wai-quantum for Python / does this change touch it (push) Successful in 19s
repository checks / lockfiles, advisories, tests in CI, workflow hygiene, spec and section references, public text (push) Failing after 4m40s
WAI breaking changes and the conformance runner / WAI breaking · does this change touch WAI (push) Successful in 11s
wai-quantum docs, course and locales / the Studio's words in every locale · linux (push) Successful in 26s
wai-quantum docs, course and locales / the course and the command line's languages · linux (push) Successful in 3m56s
wai-quantum for Python / python · linux (push) Successful in 7m58s
wai-quantum for Python / python · macos (push) Successful in 3m14s
wai-quantum docs, course and locales / every command and snippet in the docs · linux (push) Successful in 21m25s
WAI breaking changes and the conformance runner / WAI breaking · wire, record and API against main · linux (push) Successful in 1m4s
WAI breaking changes and the conformance runner / WAI breaking and conform · their tests, and the independent verifiers through wai conform · linux (push) Successful in 9m28s
wai-quantum-py: the receipt notebook's stored verdict states what the receipt seals of its time
A verdict now says whether its receipt seals a time (`'time': {'sealed': False}` for one
that seals none), and the notebook's stored output for `verify` is held to what a run
prints: the Python workflow's notebook check failed on it after 3fc116ef0.

Changelog: none
Co-Authored-By: Claude Fable 5.2 <[email protected]>
2026-11-11 10:52:17 -05:00

331 lines
16 KiB
Text

{
"cells": [
{
"cell_type": "markdown",
"id": "bell-receipt-0",
"metadata": {},
"source": [
"# A Bell pair and its receipt\n",
"\n",
"A receipt is an Ed25519 signature over the request and the result in their RFC 8785 canonical JSON. This page seals a Bell pair, writes it to a file, checks it, and shows what breaks it."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "bell-receipt-1",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:53.957728Z",
"iopub.status.busy": "2026-11-11T12:23:53.957650Z",
"iopub.status.idle": "2026-11-11T12:23:53.962287Z",
"shell.execute_reply": "2026-11-11T12:23:53.962075Z"
}
},
"outputs": [],
"source": [
"import json\n",
"import wai_quantum as wq"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "bell-receipt-2",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:53.963230Z",
"iopub.status.busy": "2026-11-11T12:23:53.963158Z",
"iopub.status.idle": "2026-11-11T12:23:53.965590Z",
"shell.execute_reply": "2026-11-11T12:23:53.965396Z"
}
},
"outputs": [
{
"data": {
"text/plain": [
"Key(did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd, in memory)"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# A fixed key for this page, so that its receipts repeat byte for byte when it runs\n",
"# again. Keep a key of your own: wq.Key.generate().save(\"my.key\"), then\n",
"# wq.Key.from_file(\"my.key\"); with no key given, wq.run signs with this user's key,\n",
"# the command line's.\n",
"key = wq.Key(bytes(range(32)))\n",
"key"
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "bell-receipt-3",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:53.966180Z",
"iopub.status.busy": "2026-11-11T12:23:53.966120Z",
"iopub.status.idle": "2026-11-11T12:23:54.007110Z",
"shell.execute_reply": "2026-11-11T12:23:54.006461Z"
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "b4e78a73d73b41d8bc8f80167b7e417f",
"version_major": 2,
"version_minor": 1
},
"text/html": [
"<div class=\"wq-result\" style=\"font-family:ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;font-size:13px;line-height:1.45;border:1px solid var(--jp-border-color2,rgba(127,127,127,.35));border-radius:8px;padding:10px 12px;margin:2px 0;max-width:100%;overflow-x:auto\"><div><b>stabilizer</b> · accuracy <b>exact</b></div><div style=\"opacity:.7\">Clifford circuit: the stabilizer tableau of 2 qubits</div><div style=\"margin-top:6px\">2000 shots, 2 distinct outcomes; the 2 most frequent:</div><svg xmlns=\"http://www.w3.org/2000/svg\" class=\"wq-histogram\" width=\"370\" height=\"40\" viewBox=\"0 0 370 40\" role=\"img\" aria-label=\"Counts of 2 outcomes\"><text x=\"34\" y=\"11\" text-anchor=\"end\" dominant-baseline=\"central\" fill=\"currentColor\" style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\">00</text><rect x=\"40\" y=\"4\" width=\"260.0\" height=\"14\" rx=\"2\" fill=\"#7aa0ff\"><title>00: 1028 of 2000</title></rect><text x=\"306.0\" y=\"11\" dominant-baseline=\"central\" fill=\"currentColor\" style=\"font-size:11px\">1028</text><text x=\"34\" y=\"29\" text-anchor=\"end\" dominant-baseline=\"central\" fill=\"currentColor\" style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\">11</text><rect x=\"40\" y=\"22\" width=\"245.8\" height=\"14\" rx=\"2\" fill=\"#7aa0ff\"><title>11: 972 of 2000</title></rect><text x=\"291.8\" y=\"29\" dominant-baseline=\"central\" fill=\"currentColor\" style=\"font-size:11px\">972</text></svg><table style=\"border-collapse:collapse;margin-top:6px\"><tr><th style=\"text-align:left;padding:1px 10px 1px 0;font-weight:600\">observable</th><th style=\"text-align:left;padding:1px 10px 1px 0;font-weight:600\">value</th><th style=\"text-align:left;padding:1px 10px 1px 0;font-weight:600\">error</th></tr><tr><td style=\"padding:1px 10px 1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\">Z0 Z1</td><td style=\"padding:1px 10px 1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\">1</td><td style=\"padding:1px 10px 1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\"></td></tr><tr><td style=\"padding:1px 10px 1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\">X0 X1</td><td style=\"padding:1px 10px 1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\">1</td><td style=\"padding:1px 10px 1px 0;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\"></td></tr></table><div style=\"margin-top:6px\">receipt <span class=\"wq-badge\" style=\"display:inline-block;padding:0 7px;border-radius:9px;font-size:11px;font-weight:600;color:#fff;background:#10b981\">verified</span> signed by <span style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px\" title=\"did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd\">did:key:z6Mkeh…howQdcjqSJgvVd</span></div></div>"
],
"text/plain": [
"Result(stabilizer, accuracy exact, 2000 shots, 2 expectation values)"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"bell = \"OPENQASM 3.0; qubit[2] q; bit[2] c; h q[0]; cx q[0], q[1]; c = measure q;\"\n",
"job = wq.run(bell, shots=2000, seed=1, observables=[\"Z0 Z1\", \"X0 X1\"], key=key)\n",
"wq.Result(job)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "bell-receipt-4",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:54.008082Z",
"iopub.status.busy": "2026-11-11T12:23:54.007993Z",
"iopub.status.idle": "2026-11-11T12:23:54.011349Z",
"shell.execute_reply": "2026-11-11T12:23:54.011037Z"
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "7b085602350c47188c2e7df0b5fbc222",
"version_major": 2,
"version_minor": 1
},
"text/html": [
"<div class=\"wq-receipt\" style=\"font-family:ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;font-size:13px;line-height:1.45;border:1px solid var(--jp-border-color2,rgba(127,127,127,.35));border-radius:8px;padding:10px 12px;margin:2px 0;max-width:100%;overflow-x:auto\"><div>receipt <span class=\"wq-badge\" style=\"display:inline-block;padding:0 7px;border-radius:9px;font-size:11px;font-weight:600;color:#fff;background:#10b981\">verified</span> <span style=\"opacity:.7\">checked here, binding the request and the result as given</span></div><table style=\"border-collapse:collapse;margin-top:6px\"><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">signer</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\"><span title=\"did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd\">did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd</span></td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">key</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8</td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">digest</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">a80f7e659df721f1136cfb3aaa63b983a4c976c5421ae76671c8bebdb6c6353d</td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">signature</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">6b1619335dcdaa9f…98e57c8fe1e95c00</td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">form</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">ed25519 over rfc8785 canonical JSON</td></tr></table></div>"
],
"text/plain": [
"Receipt(valid, signed by did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd)"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"wq.Receipt(job)"
]
},
{
"cell_type": "markdown",
"id": "bell-receipt-5",
"metadata": {},
"source": [
"## What is signed\n",
"\n",
"The digest is BLAKE3 over a domain tag and the canonical text of the request and of the result without its receipt. Any JSON reader and writer can carry the job: the canonical text, and so the digest, stays the same."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "bell-receipt-6",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:54.012323Z",
"iopub.status.busy": "2026-11-11T12:23:54.012253Z",
"iopub.status.idle": "2026-11-11T12:23:54.014046Z",
"shell.execute_reply": "2026-11-11T12:23:54.013789Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{\"observables\":[\"Z0 Z1\",\"X0 X1\"],\"qasm\":\"OPENQASM 3.0; qubit[2] q; bit[2] c; h q[0]; cx q[0], q[1]; c = measure q;\",\"seed\":1,\"shots\":2000}\n",
"True\n"
]
}
],
"source": [
"result = {k: v for k, v in job.result.items() if k != \"receipt\"}\n",
"print(wq.canonical(job.request).decode())\n",
"print(wq.digest(job.request, result) == job.receipt[\"digest\"])"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "bell-receipt-7",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:54.014891Z",
"iopub.status.busy": "2026-11-11T12:23:54.014819Z",
"iopub.status.idle": "2026-11-11T12:23:54.016655Z",
"shell.execute_reply": "2026-11-11T12:23:54.016408Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"{'valid': True, 'reasons': [], 'key': '03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8', 'form': 'rfc8785', 'time': {'sealed': False}, 'signer': 'did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd'}\n"
]
}
],
"source": [
"with open(\"bell-job.json\", \"w\") as f:\n",
" json.dump(job, f)\n",
"print(wq.verify(\"bell-job.json\"))"
]
},
{
"cell_type": "markdown",
"id": "bell-receipt-8",
"metadata": {},
"source": [
"The command line checks the same file the same way: `wai-quantum verify bell-job.json`."
]
},
{
"cell_type": "markdown",
"id": "bell-receipt-9",
"metadata": {},
"source": [
"## What breaks it"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "bell-receipt-10",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:54.017376Z",
"iopub.status.busy": "2026-11-11T12:23:54.017293Z",
"iopub.status.idle": "2026-11-11T12:23:54.019999Z",
"shell.execute_reply": "2026-11-11T12:23:54.019691Z"
}
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"one more count valid: False\n",
"another seed valid: False\n",
"another method named valid: False\n"
]
}
],
"source": [
"for what, change in [\n",
" (\"one more count\", lambda j: j[\"result\"][\"counts\"].__setitem__(\"00\", j[\"result\"][\"counts\"][\"00\"] + 1)),\n",
" (\"another seed\", lambda j: j[\"request\"].__setitem__(\"seed\", 2)),\n",
" (\"another method named\", lambda j: j[\"result\"].__setitem__(\"method\", \"statevector\")),\n",
"]:\n",
" forged = json.loads(json.dumps(job))\n",
" change(forged)\n",
" print(f\"{what:<22} valid: {wq.verify(forged).valid}\")"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "bell-receipt-11",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:54.020774Z",
"iopub.status.busy": "2026-11-11T12:23:54.020706Z",
"iopub.status.idle": "2026-11-11T12:23:54.023398Z",
"shell.execute_reply": "2026-11-11T12:23:54.023066Z"
}
},
"outputs": [
{
"data": {
"application/vnd.jupyter.widget-view+json": {
"model_id": "394648b8d10e43a68e7c24031afd8eb0",
"version_major": 2,
"version_minor": 1
},
"text/html": [
"<div class=\"wq-receipt\" style=\"font-family:ui-sans-serif,system-ui,-apple-system,'Segoe UI',sans-serif;font-size:13px;line-height:1.45;border:1px solid var(--jp-border-color2,rgba(127,127,127,.35));border-radius:8px;padding:10px 12px;margin:2px 0;max-width:100%;overflow-x:auto\"><div>receipt <span class=\"wq-badge\" style=\"display:inline-block;padding:0 7px;border-radius:9px;font-size:11px;font-weight:600;color:#fff;background:#ef4444\">INVALID</span> <span style=\"opacity:.7\">checked here, binding the request and the result as given</span></div><table style=\"border-collapse:collapse;margin-top:6px\"><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">signer</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\"><span title=\"did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd\">did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd</span></td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">key</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8</td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">digest</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">a80f7e659df721f1136cfb3aaa63b983a4c976c5421ae76671c8bebdb6c6353d</td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">signature</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">6b1619335dcdaa9f…98e57c8fe1e95c00</td></tr><tr><td style=\"padding:1px 12px 1px 0;opacity:.7\">form</td><td style=\"font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:12px;word-break:break-all\">ed25519 over rfc8785 canonical JSON</td></tr></table></div>"
],
"text/plain": [
"Receipt(INVALID, signed by did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd)"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"forged = json.loads(json.dumps(job))\n",
"forged[\"result\"][\"counts\"][\"00\"] += 1\n",
"wq.Receipt(forged)"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "bell-receipt-12",
"metadata": {
"execution": {
"iopub.execute_input": "2026-11-11T12:23:54.024007Z",
"iopub.status.busy": "2026-11-11T12:23:54.023935Z",
"iopub.status.idle": "2026-11-11T12:23:54.025198Z",
"shell.execute_reply": "2026-11-11T12:23:54.024999Z"
}
},
"outputs": [],
"source": [
"import os\n",
"os.remove(\"bell-job.json\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.15"
}
},
"nbformat": 4,
"nbformat_minor": 5
}