EigenDA Proxy

repository·master·Indexed 42 days ago

https://github.com/layr-labs/eigenda

A RESTful middleware that enables rollup frameworks to interact with the EigenDA network. It handles blob dispersal, retrieval, and cryptographic verification (KZG and DA certificates) in conformance with the OP Alt-DA spec. The proxy supports Optimism and standard commitment modes, provides an admin API for backend version management (V1/V2), and includes a Memstore backend for integration testing.

Tokens
92.7K
Snippets
241
Records
410
Agent score
54%

What's inside EigenDA

  1. What is EigenDA?

    master

    EigenDA is a Data Availability (DA) service implemented as an Actively Validated Service (AVS) on EigenLayer. It provides secure and scalable data availability for Layer 2 (L2) solutions on Ethereum.

    As a DA system, it performs two primary functions:

    1. Accepts blobs of data via an ingestion interface.
    2. Makes data available to retrievers via a retrieval interface.

    Key metrics for evaluating the service include Security (ensuring certified data is actually available to honest retrievers) and Throughput (the rate of data acceptance, measured in bytes/second).

  2. Overview of EigenDA Proxy

    master

    The EigenDA Proxy is a REST proxy server designed to facilitate interaction with the EigenDA network. It acts as a bridge between rollup frameworks and the EigenDA disperser, conforming to the OP Alt-DA server specification.

    Core Functionality:

    • Dispersal (POST): Submit payloads (such as rollup transactions or state diffs) to be encoded into an EigenDA blob. The disperser makes this data available for 2 weeks and returns a DA certificate of availability.
    • Retrieval (GET): Provide a DA Certificate to retrieve the corresponding blob. The proxy decodes, validates, and returns the payload.

    Key Security and Compatibility Features:

    • KZG Verification: Performs KZG verification during both dispersal (to ensure certificates have correct commitments) and retrieval (to ensure returned data is correct).
    • Certificate Verification: Validates that DA certificates are properly bridged to Ethereum during both dispersal and retrieval.
    • Encoding: Handles BN254 field element encoding/decoding.
    • Optimism Compatibility: Supports Optimism's alt-da commitment type with the EigenDA backend and keccak-256 commitment type with S3 storage.
  3. Overview of the EigenDA Proving SDK

    master
    The EigenDA Proving SDK is a collection of Rust crates designed to provide the necessary proving and verifying infrastructure for modular rollups to create trustless integrations with EigenDA. It is framework-agnostic, meaning it can be used with various rollup infrastructures (such as the Sovereign SDK) to handle Ethereum interactions, proxy communication, and cryptographic verification.
  4. Overview of the encoding library

    master

    The encoding library performs Reed-Solomon encoding using elliptic curve points. It is designed to enable KZG multi-proof and reveal operations in $O(n \log n)$ time using Fast Fourier Transform (FFT), following the FK20 algorithm.

    Key features include:

    • Built upon cryptographic primitives from github.com/protolambda/go-kzg.
    • Supports an arbitrary number of systematic nodes, parity nodes, and data sizes.
    • Does not require the data size to be a power of 2.
  5. What is LittDB?

    master

    LittDB is a highly specialized embedded key-value store optimized for high write throughput, low read latency, and low memory usage. It is designed for a 'write once, never update' workload where data is only deleted via a Time-To-Live (TTL) mechanism.

    Key Characteristics

    • Write Once: Once a value is written, it cannot be mutated.
    • TTL-based Deletion: Values are only removed when they expire via TTL; manual deletion is not supported.
    • Specialized Performance: By omitting general-purpose features like transactions, encryption, and complex queries, LittDB achieves superior performance for specific high-throughput workloads.
  6. Understand the EigenDA System Architecture

    master

    EigenDA is a Data Availability (DA) system composed of three primary actors and two conceptual layers:

    Core Components

    • DA nodes: Service providers that store chunks of blob data for a predefined period and serve them upon request.
    • Disperser: Responsible for encoding blobs, distributing them to DA nodes, and aggregating digital signatures into a DA attestation. Currently centralized (trusted for liveness), but intended to be decentralized.
    • Ethereum L1: Provides shared state for DA node registration and stake delegation. It is also used to bridge DA attestations to L2 applications (e.g., rollup chains).

    Conceptual Layers

    • Attestation Layer: Ensures that when a DA attestation is accepted by an end-user (like a rollup), the data is indeed available. It relies on Ethereum's consensus via EigenLayer.
    • Network Layer: The communication protocol ensuring liveness and safety against network-level threats.
  7. On-chain churn selection logic in EigenDARegistryCoordinator

    master

    The EigenDARegistryCoordinator contract handles churn selection during the registerOperator() call. If the operator count exceeds maxOperatorCount, the contract invokes the internal _churnOperator(uint8 quorumNumber) function.

    The selection process follows these steps:

    1. Retrieves the current list of operators for the specified quorumNumber using indexRegistry().getOperatorListAtBlockNumber().
    2. Iterates through the list to find the operator with the lowest stake via stakeRegistry().getCurrentStake().
    3. Deregisters the identified lowest-stake operator using _deregisterOperator().
    4. Proceeds with the registration of the new operator.
    // EigenDARegistryCoordinator.sol:157-178
    function _churnOperator(uint8 quorumNumber) internal {
        bytes32[] memory operatorList = indexRegistry().getOperatorListAtBlockNumber(quorumNumber, uint32(block.number));
        require(operatorList.length > 0, "RegCoord._churnOperator: no operators to churn");
    
        // Find the operator with the lowest stake
        bytes32 operatorToChurn;
        uint96 lowestStake = type(uint96).max;
        for (uint256 i; i < operatorList.length; i++) {
            uint96 operatorStake = stakeRegistry().getCurrentStake(operatorList[i], quorumNumber);
            if (operatorStake < lowestStake) {
                lowestStake = operatorStake;
                operatorToChurn = operatorList[i];
            }
        }
    
        // Deregister the operator with the lowest stake
        bytes memory quorumNumbers = new bytes(1);
        quorumNumbers[0] = bytes1(uint8(quorumNumber));
        _deregisterOperator({operator: blsApkRegistry().pubkeyHashToOperator(operatorToChurn), quorumNumbers: quorumNumbers});
    }
  8. Prover and Verifier Optimizations in EigenDA

    master

    To prevent computational bottlenecks, EigenDA implements specific optimizations for the encoding process:

    • Prover Optimizations: Uses Fast Amortized Kate Proofs to reduce the computational complexity of generating proofs.
    • Verifier Optimizations: Implements the Universal Verification Equation (originally developed for Danksharding) to dramatically reduce the complexity of KZG verification for DA nodes.
  9. How LittDB manages data segments and garbage collection

    master

    To avoid the inefficiency of rewriting entire files during data deletion (TTL expiration), LittDB breaks the data file into multiple segments.

    Segment Management:

    • Each segment has a maximum file size. When full, a new segment is opened with a monotonically increasing segment index (starting at 0).
    • The keymap stores addresses as a combination of the segment index and the offset within that segment.
    • Metadata files are created for each segment, storing the timestamp of the last value written. This allows the garbage collector to decide if a segment can be deleted by checking only the metadata file, rather than scanning the whole segment.
    • Key files separate keys from values. This allows the system to rebuild the keymap or clean up keys during segment deletion by scanning much smaller files instead of large value files.

    Safe Deletion (Garbage Collection): To prevent race conditions where a reader tries to access a segment being deleted, LittDB uses reference counters for each segment:

    1. A reader finds the address in the keymap.
    2. The reader increments the segment's reference counter.
    3. The reader decrements the reference counter when finished.
    4. The garbage collector waits until the reference counter is zero before physically deleting the segment file from disk.
  10. How LittDB achieves read-your-writes consistency with an unflushed data map

    master

    To allow reads to continue uninterrupted during background writes, LittDB uses an unflushed data map (a thread-safe key->value map).

    Write Workflow:

    1. Immediately add the data to the unflushed data map.
    2. Write the data to the file asynchronously (e.g., using buffered file stream APIs).
    3. The write operation returns as soon as the data is in the map and the buffer.

    Read Workflow: To ensure consistency, LittDB searches in this specific order:

    1. The Cache: For high-speed access to recent data.
    2. The Unflushed Data Map: To catch data that has been written but not yet committed to disk.
    3. On Disk: Using the keymap and the data file for committed data.

    The Flush() Method: Users can call Flush() to force synchronization. This method:

    1. Flushes all data in buffers to disk.
    2. Empties the unflushed data map.
    3. Writes the key-address pairs to the keymap for each entry before removal.
    4. Blocks until all operations are complete.

    This pattern provides read-your-writes consistency: if a reader looks for data currently being written, it will find it in the unflushed data map. If it finds an entry in the keymap, the data is safely on disk.

    // Conceptual usage of the Flush mechanism
    db.put("my_key", "my_value");
    // Data is now in the unflushed data map
    
    db.Flush();
    // Data is now guaranteed to be on disk and in the keymap
  11. Criteria for automatic validator ejection

    master

    Dispersers use automatic decision-making to identify eligible validators for ejection. A validator is considered ejectable only when all the following conditions are met during the performance_evaluation_window (default: 10 minutes):

    1. Zero signing rate: The validator's signing_rate is zero.
    2. Cool-down period elapsed: DISPERSER_COOL_DOWN has passed since the last ejection attempt against this specific validator.
    3. Selective non-participation: Other validators in the set show non-zero signing rates during the same window, ensuring the issue is not a network-wide outage.

    In code, the criterion is expressed as: signingRate.GetSignedBatches() == 0 && signingRate.GetUnsignedBatches() > 0.

    // ejector/ejector.go:146
    isEjectable := signingRate.GetSignedBatches() == 0 && signingRate.GetUnsignedBatches() > 0