EigenDA: Start developing on Blobs today
Published: 2024-02-16 18:48:42

---
title: EigenDA: Start developing on Blobs today
published: true
description: 
tags: 
cover_image: https://dev-to-uploads.s3.amazonaws.com/uploads/articles/pnei2sdzz5mjnb0bxpo7.png
# Use a ratio of 100:42 for best results.
# published_at: 2023-12-31 02:17 +0000
---

Danksharding is coming to Ethereum Mainnet in less than a month, giving rollup developers more block space at a lower cost. However, even with this progress, all demands won't be fully met. This has led different projects to roll out their own data availability solutions or DA in short. Celestia, Near, and others are building their own solutions but my current favorite is EigenDA.

### Why EigenDA?

I believe EigenDA offers the best economic guarantees and the best compatibility with dApps on Ethereum and L2s since it is native to the Ethereum Mainnet and uses Ether as the base economic security. Lately, my focus has been on developing dApps on L3s without economic incentives for attacks, such as social web3 applications or video games. I think EigenDA is a good solution for this even if it doesn't offer the same security as Ethereum. This has led me to research deeper into EigenDA technology.

This article is my current progress on my research on how to use EigenDA, where we'll learn how to interact with blobs. How to store them and how rollups can use them to scale.

## Setup your environment

### Install grpcurl

EigenDA suggests using `grpcurl` to disperse and retrieve blobs.

#### MacOS

```
brew install grpcurl
```

#### Linux

In order to install it we will need the Go compiler, install it if you haven't.

```bash
https://go.dev/dl/go1.22.0.linux-amd64.tar.gz
rm -rf /usr/local/go
sudo tar -C /usr/local -xzf go1.22.0.linux-amd64.tar.gz 
export PATH=$PATH:/usr/local/go/bin
```

Now install `grpcurl`.

```bash
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
```

`grpcurl` is now installed at `$HOME/go/bin/grpcurl`.

### Install foundry

Install the forge command if you haven't.

```
curl -L https://foundry.paradigm.xyz | bash
foundryup
```

### Clone the repo

Now clone the EigenDA repo and cd into it.

```bash
git clone https://github.com/Layr-Labs/eigenda.git
cd eigenda
```

### 1. Disperse a blob

Let's start by putting some data on EigenDA, this process is called _"Dispersing a Blob"_. If you're building a rollup you might want to store your transaction data history to allow users to permissionlessly retrieve any asset, funds or any information from L2 to L1. To achieve this we need to store data in the form of a merkle tree root, one merkle root at the time every now and then.

We're keeping it simple for now, in the following command we store "Hello Eigen DA!", feel free to put whatever data you want.

```bash
$HOME/go/bin/grpcurl -import-path ./api/proto -proto ./api/proto/disperser/disperser.proto -d '{"data": "Hello Eigen DA!", "security_params": [{"quorum_id": 0, "adversary_threshold": 25, "quorum_threshold": 50}]}' disperser-goerli.eigenda.xyz:443 disperser.Disperser/DisperseBlob
```

This will return a json that includes a `requestId` value, save it somewhere. We will need it in the following steps.

### 2. Query the blob status

Wait about a minute and call the following.

```bash
$HOME/go/bin/grpcurl -import-path ./api/proto -proto ./api/proto/disperser/disperser.proto -d '{"request_id": "YOUR REQUEST ID"}' disperser-goerli.eigenda.xyz:443 disperser.Disperser/GetBlobStatus
```

This will return a json with your blob status. Save it somewhere, we'll need it in a moment.

Optional: Query the data you stored directly by running the following command and passing the `info.blobVerificationProof.batchHeaderHash` returned on out blob status json.

```bash
$HOME/go/bin/grpcurl -import-path ./api/proto -proto ./api/proto/disperser/disperser.proto -d '{"batch_header_hash": "YOUR BLOB HEADER HASH", "blob_index":"0"}' disperser-goerli.eigenda.xyz:443 disperser.Disperser/RetrieveBlob
```

### 3. Verify the blob on-chain

Now, create a `contracts/scripts/BlobVerification.sol` file and put all your blob status data on the contract as described below. The blob status json uses base64 encoding, so I recommend you using [this decoder online](https://base64.guru/converter/decode/hex), and [this hex to dec converter](https://www.rapidtables.com/convert/number/hex-to-decimal.html) for the X and Y commitment.

`contracts/scripts/BlobVerification.sol`
```javascript
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.9;

import "forge-std/Script.sol";
import "../src/rollup/MockRollup.sol";
import {EigenDARollupUtils} from "../src/libraries/EigenDARollupUtils.sol";

contract MockRollupDeployer is Script {
    function run() external {
        vm.startBroadcast();

        IEigenDAServiceManager.QuorumBlobParam[]
            memory quorumBlobParams = new IEigenDAServiceManager.QuorumBlobParam[](1);
        
        quorumBlobParams[0] = IEigenDAServiceManager.QuorumBlobParam(
            /*quorumNumber*/0,
            /*adversaryThresholdPercentage*/25,
            /*quorumThresholdPercentage*/50,
            /*chunkLength*/1);

        IEigenDAServiceManager.BlobHeader memory blobHeader = IEigenDAServiceManager.BlobHeader(
            BN254.G1Point(/*X*/4317633011943442688312675280968246407649523414935450151451943114581321374794,
                          /*Y*/19103178923486544823523596462585377039936043999112285141018622651122914686888),
            /*dataLength*/ 1,
            quorumBlobParams
        );

        address eigenDAServiceManager = 0xa3b1689Ab85409B15e07d2ED50A6EA9905074Ee5;
        //0x1eEa1C6b573f192F33BE6AA56dC9080314a89491;

        IEigenDAServiceManager.BatchHeader memory batchHeader 
            = IEigenDAServiceManager.BatchHeader(
                /*bytes32 blobHeadersRoot*/ 0x1d1af6d981553efb8d0a7b6d6022b56d1fbf2a615d1dd5a034e6870e87159a68,
                /*bytes quorumNumbers*/ hex"00",
                /*bytes quorumThresholdPercentages*/ hex"5f", 
                /*uint32 referenceBlockNumber*/ 10544012
            );

        IEigenDAServiceManager.BatchMetadata memory batchMetadata
            = IEigenDAServiceManager.BatchMetadata(
                batchHeader,
                /*bytes32 signatoryRecordHash*/ 0x3bb6b9f58f262b89fb02e339a045438b4765f6f09ca136d045556b3869e07b70,
                /*uint96 fee*/0,
                /*uint32 confirmationBlockNumber*/10544016
            );
        
        EigenDARollupUtils.BlobVerificationProof memory blobVerificationProof
            = EigenDARollupUtils.BlobVerificationProof(
                /*uint32 batchId*/ 12580,
                /*uint8 blobIndex*/ 9,
                batchMetadata,
                /*bytes inclusionProof*/ hex"082915e241f357b6c2f43fac8767a909286b7f9e392c04a40caf9be28486e561b2127431770921e8f3461e1a4d845e2991e803d1c6591655873bf1cc03702cb5626b47f9b14bb86bbfaf11ad723b5bdaa3a25fc33dda9f768e58c1df463d9e0d279e7a791b0bdcbe8f32610c0ff7cfb99fd15ad0aa9091d2d02ab520a34536793829e2605b7aa684f488b51ffff369f49e23fc075b1d0413fca94f9bb670b92a024b2b6efbf73d9f0522191941d18c15ea5713fb87c679cd7abf2fdec390b5fd",
                /*bytes quorumThresholdIndexes*/ hex"00"
            );

        EigenDARollupUtils.verifyBlob(blobHeader, IEigenDAServiceManager(eigenDAServiceManager), blobVerificationProof);

        vm.stopBroadcast();
    }
}
```

### 4. Test it

Currently, EigenDA is deployed on Goerli. Let's fork it and run an RPC locally.

```
anvil --fork-url https://goerli.gateway.tenderly.co
#https://rpc.tornadoeth.cash/goerli
```

If all data is correct, the following command should not revert.

```
cd contracts
forge script script/BlobVerification.sol --rpc-url http://127.0.0.1:8545
```

### What's next?

Now that we know how to call the `verifyBlob()` function from EigenDA, we should be able to verify rollup data stored on a format similar to the following draft.

```javascript
// SPDX-License-Identifier: MIT

pragma solidity >=0.8.20;

import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";

struct G1Point {
    uint256 X;
    uint256 Y;
}

contract MyNaiveOptimisticCrentralizedRollupDA is Ownable {
    mapping(uint timestamp => bytes32 data) public dataHistory;
    mapping(uint timestamp => G1Point commitment) public commitmentsHistory;

    function postData(uint timestamp, bytes32 data) public onlyOwner {
        dataHistory[timestamp] = data;
    }

    function postCommitment(uint timestamp, G1Point memory commitment) public onlyOwner {
        commitmentsHistory[timestamp] = commitment;
    }
}
```

Notice that we need a trusted actor to post the data on-chain. This is part of the role of what is commonly known as _"The Sequencer"_ who need to do the following:

1. Gather all the transaction data from users on L2
2. Disperse it to EigenDA
3. Post both the commitment and data on L1 and verify it using EigenDA's `verifyBlob` function

Take a look at [this official example](https://github.com/Layr-Labs/eigenda/blob/v0.3.0/contracts/src/rollup/MockRollup.sol) from EigenDA that shows a very naive implementation of a Rollup that posts blobs optimistically and then challenge them.

Also, take a look at the [official documentation](https://docs.eigenlayer.xyz/eigenda/rollup-guides/tutorial).

I think  there is a lot more to come about blobs in terms of tools and use cases. I'll be covering it here. Stay tuned!

**Thanks for reading this guide!**

Follow Filosofía Código on dev.to and in [Youtube]( https://www.youtube.com/channel/UCbF5CFuXv2vTkcGfepWV2nA) for everything related to Blockchain development.