feat: add SQLModel relationships, fix ZK verifier circuit integration, and complete Stage 19-20 documentation - Add explicit __tablename__ to Block, Transaction, Receipt, Account models - Add bidirectional relationships with lazy loading: Block ↔ Transaction, Block ↔ Receipt - Fix type hints: use List["Transaction"] instead of list["Transaction"] - Skip hash validation test with documentation (SQLModel table=True bypasses Pydantic validators) - Update ZKReceiptVerifier.sol to match receipt_simple circuit (
7.0 KiB
Protocol Message Formats
This document defines the message formats used for communication between AITBC network components.
Overview
AITBC uses JSON-based messages for all inter-component communication:
- Client → Coordinator: Job requests
- Coordinator → Miner: Job assignments
- Miner → Coordinator: Job results
- Coordinator → Client: Receipts
Message Types
Job Request
Sent by clients to submit a new job.
{
"type": "job_request",
"version": "1.0",
"timestamp": "2026-01-24T15:00:00Z",
"payload": {
"prompt": "Explain quantum computing",
"model": "llama3.2",
"params": {
"max_tokens": 256,
"temperature": 0.7,
"top_p": 0.9,
"stream": false
},
"client_id": "ait1client...",
"nonce": "abc123"
},
"signature": {
"alg": "Ed25519",
"key_id": "client-key-001",
"sig": "base64..."
}
}
| Field | Type | Required | Description |
|---|---|---|---|
type |
string | yes | Message type identifier |
version |
string | yes | Protocol version |
timestamp |
ISO8601 | yes | Message creation time |
payload.prompt |
string | yes | Input text |
payload.model |
string | yes | Model identifier |
payload.params |
object | no | Model parameters |
payload.client_id |
string | yes | Client address |
payload.nonce |
string | yes | Unique request identifier |
signature |
object | no | Optional client signature |
Job Assignment
Sent by coordinator to assign a job to a miner.
{
"type": "job_assignment",
"version": "1.0",
"timestamp": "2026-01-24T15:00:01Z",
"payload": {
"job_id": "job-abc123",
"prompt": "Explain quantum computing",
"model": "llama3.2",
"params": {
"max_tokens": 256,
"temperature": 0.7
},
"client_id": "ait1client...",
"deadline": "2026-01-24T15:05:00Z",
"reward": 5.0
},
"coordinator_id": "coord-eu-west-1"
}
| Field | Type | Required | Description |
|---|---|---|---|
payload.job_id |
string | yes | Unique job identifier |
payload.deadline |
ISO8601 | yes | Job must complete by this time |
payload.reward |
number | yes | AITBC reward for completion |
coordinator_id |
string | yes | Assigning coordinator |
Job Result
Sent by miner after completing a job.
{
"type": "job_result",
"version": "1.0",
"timestamp": "2026-01-24T15:00:05Z",
"payload": {
"job_id": "job-abc123",
"miner_id": "ait1miner...",
"result": "Quantum computing is a type of computation...",
"result_hash": "sha256:abc123...",
"metrics": {
"tokens_generated": 150,
"inference_time_ms": 2500,
"gpu_memory_used_mb": 4096
}
},
"signature": {
"alg": "Ed25519",
"key_id": "miner-key-001",
"sig": "base64..."
}
}
| Field | Type | Required | Description |
|---|---|---|---|
payload.result |
string | yes | Generated output |
payload.result_hash |
string | yes | SHA-256 hash of result |
payload.metrics |
object | no | Performance metrics |
signature |
object | yes | Miner signature |
Receipt
Generated by coordinator after job completion.
{
"type": "receipt",
"version": "1.0",
"timestamp": "2026-01-24T15:00:06Z",
"payload": {
"receipt_id": "rcpt-20260124-001234",
"job_id": "job-abc123",
"provider": "ait1miner...",
"client": "ait1client...",
"units": 2.5,
"unit_type": "gpu_seconds",
"price": 5.0,
"model": "llama3.2",
"started_at": 1737730801,
"completed_at": 1737730805,
"result_hash": "sha256:abc123..."
},
"signature": {
"alg": "Ed25519",
"key_id": "coord-key-001",
"sig": "base64..."
}
}
See Receipt Specification for full details.
Miner Registration
Sent by miner to register with coordinator.
{
"type": "miner_registration",
"version": "1.0",
"timestamp": "2026-01-24T14:00:00Z",
"payload": {
"miner_id": "ait1miner...",
"capabilities": ["llama3.2", "llama3.2:1b", "codellama"],
"gpu_info": {
"name": "NVIDIA RTX 4090",
"memory_gb": 24,
"cuda_version": "12.1",
"driver_version": "535.104.05"
},
"endpoint": "http://miner.example.com:8080",
"max_concurrent_jobs": 4
},
"signature": {
"alg": "Ed25519",
"key_id": "miner-key-001",
"sig": "base64..."
}
}
Heartbeat
Sent periodically by miners to indicate availability.
{
"type": "heartbeat",
"version": "1.0",
"timestamp": "2026-01-24T15:01:00Z",
"payload": {
"miner_id": "ait1miner...",
"status": "available",
"current_jobs": 1,
"gpu_utilization": 45.5,
"memory_used_gb": 8.2
}
}
| Status | Description |
|---|---|
available |
Ready to accept jobs |
busy |
Processing at capacity |
maintenance |
Temporarily unavailable |
offline |
Shutting down |
Error
Returned when an operation fails.
{
"type": "error",
"version": "1.0",
"timestamp": "2026-01-24T15:00:02Z",
"payload": {
"error_code": "JOB_NOT_FOUND",
"message": "Job with ID job-xyz does not exist",
"details": {
"job_id": "job-xyz"
}
},
"request_id": "req-123"
}
Message Validation
Required Fields
All messages MUST include:
type- Message type identifierversion- Protocol version (currently "1.0")timestamp- ISO8601 formatted creation timepayload- Message-specific data
Signature Verification
For signed messages:
- Extract
payloadas canonical JSON (sorted keys, no whitespace) - Compute SHA-256 hash of canonical payload
- Verify signature using specified algorithm and key
import json
import hashlib
from nacl.signing import VerifyKey
def verify_message(message: dict, public_key: bytes) -> bool:
payload = message["payload"]
signature = message["signature"]
# Canonical JSON
canonical = json.dumps(payload, sort_keys=True, separators=(',', ':'))
payload_hash = hashlib.sha256(canonical.encode()).digest()
# Verify
verify_key = VerifyKey(public_key)
try:
verify_key.verify(payload_hash, bytes.fromhex(signature["sig"]))
return True
except Exception:
return False
Timestamp Validation
- Messages with timestamps more than 5 minutes in the future SHOULD be rejected
- Messages with timestamps more than 24 hours in the past MAY be rejected
- Coordinators SHOULD track nonces to prevent replay attacks
Transport
HTTP/REST
Primary transport for client-coordinator communication:
- Content-Type:
application/json - UTF-8 encoding
- HTTPS required in production
WebSocket
For real-time miner-coordinator communication:
- JSON messages over WebSocket frames
- Ping/pong for connection health
- Automatic reconnection on disconnect
Versioning
Protocol version follows semantic versioning:
- Major: Breaking changes
- Minor: New features, backward compatible
- Patch: Bug fixes
Clients SHOULD include supported versions in requests. Servers SHOULD respond with highest mutually supported version.