Skip to main content

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

ParameterValue
Attestor APIhttp://${ATTESTOR_IP}:8001
WebSocketws://${ATTESTOR_IP}:8001/ws
Health Checkhttp://${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

TypeDirectionDescription
initClient → ServerInitialize connection
createTunnelClient → ServerCreate TCP tunnel
disconnectTunnelClient → ServerClose tunnel
claimTunnelClient → ServerGenerate proof
tunnelMessageBidirectionalTunnel data
errorServer → ClientError 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 operators
  • api_keys - API key management
  • audit_logs - Request audit trail
  • claims - Claim metadata

Error Handling

HTTP Errors

StatusCodeDescription
400INVALID_REQUESTMalformed request
401UNAUTHORIZEDMissing/invalid auth
403FORBIDDENAccess denied
404NOT_FOUNDResource not found
500INTERNAL_ERRORServer error

WebSocket Errors

{
type: 'error',
data: {
code: 'ERROR_TUNNEL_FAILED',
message: 'Failed to create tunnel'
}
}

Common Error Codes

CodeDescription
ERROR_AUTHENTICATION_FAILEDAuth required
ERROR_TUNNEL_FAILEDTunnel creation failed
ERROR_CLAIM_FAILEDProof generation failed
ERROR_LCORE_DISABLEDL{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.