- Update key capabilities to include GPU marketplace, payments, billing, and governance - Expand CLI section from basic examples to 12 command groups with 90+ subcommands - Add detailed test results table showing 208 passing tests across 6 test suites - Update documentation links to reference new CLI reference and coordinator API docs - Revise test commands to reflect actual test structure (
12 KiB
AITBC Receipt Specification (Draft)
Overview
This document defines the canonical schema and serialization rules for receipts generated by the AITBC network after miners complete compute jobs. Receipts serve as tamper-evident evidence tying compute usage to token minting events.
Receipt Fields
| Field | Type | Required | Description |
|---|---|---|---|
version |
string | yes | Receipt schema version (e.g., "1.0"). |
receipt_id |
string | yes | Unique identifier for this receipt. SHOULD be globally unique (UUID or hash). |
job_id |
string | yes | Identifier of the coordinator job this receipt references. |
provider |
string | yes | Miner address/account that executed the job. |
client |
string | yes | Client address/account that requested the job. |
units |
number | yes | Compute units earned by the miner (token minting basis). |
unit_type |
string | yes | Unit denomination (e.g., "gpu_seconds", "token_ops"). |
price |
number | optional | Price paid by the client for the job (same unit as units if applicable). |
model |
string | optional | Model or workload identifier (e.g., "runwayml/stable-diffusion-v1-5"). |
prompt_hash |
string | optional | Hash of user prompt or workload input to preserve privacy. |
started_at |
integer | yes | Unix timestamp (seconds) when the job started. |
completed_at |
integer | yes | Unix timestamp when the job completed. |
duration_ms |
integer | optional | Milliseconds elapsed during execution. |
artifact_hash |
string | optional | SHA-256 hash of the result artifact(s). |
coordinator_id |
string | optional | Coordinator identifier if multiple coordinators exist. |
nonce |
string | optional | Unique nonce to prevent replay/double minting. |
chain_id |
integer | optional | Target chain/network identifier. |
metadata |
object | optional | Arbitrary key/value pairs for future extensions. |
signature |
object | conditional | Signature object (see below). |
Signature Object
| Field | Type | Required | Description |
|---|---|---|---|
alg |
string | yes | Signature algorithm (e.g., "Ed25519", "secp256k1"). |
key_id |
string | yes | Identifier of signing key (e.g., "miner-ed25519-2025-09"). |
sig |
string | yes | Base64url-encoded signature over the canonical receipt bytes. |
Receipts SHOULD be signed by either the miner, coordinator attester, or both depending on trust model. Multiple signatures can be supported by storing them in metadata.signatures array.
Canonical Serialization
- Construct a JSON object containing all fields except
signature. - Remove any fields with null/undefined values.
- Sort keys lexicographically at each object level.
- Serialize using UTF-8 without whitespace (RFC 8785 style).
- Compute hash as
sha256(serialized_json)for Ed25519 signing. - Attach
signatureobject containing algorithm, key ID, and base64url signature over the hash.
Validation Rules
completed_at >= started_at.units >= 0andprice >= 0when present.signature.algMUST be one of the network approved algorithms (initiallyEd25519).chain_idSHOULD match the target blockchain network when provided.- Reject receipts older than network-defined retention period.
Example Receipt (unsigned)
{
"version": "1.0",
"receipt_id": "rcpt-20250926-000123",
"job_id": "job-abc123",
"provider": "ait1minerxyz...",
"client": "ait1clientabc...",
"units": 1.9,
"unit_type": "gpu_seconds",
"price": 4.2,
"model": "runwayml/stable-diffusion-v1-5",
"prompt_hash": "sha256:cf1f...",
"started_at": 1695720000,
"completed_at": 1695720002,
"artifact_hash": "sha256:deadbeef...",
"coordinator_id": "coord-eu-west-1",
"nonce": "b7f3d10b",
"chain_id": 12345
}
Signed form includes:
"signature": {
"alg": "Ed25519",
"key_id": "miner-ed25519-2025-09",
"sig": "Fql0..."
}
Multi-Signature Receipt Format
Receipts requiring attestation from multiple parties (e.g., miner + coordinator) use a signatures array instead of a single signature object.
Schema
| Field | Type | Required | Description |
|---|---|---|---|
signatures |
array | conditional | Array of signature objects when multi-sig is used. |
threshold |
integer | optional | Minimum signatures required for validity (default: all). |
quorum_policy |
string | optional | Policy name: "all", "majority", "threshold". |
Signature Entry
Each entry in the signatures array:
| Field | Type | Required | Description |
|---|---|---|---|
alg |
string | yes | Signature algorithm ("Ed25519", "secp256k1"). |
key_id |
string | yes | Signing key identifier. |
signer_role |
string | yes | Role of signer: "miner", "coordinator", "auditor". |
signer_id |
string | yes | Address or account of the signer. |
sig |
string | yes | Base64url-encoded signature over canonical receipt bytes. |
signed_at |
integer | yes | Unix timestamp when signature was created. |
Validation Rules
- When
signaturesis present,signature(singular) MUST be absent. - Each signature is computed over the same canonical serialization (excluding all signature fields).
thresholddefaults tolen(signatures)(all required) when omitted.- Signers MUST NOT appear more than once in the array.
- At least one signer with
signer_role: "miner"is required.
Example
{
"version": "1.1",
"receipt_id": "rcpt-20260212-ms001",
"job_id": "job-xyz789",
"provider": "ait1minerabc...",
"client": "ait1clientdef...",
"units": 3.5,
"unit_type": "gpu_seconds",
"started_at": 1739376000,
"completed_at": 1739376004,
"threshold": 2,
"quorum_policy": "all",
"signatures": [
{
"alg": "Ed25519",
"key_id": "miner-ed25519-2026-02",
"signer_role": "miner",
"signer_id": "ait1minerabc...",
"sig": "Xk9f...",
"signed_at": 1739376005
},
{
"alg": "Ed25519",
"key_id": "coord-ed25519-2026-01",
"signer_role": "coordinator",
"signer_id": "coord-eu-west-1",
"sig": "Lm3a...",
"signed_at": 1739376006
}
]
}
ZK-Proof Metadata Extension
Receipts can carry zero-knowledge proof metadata in the metadata.zk_proof field, enabling privacy-preserving verification without revealing sensitive job details.
Schema (metadata.zk_proof)
| Field | Type | Required | Description |
|---|---|---|---|
circuit_id |
string | yes | Identifier of the ZK circuit used (e.g., "SimpleReceipt_v1"). |
circuit_version |
integer | yes | Circuit version number. |
proof_system |
string | yes | Proof system: "groth16", "plonk", "stark". |
proof |
object | yes | Proof data (system-specific). |
public_signals |
array | yes | Public inputs to the circuit. |
verifier_contract |
string | optional | On-chain verifier contract address. |
verification_key_hash |
string | optional | SHA-256 hash of the verification key. |
generated_at |
integer | yes | Unix timestamp of proof generation. |
Groth16 Proof Object
| Field | Type | Description |
|---|---|---|
a |
array[2] | G1 point (π_A). |
b |
array[2][2] | G2 point (π_B). |
c |
array[2] | G1 point (π_C). |
Public Signals
For the SimpleReceipt circuit, public_signals contains:
[0]:receiptHash— Poseidon hash of private receipt data.
For the full ReceiptAttestation circuit:
[0]:receiptHash[1]:settlementAmount[2]:timestamp
Validation Rules
circuit_idMUST match a known registered circuit.public_signals[0](receiptHash) MUST NOT be zero.- If
verifier_contractis provided, on-chain verification SHOULD be performed. - Proof MUST be verified before the receipt is accepted for settlement.
Example
{
"version": "1.1",
"receipt_id": "rcpt-20260212-zk001",
"job_id": "job-priv001",
"provider": "ait1minerxyz...",
"client": "ait1clientabc...",
"units": 2.0,
"unit_type": "gpu_seconds",
"started_at": 1739376000,
"completed_at": 1739376003,
"metadata": {
"zk_proof": {
"circuit_id": "SimpleReceipt_v1",
"circuit_version": 1,
"proof_system": "groth16",
"proof": {
"a": ["0x1a2b...", "0x3c4d..."],
"b": [["0x5e6f...", "0x7a8b..."], ["0x9c0d...", "0xef12..."]],
"c": ["0x3456...", "0x7890..."]
},
"public_signals": ["0x48fa91c3..."],
"verifier_contract": "0xAbCdEf0123456789...",
"verification_key_hash": "sha256:a1b2c3d4...",
"generated_at": 1739376004
}
},
"signature": {
"alg": "Ed25519",
"key_id": "miner-ed25519-2026-02",
"sig": "Qr7x..."
}
}
Merkle Proof Anchoring Specification
Receipts can be anchored on-chain using Merkle trees, allowing efficient batch verification and compact inclusion proofs.
Anchoring Process
- Batch collection: Coordinator collects N receipts within a time window.
- Leaf computation: Each leaf =
sha256(canonical_receipt_bytes). - Tree construction: Binary Merkle tree with leaves sorted by
receipt_id. - Root submission: Merkle root is submitted on-chain in a single transaction.
- Proof distribution: Each receipt owner receives their inclusion proof.
Schema (metadata.merkle_anchor)
| Field | Type | Required | Description |
|---|---|---|---|
root |
string | yes | Hex-encoded Merkle root (0x...). |
leaf |
string | yes | Hex-encoded leaf hash of this receipt. |
proof |
array | yes | Array of sibling hashes from leaf to root. |
index |
integer | yes | Leaf index in the tree (0-based). |
tree_size |
integer | yes | Total number of leaves in the tree. |
block_height |
integer | optional | Blockchain block height where root was anchored. |
tx_hash |
string | optional | Transaction hash of the anchoring transaction. |
anchored_at |
integer | yes | Unix timestamp of anchoring. |
Verification Algorithm
1. leaf_hash = sha256(canonical_receipt_bytes)
2. assert leaf_hash == anchor.leaf
3. current = leaf_hash
4. for i, sibling in enumerate(anchor.proof):
5. if bit(anchor.index, i) == 0:
6. current = sha256(current || sibling)
7. else:
8. current = sha256(sibling || current)
9. assert current == anchor.root
Validation Rules
leafMUST equalsha256(canonical_receipt_bytes)of the receipt.prooflength MUST equalceil(log2(tree_size)).indexMUST be in range[0, tree_size).- If
tx_hashis provided, the root MUST match the on-chain value. - Merkle roots MUST be submitted within the network retention window.
Example
{
"version": "1.1",
"receipt_id": "rcpt-20260212-mk001",
"job_id": "job-batch42",
"provider": "ait1minerxyz...",
"client": "ait1clientabc...",
"units": 1.0,
"unit_type": "gpu_seconds",
"started_at": 1739376000,
"completed_at": 1739376001,
"metadata": {
"merkle_anchor": {
"root": "0x7f83b1657ff1fc53b92dc18148a1d65dfc2d4b1fa3d677284addd200126d9069",
"leaf": "0x3e23e8160039594a33894f6564e1b1348bbd7a0088d42c4acb73eeaed59c009d",
"proof": [
"0x2cf24dba5fb0a30e26e83b2ac5b9e29e1b161e5c1fa7425e73043362938b9824",
"0x486ea46224d1bb4fb680f34f7c9ad96a8f24ec88be73ea8e5a6c65260e9cb8a7"
],
"index": 2,
"tree_size": 4,
"block_height": 15234,
"tx_hash": "0xabc123def456...",
"anchored_at": 1739376060
}
},
"signature": {
"alg": "Ed25519",
"key_id": "coord-ed25519-2026-01",
"sig": "Yz4w..."
}
}
Version History
| Version | Date | Changes |
|---|---|---|
| 1.0 | 2025-09 | Initial receipt schema, Ed25519 signatures, canonical serialization. |
| 1.1 | 2026-02 | Multi-signature format, ZK-proof metadata extension, Merkle proof anchoring. |