L{CORE} Architecture Decision Records
L{CORE} Specific: These ADRs document L{CORE}'s architectural decisions for IoT attestation. The attestor container uses Reclaim Protocol's attestor-core—decisions about the attestor's internal architecture are Reclaim's. Our decisions focus on how we integrate their infrastructure with Cartesi and IoT devices.
This document records the key architectural decisions made in L{CORE} and the reasoning behind them.
ADR-001: Two-Container Architecture
Status
Accepted
Context
L{CORE} needs both external API capabilities (network access to Reclaim Protocol, database connections) and deterministic on-chain computation (Cartesi rollup). These requirements are fundamentally at odds:
- External I/O is inherently non-deterministic (network latency, API responses vary)
- Cartesi rollups require bit-for-bit identical execution across all nodes
Decision
Split the system into two containers:
-
Attestor Container: Handles all external I/O
- REST API server
- Reclaim Protocol integration
- Supabase database connection
- Blockchain transaction submission
-
Cartesi Node Container: Handles deterministic computation
- Cartesi rollup runtime
- SQLite state database
- L{CORE} business logic
- Inspect/Advance APIs
graph LR
subgraph "Attestor (Non-Deterministic)"
API[REST API]
RECLAIM[Reclaim SDK]
DB[(Supabase)]
TX[TX Submitter]
end
subgraph "Cartesi Node (Deterministic)"
ROLLUP[Rollup Runtime]
SQLITE[(SQLite)]
LCORE[L\{CORE\} Logic]
end
API --> RECLAIM
API --> DB
API --> TX
TX --> ROLLUP
ROLLUP --> SQLITE
SQLITE --> LCORE
Consequences
Positive:
- Clear separation of concerns
- Each container can be scaled independently
- Cartesi VM remains fully deterministic
- External failures don't affect rollup state
Negative:
- Inter-container communication adds latency
- More complex deployment (two images, two deployments)
- Must coordinate versions between containers
Alternatives Considered
- Single Container: Would violate Cartesi's determinism requirements
- Sidecar Pattern: Similar complexity but less clear separation
- Lambda/Serverless for Attestor: Higher latency, cold start issues
ADR-002: Cartesi for On-Chain State
Status
Accepted
Context
Need to store and query attestation data with:
- Complex access control (grants, revocations, time-based)
- Rich queries (filter by provider, date range, data type)
- Privacy (encrypted fields, selective disclosure)
- On-chain verifiability
Decision
Use Cartesi rollup with SQLite for state management.
graph TB
subgraph "Traditional Smart Contract"
SC[Solidity Contract]
MAP1[mapping address => data]
MAP2[mapping bytes32 => grant]
end
subgraph "Cartesi Rollup"
VM[Linux VM]
SQL[(SQLite)]
QUERY[Complex SQL Queries]
JOIN[JOINs, Aggregations]
end
SC --> |Limited| MAP1 & MAP2
VM --> SQL --> QUERY --> JOIN
Consequences
Positive:
- Full SQL query support (JOINs, aggregations, window functions)
- Complex access control logic possible
- Cryptographically verifiable state (fraud proofs)
- Run any Linux binary for data processing
Negative:
- Requires Cartesi-specific deployment infrastructure
- Learning curve for Cartesi development
- Finality depends on fraud proof window
Alternatives Considered
- Pure Solidity: Limited query capabilities, expensive storage (~20k gas per 32 bytes)
- Standard Optimistic Rollup: Good but no Linux environment for complex data processing
- zkRollup: Expensive proof generation for complex queries
- Off-chain Database: No verifiability, trust assumptions
ADR-003: Reclaim Protocol for Data Verification
Status
Accepted
Context
Need to verify user data from arbitrary web sources:
- Banking APIs (account balances, transaction history)
- Social media (followers, posts, verification status)
- Commerce platforms (purchase history, ratings)
- Government services (identity, licenses)
Verification must be:
- Privacy-preserving (don't expose raw data)
- Decentralized (no central authority)
- User-controlled (user initiates proof generation)
Decision
Use Reclaim Protocol's zkTLS proofs for data attestation.
sequenceDiagram
participant User
participant Browser
participant API as External API
participant Reclaim as Reclaim Network
participant Attestor as L\{CORE\} Attestor
User->>Browser: Initiate proof request
Browser->>API: HTTPS request
API-->>Browser: TLS response
Browser->>Reclaim: Submit TLS transcript
Reclaim->>Reclaim: Generate zkTLS proof
Reclaim-->>Browser: Proof + signature
Browser->>Attestor: Submit proof
Attestor->>Attestor: Verify proof
Attestor-->>User: Attestation stored
Consequences
Positive:
- Any HTTPS data source can be verified
- User privacy preserved (zero-knowledge proofs)
- Decentralized verification (Reclaim network)
- No API keys or partnerships needed with data sources
Negative:
- Requires Reclaim SDK integration
- Proof generation happens on user's device (mobile/browser)
- Limited to HTTPS sources (no native app data)
Alternatives Considered
- Direct API Integration: Requires partnerships, API keys, trust
- TEE-only Verification: No ZK privacy, larger trusted compute base
- Custom zkTLS: Massive engineering effort, unproven security
ADR-004: EigenCloud for TEE Deployment
Status
Accepted
Context
Need a Trusted Execution Environment (TEE) for:
- Hardware-backed isolation of attestation logic
- Verifiable execution (attestation reports)
- Protection of signing keys
- Compliance requirements
Decision
Deploy to EigenCloud's managed TEE infrastructure.
Consequences
Positive:
- Hardware-level security (Intel SGX/TDX)
- Managed infrastructure (no K8s expertise needed)
- Pay-per-compute pricing
- Built-in attestation support
Negative:
- Vendor dependency on EigenCloud
- Limited to supported regions
- Must adapt to EigenCloud's deployment model
Alternatives Considered
- Self-hosted SGX: Complex setup, hardware procurement, maintenance
- AWS Nitro Enclaves: Good but more expensive, AWS lock-in
- Azure Confidential Computing: Similar to AWS, Azure lock-in
- No TEE: Unacceptable security tradeoff for attestation
ADR-005: Arbitrum Sepolia for Settlement
Status
Accepted
Context
Need a blockchain for:
- Cartesi InputBox contract deployment
- Settlement of attestations
- Access control enforcement
- Immutable audit trail
Decision
Use Arbitrum Sepolia (testnet) with planned migration to Arbitrum One (mainnet).
Consequences
Positive:
- Low gas costs (L2 scaling)
- Fast finality (~1 second)
- EVM compatibility (existing tools work)
- Strong ecosystem and bridge support
Negative:
- Testnet (Sepolia) is not production-grade
- Sequencer centralization risk
- Must migrate to mainnet for production
Alternatives Considered
- Ethereum Mainnet: Too expensive for frequent attestations
- Custom Appchain: Overkill for current scale, fragmented liquidity
- Other L2s: Less ecosystem support for Cartesi integration
ADR-006: URL-Encoded JSON for Inspect Queries
Status
Accepted
Context
Cartesi's inspect endpoint accepts payloads in the URL path. Need to determine encoding format.
Decision
Use URL-encoded JSON (encodeURIComponent(JSON.stringify(query))).
Correct:
const query = { type: 'all_provider_schemas', params: {} }
const url = `/inspect/${encodeURIComponent(JSON.stringify(query))}`
Wrong (hex encoding):
const payload = '0x' + Buffer.from(JSON.stringify(query)).toString('hex')
const url = `/inspect/${payload}`
Consequences
Positive:
- Human-readable in logs and debugging
- Standard URL encoding, widely supported
- Easy to construct in any language
Negative:
- Longer URLs for large queries
- Must remember to use
encodeURIComponent, not hex
Rationale
The Cartesi node's inspect handler expects the raw JSON string in the path, which it then parses. Hex encoding the payload causes the handler to receive a hex string instead of JSON, resulting in "Unknown query type" errors.