Attestor Layer Documentation
This is Reclaim Protocol's Code: The attestor layer is Reclaim Protocol's attestor-core. We deploy their open-source TEE infrastructure and have extended it with IoT device endpoints for L{CORE}. All credit for the core attestation technology goes to the Reclaim team.
The Attestor layer provides TEE-secured proof generation and verification using Reclaim Protocol's zkTLS technology. It runs in a Trusted Execution Environment (TEE) on EigenCloud.
Overview
The Attestor layer is built on reclaimprotocol/attestor-core and handles:
- Proof Generation - Creating zkTLS proofs via Reclaim Protocol
- TEE Verification - Hardware-attested secure execution
- L{CORE} Integration - Storing attestations to Cartesi rollup
- Database Storage - Persisting data to Supabase
- API Gateway - HTTP/WebSocket endpoints for clients
Architecture
graph TB
subgraph "Attestor (TEE)"
API[HTTP API :8001]
WS[WebSocket /ws]
LC[L\{CORE\} Client]
DB[(Supabase)]
end
subgraph "External Services"
RP[Reclaim Protocol]
BC[Blockchain RPC]
CN[Cartesi Node]
end
Client --> API
Client --> WS
WS --> RP
API --> LC
LC --> CN
LC --> BC
API --> DB
Production Deployment
| Parameter | Value |
|---|---|
| Attestor API | http://${ATTESTOR_IP}:8001 |
| WebSocket | ws://${ATTESTOR_IP}:8001/ws |
| Health Check | http://${ATTESTOR_IP}:8001/healthcheck |
API Endpoints
Health Check
GET /healthcheck
# Response
{
"status": "ok",
"version": "1.0.0",
"lcore_enabled": true
}
L{CORE} Endpoints
All L{CORE} endpoints are prefixed with /api/lcore/.
Get All Provider Schemas
GET /api/lcore/schemas
# Response
{
"success": true,
"data": [
{
"schema_id": "coingecko-btc-price",
"name": "CoinGecko BTC Price",
"description": "Bitcoin price from CoinGecko API",
"provider_type": "http"
}
]
}
Get Provider Schema by ID
GET /api/lcore/schemas/:schemaId
# Example
GET /api/lcore/schemas/coingecko-btc-price
# Response
{
"success": true,
"data": {
"schema_id": "coingecko-btc-price",
"name": "CoinGecko BTC Price",
"config": { ... }
}
}
Get Attestations by Owner
GET /api/lcore/attestations/:owner
# Example
GET /api/lcore/attestations/0x1234567890abcdef...
# Response
{
"success": true,
"data": [
{
"id": 1,
"schema_id": "coingecko-btc-price",
"encrypted_data": "...",
"timestamp": 1704067200
}
]
}
Check Access
GET /api/lcore/access/:owner/:requester
# Example
GET /api/lcore/access/0x1234.../0x5678...
# Response
{
"success": true,
"data": {
"has_access": true,
"expires_at": 1704153600
}
}
Store Attestation (Internal)
POST /api/lcore/attestation
# Request Body
{
"owner": "0x1234...",
"schema_id": "coingecko-btc-price",
"data": { ... }, // Will be encrypted
"signature": "0x..."
}
# Response
{
"success": true,
"data": {
"tx_hash": "0x...",
"attestation_id": 123
}
}
WebSocket API
The WebSocket API is used for real-time proof generation.
Connection
const ws = new WebSocket('ws://${ATTESTOR_IP}:8001/ws');
ws.onopen = () => {
// Send init message
ws.send(JSON.stringify({
type: 'init',
data: { version: '1.0.0' }
}));
};
Creating a Claim
// 1. Initialize connection
ws.send(JSON.stringify({
type: 'init',
data: { version: '1.0.0' }
}));
// 2. Create tunnel
ws.send(JSON.stringify({
type: 'createTunnel',
data: {
host: 'api.example.com',
port: 443
}
}));
// 3. Claim tunnel (after data exchange)
ws.send(JSON.stringify({
type: 'claimTunnel',
data: {
id: tunnelId,
request: { ... },
response: { ... }
}
}));
Message Types
| Type | Direction | Description |
|---|---|---|
init | Client → Server | Initialize connection |
createTunnel | Client → Server | Create TCP tunnel |
disconnectTunnel | Client → Server | Close tunnel |
claimTunnel | Client → Server | Generate proof |
tunnelMessage | Bidirectional | Tunnel data |
error | Server → Client | Error response |
L{CORE} Client
The Attestor uses the L{CORE} client to interact with the Cartesi rollup.
Configuration
// Environment variables
LCORE_ENABLED=1
LCORE_NODE_URL=http://${CARTESI_NODE_IP}:10000
LCORE_RPC_URL=https://arb-sepolia.g.alchemy.com/v2/...
LCORE_DAPP_ADDRESS=0xAE0863401D5B953b89cad8a5E7c98f5136E9C26d
LCORE_INPUTBOX_ADDRESS=0x59b22D57D4f067708AB0c00552767405926dc768
Client Usage
import { LCoreClient } from '#src/lcore/index.ts';
const client = new LCoreClient({
nodeUrl: process.env.LCORE_NODE_URL,
rpcUrl: process.env.LCORE_RPC_URL,
dappAddress: process.env.LCORE_DAPP_ADDRESS,
inputBoxAddress: process.env.LCORE_INPUTBOX_ADDRESS
});
// Query schemas
const schemas = await client.getAllProviderSchemas();
// Query attestations
const attestations = await client.getAttestationsByOwner('0x...');
// Submit input (requires signer)
await client.submitInput(signer, {
type: 'store_attestation',
params: { ... }
});
Encryption
The Attestor handles encryption/decryption of sensitive data using NaCl box.
Keys
# Generate keypair
LCORE_ADMIN_PUBLIC_KEY=<base64-public-key>
LCORE_ADMIN_PRIVATE_KEY=<base64-private-key>
Encryption Flow
import { encryptForLCore, decryptFromLCore } from '#src/lcore/encryption.ts';
// Encrypt data before storing
const encrypted = encryptForLCore(
JSON.stringify(sensitiveData),
adminPublicKey
);
// Decrypt data when retrieved
const decrypted = decryptFromLCore(
encryptedData,
adminPrivateKey
);
TEE Verification
The Attestor runs in a Trusted Execution Environment for hardware-attested security.
EigenCloud TEE
EigenCloud provides:
- Isolated execution - Code runs in secure enclave
- Attestation - Hardware proof of code integrity
- Key management - Secure key derivation from mnemonic
Docker Image Hash
For TEE registration, compute the Docker image hash:
docker build -f attestor.dockerfile -t attestor .
docker inspect --format='{{.Id}}' attestor | cut -d: -f2 | sed 's/^/0x/'
Database (Supabase)
The Attestor stores operational data in Supabase.
Configuration
SUPABASE_URL=https://your-project.supabase.co
SUPABASE_SERVICE_KEY=your-service-key
Tables
operators- Registered attestor operatorsapi_keys- API key managementaudit_logs- Request audit trailclaims- Claim metadata
Error Handling
HTTP Errors
| Status | Code | Description |
|---|---|---|
| 400 | INVALID_REQUEST | Malformed request |
| 401 | UNAUTHORIZED | Missing/invalid auth |
| 403 | FORBIDDEN | Access denied |
| 404 | NOT_FOUND | Resource not found |
| 500 | INTERNAL_ERROR | Server error |
WebSocket Errors
{
type: 'error',
data: {
code: 'ERROR_TUNNEL_FAILED',
message: 'Failed to create tunnel'
}
}
Common Error Codes
| Code | Description |
|---|---|
ERROR_AUTHENTICATION_FAILED | Auth required |
ERROR_TUNNEL_FAILED | Tunnel creation failed |
ERROR_CLAIM_FAILED | Proof generation failed |
ERROR_LCORE_DISABLED | L{CORE} not enabled |
Authentication
Private Attestor Mode
Enable authentication to restrict access:
AUTHENTICATION_PUBLIC_KEY=0x1234...
Creating Auth Requests
import { createAuthRequest } from '@reclaimprotocol/attestor-core';
const authRequest = await createAuthRequest(
{
userId: 'user-123',
hostWhitelist: ['api.example.com']
},
privateKey
);
// Use in claim creation
await createClaim({
...params,
client: {
url: 'wss://attestor.example.com/ws',
authRequest
}
});
Monitoring
Health Checks
# Basic health
curl http://${ATTESTOR_IP}:8001/healthcheck
# Detailed status
curl http://${ATTESTOR_IP}:8001/api/stats
Logging
Logs use Pino with configurable levels:
LOG_LEVEL=debug # debug, info, warn, error
Elastic APM (Optional)
ELASTIC_APM_SERVER_URL=https://apm.example.com
ELASTIC_APM_SECRET_TOKEN=your-token
Credits & Attribution
The Attestor layer is entirely built on Reclaim Protocol's attestor-core. We are grateful to the Reclaim team for open-sourcing their TEE infrastructure.
What's Reclaim's:
- The entire attestor codebase (TEE verification, zkTLS, signature generation)
- The WebSocket RPC protocol
- The proof generation system
- The tunnel management system
What L{CORE} adds:
- IoT device endpoints (
/api/lcore/*) - did:key signature verification for embedded devices
- Integration with Cartesi rollup for on-chain storage
- Privacy bucketing for sensor data
For the original attestor documentation, see Reclaim Protocol Docs.