Storage

This document describes the storage subsystem of the EigenLayer-AVS platform.

This document describes the storage subsystem of the EigenLayer-AVS platform. The storage layer provides persistent data storage capabilities to all components in the system, particularly the Task Engine and Aggregator. It manages task definitions, execution histories, user data, smart wallet information, and sensitive secret values using a key-value database approach.

Storage Architecture Overview#

The EigenLayer-AVS system uses BadgerDB, a high-performance embedded key-value database written in pure Go, as its primary storage engine. This choice enables cross-platform compatibility while providing efficient data access patterns optimized for the system's operational needs.

Sources:

Storage Interface#

The storage system is built around a well-defined interface that abstracts the underlying implementation. This design allows for potential replacement of the storage backend while maintaining compatibility with the rest of the system.

Sources:

Key Operations#

The storage interface provides a comprehensive set of key-value operations for data management:

CategoryOperationsDescription
Basic OperationsSet, Delete, GetKey, ExistCore operations for manipulating individual key-value pairs
Prefix OperationsGetByPrefix, GetKeyHasPrefix, FirstKVHasPrefixFunctions for working with key prefixes to support hierarchical data structures and range queries
Batch OperationsBatchWrite, MoveUtilities for atomic operations on multiple keys or moving data between keys
Listing OperationsListKeys, ListKeysMultiMethods for retrieving lists of keys matching certain patterns
Counting OperationsCountKeysByPrefix, CountKeysByPrefixesEfficient counting of keys with specific prefixes without retrieving values
Counter OperationsGetCounter, IncCounter, SetCounterSpecial utilities for managing counter values
Sequence OperationsGetSequenceSupport for generating sequential IDs
MaintenanceVacuum, Backup, LoadDatabase maintenance and backup functionality

Sources:

BadgerDB Implementation#

The BadgerDB implementation (BadgerStorage) provides the concrete implementation of the Storage interface using BadgerDB as the underlying data store. The implementation configures BadgerDB with sync writes enabled to ensure durability of data.

Key characteristics of the BadgerDB implementation include:

  1. Durability - Configured with sync writes to prevent data loss
  2. Efficient Key Scanning - Operations like CountKeysByPrefix only scan keys, not values
  3. Sequence Management - Tracking and releasing sequences to prevent resource leaks
  4. Backup and Recovery - Support for backing up and restoring the database

Sources:

Data Organization#

The storage system uses a hierarchical key structure with prefixes to organize different types of data. This enables efficient access patterns based on the type of data and relationships between entities.

Key Structure#

Sources:

Task Storage Schema#

Tasks are managed using several key patterns:

  • t:<status>:<task-id> - Stores the full task definition with its current status
  • u:<eoa>:<smart-wallet>:<task-id> - Maps user accounts to their tasks
  • history:<task-id>:<execution-id> - Stores execution history for each task
  • trigger:<task-id>:<execution-id> - Records trigger information for task executions

Task status is encoded in the key prefix using single characters:

  • a - Active tasks that can be triggered
  • c - Completed tasks
  • f - Failed tasks
  • l - Cancelled (cancelled) tasks
  • x - Currently executing tasks

Sources:

Secret Storage Schema#

Secrets are stored with a flexible permission model that can scope secrets to different levels:

  • secret:_:<eoa>:_:<name> - User-level secrets available to all workflows
  • secret:_:<eoa>:<workflow-id>:<name> - Workflow-specific secrets
  • secret:<org-id>:<eoa>:_:<name> - Organization-level secrets

This structure allows for precise control over secret visibility while maintaining efficient lookup.

Sources:

Counter Management#

The system uses counters for tracking various metrics, such as contract write operations:

  • ct:cw:<eoa> - Tracks contract writes initiated by a particular user

Counters are implemented as string-encoded integer values for easy inspection and debugging.

Sources:

Storage Integration with System Components#

The storage layer integrates with several key components of the EigenLayer-AVS system:

Sources:

RPC Server Integration#

The RPC Server uses the storage layer for all persistent data needs, including:

  1. Task management - Creation, retrieval, listing, and deletion of tasks
  2. Execution tracking - Recording and querying task execution histories
  3. Secret management - Storing and retrieving encrypted secrets
  4. Smart wallet tracking - Managing wallet associations

The storage instance is injected into the RPC Server during initialization and is accessible via the db field.

Sources:

Task Engine Integration#

The Task Engine uses storage to:

  1. Persist task definitions and state
  2. Track execution history
  3. Manage trigger states
  4. Access secret values during task execution

The engine accesses storage directly through the storage interface, enabling efficient operations like listing tasks by status or retrieving execution histories.

Sources:

Data Backup and Maintenance#

The storage system provides built-in capabilities for backup, restoration, and maintenance:

Backup and Restore#

BadgerDB supports incremental backups, allowing efficient capture of changes since the last backup:

Sources:

Database Maintenance#

The Vacuum operation performs garbage collection on the database to reclaim space from deleted entries:

This is particularly important for long-running systems where task and execution data may accumulate over time.

Sources:

Inspection and Debugging#

The storage system supports direct inspection through a telnet interface, allowing administrators to examine keys and values directly:

telnet /tmp/ap.sock
> list *           # List all keys
> get <key>        # Retrieve a specific value
> list <prefix>    # List keys with a specific prefix

This feature aids in troubleshooting and verifying system state.

Sources:

Storage Performance Considerations#

Several design choices in the storage implementation aim to optimize performance:

  1. Key-Only Operations - Functions like CountKeysByPrefix avoid loading values when only key information is needed
  2. Prefix Scanning - Efficient iteration over keys with common prefixes
  3. BatchWrite Operations - Grouping multiple writes for better throughput
  4. Sequence Management - Using BadgerDB sequences for generating IDs with minimal contention

Sources:

Conclusion#

The storage subsystem provides a reliable, efficient persistence layer for the EigenLayer-AVS platform. Its flexible key structure and comprehensive interface enable the various components to store and retrieve data with appropriate access patterns. The BadgerDB implementation offers good performance characteristics while maintaining simplicity and cross-platform compatibility.

Feature this wiki to auto refresh weekly

Try DeepWiki on your private codebase with Devin