El lanzamiento de Danksharding está próximo, brindando a los desarrolladores de rollups más espacio de bloque (o mas bien blobs) a un costo reducido. Sin embargo, a pesar de este avance, es posible que esto no satisfaga todos los casos de uso. Esto ha llevado a diferentes proyectos a desarrollar sus propias soluciones de disponibilidad de datos, conocidas como DA o Data Availability en inglés. Celestia, Near y otros ya están desarrollando sus productos, pero hasta el momento, mi preferido es EigenDA.
¿Porqué EigenDA?
Considero que EigenDA ofrece las mejores garantías económicas y una mayor compatibilidad con dApps en Ethereum y L2s. Esto es porque EigenLayer es un proyecto nativo en Ethereum Mainnet asegurado por el re-staking de Ether, como moneda base. Mi interés reciente se ha centrado en la construcción de dApps en L3s sin incentivos económicos para ser atacadas, como es el caso de aplicaciones web3 sociales o videojuegos. A pesar que EigenDA no ofrece el mismo nivel de seguridad que Ethereum y además trae un riesgo sistémico para L1, pienso que se presta para este tipo de dApps. Es este enfoque lo que me ha llevado a investigar más a fondo la tecnología de EigenDA.
Este artículo resume mi progreso en las investigaciones que he hecho sobre EigenDA, donde he aprendido a interactuar con blobs. Cómo guardarlos y cómo los rollups los usan para escalar.
Establece tu entorno de desarrollo
Instala grpcurl
EigenDA sugiere el uso de grpcurl
para dispersar y obtener blobs.
MacOS
brew install grpcurl
Linux
Para instalarlo ocupamos el compilador de Go, instálalo si aún no lo tienes.
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
Ahora instala grpcurl
.
go install github.com/fullstorydev/grpcurl/cmd/grpcurl@latest
Ahora grpcurl
está instalado en $HOME/go/bin/grpcurl
.
Instala foundry
Instala el comando forge
si aún no lo tienes.
curl -L https://foundry.paradigm.xyz | bash
foundryup
Clona el repo
Ahora clona el repo de EigenDA e ingresa en él.
git clone https://github.com/Layr-Labs/eigenda.git
cd eigenda
1. Dispersa un Blob
Comenzemos poniendo data en EigenDA, este proceso es llamado "Dispersar un Blob". Si estás construyendo un rollup vas a querer ofrecer a tus usuarios una manera de reconstruir el estado de tu L2 para ofrecer la posibilidad de forzar una transacción y retirar assets, fondos o cualquier información. Para lograr esto es necesario guardar todo el histórico de la L2, usualmente en el formato de raíces de árboles merkle para ahorrar gas. Vamos a querer guardar todo el histórico de las raices una por una, cada cierto tiempo.
Por ahora vamos a hacer un ejemplo sencillo, vamos a guardar "Hola Eigen DA!" en un blob, cambia la data a tu gusto si deseas para este ejemplo.
$HOME/go/bin/grpcurl -import-path ./api/proto -proto ./api/proto/disperser/disperser.proto -d '{"data": "Hola Eigen DA!", "security_params": [{"quorum_id": 0, "adversary_threshold": 25, "quorum_threshold": 50}]}' disperser-goerli.eigenda.xyz:443 disperser.Disperser/DisperseBlob
Esto devolverá un json con el estado de tu blob que incluye un requestId
, guárdalo en algún lugar. Lo vamos a ocupar en los siguientes pasos.
2. Obtenén el estado de un blob
Espera al rededor de un minuto y haz el siguiente llamado.
$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
Esto devolverá un json con el estado de tu blob. Guárdalo en algún lugar, lo necesitaremos a continuación
Opcional: Obtén la data guardada en el blob haciendo la siguiente llamada pasando como parámetro el hash que puedes encontrar en el estado de tu blob en el valor info.blobVerificationProof.batchHeaderHash
.
$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. Verifica tu blob on-chain
Ahora crea un archivo contracts/scripts/BlobVerification.sol
y pon la información del estado de tu blob como se detalla a continuación. La infomación está encodeada usando base64, te recomiendo usar este decodificador para convertirla a hexadecimal, y este conversor de hex a dec para los puntos X
y Y
del commitment.
contracts/scripts/BlobVerification.sol
// 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. Pruébalo en Goerli
Actualmente, EigenDA está lanzado en Goerli testnet. Forkiémoslo y corramos un RPC local.
anvil --fork-url https://goerli.gateway.tenderly.co
#https://rpc.tornadoeth.cash/goerli
Si todo está correcto, el siguiente comando no debería revertir.
cd contracts
forge script script/BlobVerification.sol --rpc-url http://127.0.0.1:8545
¿Qué sigue?
Ahora que sabemos cómo llamar la función verifyBlob()
de EigenDA, somos capaces de verificar data de un rollup guardada on-chain en un formato similar al siguiente borrador.
// 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;
}
}
Ten en consideración que necesitamos un actor de confianza para guardar la data on-chain. Esta responsabilidad es parte del rol que usualmente conocemos como "El Secuenciador" quien se encarga de:
- Recolectar y procesar todas las transacciones de los usuarios en L2
- Disparcirla en EigenDA
- Postear la data y el commitment en L1 que puede ser verificado por la funcion
verifyBlob()
de EigenDA
Observa este ejemplo oficial de EigenDA donde se muestra una implementación bastante sencilla de un Rollup donde validadores de confianza postean de una manera optimista la data on-chain y luego se puede chequear que todo esté bien llamando la función challenge
.
Además, visita la documentación oficial para más información.
Pienso que los blobs darán bastante que hablar y vendrán más y mejores herramientas que estaré investigando por este medio. ¡Pendientes!
¡Gracias por leer este tutorial!
Sígueme en dev.to y en Youtube para todo lo relacionado al desarrollo en Blockchain en Español.