{
"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": [
"
stabilizer · accuracy exact
Clifford circuit: the stabilizer tableau of 2 qubits
2000 shots, 2 distinct outcomes; the 2 most frequent:
| observable | value | error |
|---|
| Z0 Z1 | 1 | |
| X0 X1 | 1 | |
receipt verified signed by did:key:z6Mkeh…howQdcjqSJgvVd
"
],
"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": [
"receipt verified checked here, binding the request and the result as given
| signer | did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd |
| key | 03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8 |
| digest | a80f7e659df721f1136cfb3aaa63b983a4c976c5421ae76671c8bebdb6c6353d |
| signature | 6b1619335dcdaa9f…98e57c8fe1e95c00 |
| form | ed25519 over rfc8785 canonical JSON |
"
],
"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": [
"receipt INVALID checked here, binding the request and the result as given
| signer | did:key:z6MkehRgf7yJbgaGfYsdoAsKdBPE3dj2CYhowQdcjqSJgvVd |
| key | 03a107bff3ce10be1d70dd18e74bc09967e4d6309ba50d5f1ddc8664125531b8 |
| digest | a80f7e659df721f1136cfb3aaa63b983a4c976c5421ae76671c8bebdb6c6353d |
| signature | 6b1619335dcdaa9f…98e57c8fe1e95c00 |
| form | ed25519 over rfc8785 canonical JSON |
"
],
"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
}