```
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 (
This commit is contained in:
299
docs/reference/specs/protocol-messages.md
Normal file
299
docs/reference/specs/protocol-messages.md
Normal file
@@ -0,0 +1,299 @@
|
||||
# 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.
|
||||
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
```json
|
||||
{
|
||||
"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](receipt-spec.md) for full details.
|
||||
|
||||
### Miner Registration
|
||||
|
||||
Sent by miner to register with coordinator.
|
||||
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
```json
|
||||
{
|
||||
"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.
|
||||
|
||||
```json
|
||||
{
|
||||
"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 identifier
|
||||
- `version` - Protocol version (currently "1.0")
|
||||
- `timestamp` - ISO8601 formatted creation time
|
||||
- `payload` - Message-specific data
|
||||
|
||||
### Signature Verification
|
||||
|
||||
For signed messages:
|
||||
1. Extract `payload` as canonical JSON (sorted keys, no whitespace)
|
||||
2. Compute SHA-256 hash of canonical payload
|
||||
3. Verify signature using specified algorithm and key
|
||||
|
||||
```python
|
||||
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.
|
||||
Reference in New Issue
Block a user