Almanac is a high-performance, multi-chain blockchain indexing system built with Rust. It provides a unified interface for indexing events and state from multiple blockchains, with support for complex queries, storage proofs, and real-time updates.
- Modularity: Each component has a single, well-defined responsibility
- Extensibility: Easy to add support for new blockchains and storage backends
- Performance: Optimized for high-throughput event processing
- Reliability: Built-in support for chain reorganizations and finality tracking
- Type Safety: Leverages Rust's type system for correctness
Almanac uses a distributed microservices architecture where chain-specific indexing nodes and an API server connect to a shared FoundationDB data layer:
┌─────────────────────────────────────────────────────────────────┐
│ External Clients │
│ • Web Apps • CLI Tools • Dashboards │
└─────────────────────────┬───────────────────────────────────────┘
│
▼ HTTP/WebSocket
┌─────────────────────────────────────────────────────────────────┐
│ almanac-api │
│ • HTTP API Server • WebSocket Support │
│ • Authentication • Rate Limiting │
│ • OpenAPI Documentation • Response Caching │
│ • Read-only operations • Query optimization │
└─────────────────────────┬───────────────────────────────────────┘
│ Reads
▼
┌─────────────────────────────────────────────────────────────────┐
│ FoundationDB Cluster │
│ • Distributed ACID transactions │
│ • Automatic replication and sharding │
│ • Multi-dimensional tuple indexing │
│ • 13 keyspaces for multi-chain data │
└─────────────────────────▲───────────────────────────────────────┘
│ Writes
┌──────────────────┼───────────────────┐
│ │ │
┌──────▼──────────┐ ┌─────▼──────────┐ ┌──────▼──────────┐
│ almanac-ethereum│ │almanac-cosmos │ │almanac-solana │
│ :9091 │ │ :9092 │ │ :9093 │
├─────────────────┤ ├────────────────┤ ├─────────────────┤
│ • Event indexing│ │• Event indexing│ │• Account data │
│ • Reorg handling│ │• BFT consensus │ │• PoH validation │
│ • State proofs │ │• IBC tracking │ │• Program logs │
│ • EVM traces │ │• Module events │ │• Slot tracking │
│ • Health :9091 │ │• Health :9092 │ │• Health :9093 │
│ • Metrics │ │• Metrics │ │• Metrics │
└─────────────────┘ └────────────────┘ └─────────────────┘
│ │ │
▼ RPC ▼ RPC ▼ RPC
┌─────────────────────────────────────────────────────────────────┐
│ Blockchain Networks │
│ • Ethereum/Anvil • Cosmos/Neutron • Solana │
│ • :8545 • :26657 • :8899 │
└─────────────────────────────────────────────────────────────────┘
The foundational crate containing core types and traits used throughout the system:
- Event trait: Base trait for all blockchain events
- Storage traits: Separate
StorageWriterandStorageReadertraits for write and read operations, respectively - Error types: Unified error handling
- Common types: BlockStatus, ChainId, EventFilter
Internal event bus for decoupled communication between components:
- Async message passing
- Event handler registration
- Subscription management
- System-wide event distribution
Configuration management with hot-reloading support:
- TOML-based configuration
- Environment variable overrides
- Runtime configuration updates
- Validation and type safety
HTTP API server built on Axum:
- RESTful endpoints for event queries
- WebSocket support for real-time updates
- Authentication and authorization
- Rate limiting and caching
- OpenAPI documentation
Event indexing engine:
- Multi-chain event processing
- Batch optimization for performance
- Event ordering and deduplication
- Pipeline management
- Integration with storage and consensus
Persistent storage layer:
- FoundationDB primary backend
- Tuple-based encoding for efficient queries
- Storage proof generation
- In-memory backend for testing
- Extensible storage trait
Almanac uses separate chain-specific indexing services that connect to shared storage:
- almanac-ethereum: Dedicated Ethereum indexing node (:9091)
- almanac-cosmos: Dedicated Cosmos indexing node (:9092)
- almanac-solana: Dedicated Solana indexing node (:9093)
- almanac-api: Read-only API server for client queries (:8080)
- Shared FoundationDB: All services use the same FoundationDB cluster with namespace isolation
Chain Indexing Nodes:
- Event Processing: Index blockchain events and state changes
- Consensus Handling: Manage chain-specific finality and reorganizations
- Storage Writing: Write normalized data to FoundationDB
- Health Monitoring: Provide health and metrics endpoints
- Independent Deployment: Each service can be scaled and deployed separately
API Server:
- Query Processing: Handle client queries and API requests
- Authentication: Manage API keys and rate limiting
- Data Aggregation: Combine data from multiple chains
- WebSocket Support: Real-time event streaming
- Read-Only: Does not perform indexing or write to storage
Core blockchain abstraction layer shared across services:
- ChainAdapter trait: Unified interface implemented by each chain service
- ChainDataIR: Normalized intermediate representation for all chains
- State extraction: Merkle proofs and storage slot tracking
- Event normalization: Consistent event format across chains
- Connection management: RPC pooling and failover handling
Consensus and finality management:
- Finality levels: Confirmed -> Safe -> Justified -> Finalized
- Fork choice rules: LongestChain, GHOST, Casper, TendermintBFT
- Reorg detection: Automatic rollback support with configurable depth
- Chain-specific configurations: Per-chain finality and consensus rules
Testing utilities and fixtures:
- Mock chain adapters
- Test event generators
- Storage test helpers
- Integration test framework
-
Block Fetching
- Chain adapter connects to RPC endpoint
- Fetches blocks at configured interval
- Extracts events and state changes
-
Normalization
- Convert chain-specific data to ChainDataIR
- Extract storage proofs if needed
- Generate event metadata
-
Consensus Processing
- Check for reorganizations
- Update finality status
- Apply fork choice rules
-
Storage
- Persist events to FoundationDB
- Update indexes and views
- Generate storage proofs
-
API Response
- Query events by filters
- Return paginated results
- Include proof data if requested
-
Request Reception
- HTTP/WebSocket request received
- Authentication and rate limiting
- Request validation
-
Query Planning
- Parse filters and parameters
- Optimize query execution
- Select appropriate indexes
-
Storage Access
- Execute FoundationDB queries
- Apply filters and pagination
- Retrieve associated proofs
-
Response Generation
- Format results
- Include metadata
- Cache if appropriate
- Service Isolation: Each blockchain has a dedicated indexing service
- Independent Scaling: Scale chain indexers independently based on throughput
- Fault Tolerance: Failure of one chain doesn't affect others
- Resource Optimization: Chain-specific resource allocation and tuning
- Deployment Flexibility: Deploy and update services independently
- ACID Guarantees: Consistent state across all nodes
- Horizontal Scaling: Automatic sharding and replication
- Multi-Version Concurrency: Non-blocking reads
- Tuple Layer: Efficient multi-dimensional indexing
- Namespace Isolation: Logical separation between chains
- Service-Based: Each chain has its own binary and service
- Trait-Based: Uniform ChainAdapter interface across all blockchain implementations
- Pluggable: Easy to add new blockchain support with new service
- Type-Safe: Leverages Rust's type system for correctness
- Configurable: Runtime configuration for different networks per service
- Decoupling: Components communicate via events
- Scalability: Async processing throughout
- Flexibility: Easy to add new processors
- Debugging: Event trail for troubleshooting
- Compile-time Validation: Catch errors early
- Runtime Flexibility: Hot-reloading support
- Environment Overrides: 12-factor app compliance
- Self-documenting: Types describe configuration
- Bearer token authentication
- Rate limiting per client
- Input validation
- CORS configuration
- Storage proofs for verification
- Cryptographic commitments
- Finality tracking
- Reorg protection
- Secure RPC connections
- API key management
- Audit logging
- Health monitoring
- Group events by block
- Bulk storage operations
- Parallel chain processing
- Memory-efficient streaming
- API response caching
- Block metadata caching
- Configuration caching
- Connection pooling
- Tuple encoding for range queries
- Indexed access patterns
- Pagination support
- Lazy loading
- Custom chain adapters
- Storage backend plugins
- Authentication providers
- Query processors
- Horizontal scaling via partitioning
- Read replicas for queries
- Event stream processing
- Caching layer expansion