Skip to content
Closed
Show file tree
Hide file tree
Changes from 14 commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
0415033
Add EigenDA V2 CI infrastructure
shyam-patel-kira Dec 17, 2025
d7fbe37
Add ReferenceDA system tests and update V2 CI workflow
shyam-patel-kira Dec 18, 2025
47a835e
Improve ReferenceDA tests with certificate verification and comprehen…
shyam-patel-kira Dec 18, 2025
6f87992
Enable EigenDA V2 with comprehensive system and e2e tests
shyam-patel-kira Dec 18, 2025
e8c2d3e
Fix double http:// prefix bug in ReferenceDA test URLs
shyam-patel-kira Dec 19, 2025
642edd9
Fix lint errors: add missing JWTSecret field to ServerConfig
shyam-patel-kira Dec 19, 2025
afda9fa
Fix errcheck lint errors: properly handle server.Shutdown error returns
shyam-patel-kira Dec 19, 2025
186a316
Handle V2 certificates: trigger failover when V2 detected
shyam-patel-kira Jan 5, 2026
da8c9f2
Restore EigenDA V2 + ReferenceDA failover test configuration
shyam-patel-kira Jan 5, 2026
0a3bd8b
Deploy ReferenceDAProofValidator contract in tests and add ALT DA sup…
shyam-patel-kira Jan 5, 2026
cbfec59
Update contracts to eigenda-v2.1.3-altda-support with ALT DA support
shyam-patel-kira Jan 5, 2026
4430bf8
Update contracts to v3.9.0-altda-support with ALT DA support
shyam-patel-kira Jan 5, 2026
516c4dc
Add e2e tests and disperser mode support for EigenDA V2 with arb API
shyam-patel-kira Jan 5, 2026
f410169
Remove placeholder tests and consolidate TODOs
shyam-patel-kira Jan 5, 2026
fa69708
Remove V1 codepaths and simplify to V2-only through DAProvider interface
shyam-patel-kira Jan 6, 2026
a37f34d
Address review: remove V1 modifications, separate V2 script, drop Ref…
shyam-patel-kira Jan 7, 2026
1551457
Handle missing GetSupportedHeaderBytes RPC method gracefully for simp…
shyam-patel-kira Jan 7, 2026
791de56
Fix V2 proxy startup to use locally-built binary with Arbitrum RPC su…
shyam-patel-kira Jan 8, 2026
62111bc
Use Docker-based proxy build for V2 with Arbitrum RPC support
shyam-patel-kira Jan 8, 2026
badb723
Exclude V2 proxy Dockerfile from main Docker build context
shyam-patel-kira Jan 9, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
90 changes: 90 additions & 0 deletions .github/workflows/eigenda-v2-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
name: EigenDA V2 CI

on:
workflow_call:
workflow_dispatch:
pull_request:
paths:
- 'eigenda/**'
- 'system_tests/eigenda_v2_test.go'
- 'system_tests/referenceda_test.go'
- 'daprovider/referenceda/**'
- 'scripts/start-eigenda-proxy.sh'
- '.github/workflows/eigenda-v2-ci.yml'

jobs:
eigenda-v2-tests:
runs-on: linux-2xl

steps:
- uses: actions/checkout@v4
with:
submodules: recursive

- uses: ./.github/actions/ci-setup

- name: Start EigenDA V2 Proxy
run: |
# Start V2 proxy (will skip if image not available)
./scripts/start-eigenda-proxy.sh v2 || echo "V2 proxy not available yet, skipping"
continue-on-error: true

- name: Build Nitro
run: make -j8 build test-go-deps
env:
CARGO_BUILD_JOBS: 2

- name: Run V2 Integration Tests
run: |
# Run V2 tests with special build tag
# Tests are currently skipped but will run when V2 is ready
go test -timeout 600s \
-tags eigendav2test \
-v \
./system_tests \
-run "TestEigenDAV2" || echo "V2 tests skipped (not yet implemented)"
env:
GOMEMLIMIT: 6GiB
GOGC: 80
continue-on-error: true

- name: Run ReferenceDA Integration Tests
run: |
# Run ReferenceDA (CustomDA/ALT DA) tests
# These tests use the existing ReferenceDA implementation and should pass
# Tests include:
# - TestReferenceDAServerReachability: Basic server startup
# - TestReferenceDAStoreRetrieve: Store/retrieve operations
# - TestReferenceDAIntegration: Full L1/L2 integration with certificate verification
go test -timeout 600s \
-v \
./system_tests \
-run "TestReferenceDA"
env:
GOMEMLIMIT: 6GiB
GOGC: 80

- name: Check for V2 TODOs
run: |
echo "=== V2 Implementation TODOs ==="
echo ""
echo "Proxy Script TODOs:"
grep -n "TODO" scripts/start-eigenda-proxy.sh || echo "None"
echo ""
echo "V2 Test TODOs:"
grep -n "TODO" system_tests/eigenda_v2_test.go | head -20 || echo "None"
echo ""
echo "=== Commands ==="
echo "V2 Proxy: ./scripts/start-eigenda-proxy.sh v2"
echo "V2 Tests: go test -tags eigendav2test ./system_tests -run TestEigenDAV2"
echo "ReferenceDA Tests: go test ./system_tests -run TestReferenceDA"

- name: Upload Test Logs
if: always()
uses: actions/upload-artifact@v4
with:
name: eigenda-v2-test-logs
path: |
system_tests/*.log
/tmp/eigenda-v2-*.log
if-no-files-found: ignore
2 changes: 1 addition & 1 deletion contracts
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is the submodule changed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it was updated to add DAC_CERTIFICATE_MESSAGE_HEADER_FLAG (0x01) support in SequencerInbox.sol. This allows the contract to accept ReferenceDA certificates which use the ALT-DA spec. Without this, ReferenceDA batches are rejected as invalid.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

still a bit fuzzy why contract submodules need to be updated here at all given the upstream repo has golang tests for their CustomDA feature which asserts to correctness of batch posting / derivation logics

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, upstream has CustomDA support and the golang daprovider/ code already supports 0x01 (we inherit that). However, the L1 contracts must also accept 0x01 headers for batch posting to work. Without this update, batch posting would fail with InvalidHeaderFlag(0x01).

The update adds one line to SequencerInbox.sol to validate the 0x01 header byte - same as upstream's CustomDA support, just using our fork's naming (DAC_CERTIFICATE_MESSAGE_HEADER_FLAG vs upstream's CUSTOM_DA_MESSAGE_HEADER_FLAG).

2 changes: 1 addition & 1 deletion daprovider/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const EigenDAMessageHeaderFlag byte = 0xed
const DACertificateMessageHeaderFlag byte = 0x01

// KnownHeaderBits is all header bits with known meaning to this nitro version
const KnownHeaderBits byte = DASMessageHeaderFlag | TreeDASMessageHeaderFlag | L1AuthenticatedMessageHeaderFlag | ZeroheavyMessageHeaderFlag | BlobHashesHeaderFlag | BrotliMessageHeaderByte | EigenDAMessageHeaderFlag
const KnownHeaderBits byte = DASMessageHeaderFlag | TreeDASMessageHeaderFlag | L1AuthenticatedMessageHeaderFlag | ZeroheavyMessageHeaderFlag | BlobHashesHeaderFlag | BrotliMessageHeaderByte | EigenDAMessageHeaderFlag | DACertificateMessageHeaderFlag

var DefaultDASRetentionPeriod time.Duration = time.Hour * 24 * 15

Expand Down
17 changes: 16 additions & 1 deletion eigenda/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,25 @@ func (c *EigenDAProxyClient) Put(ctx context.Context, data []byte) (*disperser.B
return nil, fmt.Errorf("failed to set data: %w", err)
}

if len(cert) == 0 {
return nil, fmt.Errorf("received empty certificate from proxy")
}

// Check version byte to determine certificate format
version := cert[0]

// V2 certificate (version 0x02): Not supported through V1 code path
// V2 uses ALT-DA spec and should be accessed through DAProvider interface, not EigenDA.Enable
// Returning ErrServiceUnavailable will trigger failover to DAProvider if configured
if version == 0x02 {
return nil, standard_client.ErrServiceUnavailable
}
Comment on lines +36 to +48
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why is this check being done?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This detects V2 certificates in the V1 code path and returns ErrServiceUnavailable to trigger failover to ReferenceDA. However, if we're removing V1 entirely, this check may no longer be needed.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. this implementation deviates from the initial spec proposal where we'd have a separate branch that doesn't contain any V1 code changes or we'd nuke v1 code paths. If we're doing the approach of cannibalizing the existing eigenda branch then we'll need a followup PR that nukes all V1 references.
  2. V2 uses CustomDA which is provided for us by OCL. These EigenDA specific write/read system paths would never be touched for EigenDA V2 x CustomDA and leverage the existing CustomDA writer/reader provided to us in the software.


// V1 certificate (version 0x00): decode as disperser.BlobInfo
var blobInfo disperser.BlobInfo
err = rlp.DecodeBytes(cert[1:], &blobInfo)
if err != nil {
return nil, fmt.Errorf("failed to decode blob info: %w", err)
return nil, fmt.Errorf("failed to decode V1 blob info: %w", err)
}

return &blobInfo, nil
Expand Down
133 changes: 119 additions & 14 deletions scripts/start-eigenda-proxy.sh
Original file line number Diff line number Diff line change
@@ -1,34 +1,139 @@
#!/usr/bin/env bash

echo "==== Pull eigenda-proxy container ===="
docker pull ghcr.io/layr-labs/eigenda-proxy:2.3.1
set -euo pipefail

echo "==== Starting eigenda-proxy container ===="
# EigenDA Proxy Startup Script
#
# Usage: ./start-eigenda-proxy.sh [VERSION] [MODE]
#
# VERSION: v1 or v2 (default: v1)
# - v1: EigenDA V1 with Store() API
# - v2: EigenDA V2 with ALT-DA spec
#
# MODE: memstore or disperser (default: memstore)
# - memstore: In-memory storage, no real disperser (fast CI tests)
# * Uses dummy disperser (localhost:32003)
# * Good for system tests and CI validation
# * Tests: go test -tags eigendav2test ./system_tests
#
# - disperser: Real EigenDA network with blob dispersal (e2e tests)
# * Connects to real disperser (default: disperser-holesky.eigenda.xyz:443)
# * Enables arb API for Arbitrum-specific routes
# * Requires running EigenDA infrastructure or Holesky testnet
# * Tests: go test -tags eigendav2e2etest ./system_tests
#
# Examples:
# ./start-eigenda-proxy.sh v1 # V1 with memstore
# ./start-eigenda-proxy.sh v2 # V2 with memstore (fast CI)
# ./start-eigenda-proxy.sh v2 disperser # V2 with real disperser (e2e)

# proxy has a bug currently which forces the use of the service manager address
# Version parameter: v1 or v2 (default: v1)
VERSION="${1:-v1}"
# Mode parameter: memstore or disperser (default: memstore)
MODE="${2:-memstore}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why are we supporting version switching? I thought the idea was to nuke all V1 codepaths entirely

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yea, I kept it in case we wanted to do an incremental rollout, can nuke it completely, don't have a strong opinion on this one

Copy link
Collaborator

@ethenotethan ethenotethan Jan 7, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vs overloading the existing start-eigenda-proxy.sh why not add a separate one start-eigenda-proxy-customda.sh to easier support followup deletion of V1 related logics?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

that's a good idea, create a different setup script for v2 testing: a37f34d


# Configuration based on version
case "$VERSION" in
v1)
PROXY_IMAGE="ghcr.io/layr-labs/eigenda-proxy:2.3.1"
CONTAINER_NAME="eigenda-proxy-nitro-test-instance"
STORAGE_BACKENDS="V1"
DISPERSAL_BACKEND="V1"
;;
v2)
# V2 uses latest image (v2.5.0+) with V2 backend support
# V2 implements OP Alt-DA spec with Optimism routes
PROXY_IMAGE="ghcr.io/layr-labs/eigenda-proxy:latest"
CONTAINER_NAME="eigenda-proxy-v2-nitro-test-instance"
STORAGE_BACKENDS="V2"
DISPERSAL_BACKEND="V2"
# Enable admin API for runtime backend switching
ENABLE_ADMIN_API="true"

# Mode-specific configuration for V2
case "$MODE" in
memstore)
ENABLE_MEMSTORE="true"
# For memstore mode, use dummy disperser (data stored in memory)
DISPERSER_RPC="localhost:32003"
;;
disperser)
# For disperser mode, connect to real EigenDA network
ENABLE_MEMSTORE="false"
# Disperser RPC can be overridden via env var EIGENDA_DISPERSER_RPC
DISPERSER_RPC="${EIGENDA_DISPERSER_RPC:-disperser-holesky.eigenda.xyz:443}"
# Enable arb API for Arbitrum-specific routes
ENABLE_ARB_API="true"
echo "⚠️ DISPERSER MODE: Connecting to real EigenDA network"
echo " Disperser: $DISPERSER_RPC"
;;
*)
echo "Error: Unknown mode '$MODE'. Use 'memstore' or 'disperser'"
exit 1
;;
esac
;;
*)
echo "Error: Unknown version '$VERSION'. Use 'v1' or 'v2'"
exit 1
;;
esac

echo "==== Pull eigenda-proxy $VERSION container ===="
docker pull "$PROXY_IMAGE"

echo "==== Starting eigenda-proxy $VERSION container ===="

# proxy has a bug currently which forces the use of the service manager address
# & eth rpc despite cert verification being disabled.

docker run -d --name eigenda-proxy-nitro-test-instance \
# Build docker run command
DOCKER_CMD="docker run -d --name $CONTAINER_NAME \
-p 4242:6666 \
-e EIGENDA_PROXY_ADDR=0.0.0.0 \
-e EIGENDA_PROXY_PORT=6666 \
-e EIGENDA_PROXY_STORAGE_BACKENDS_TO_ENABLE=V1 \
-e EIGENDA_PROXY_STORAGE_DISPERSAL_BACKEND=V1 \
-e EIGENDA_PROXY_APIS_TO_ENABLE=standard \
-e EIGENDA_PROXY_MEMSTORE_ENABLED=true \
-e EIGENDA_PROXY_STORAGE_BACKENDS_TO_ENABLE=$STORAGE_BACKENDS \
-e EIGENDA_PROXY_STORAGE_DISPERSAL_BACKEND=$DISPERSAL_BACKEND \
-e EIGENDA_PROXY_MEMSTORE_ENABLED=${ENABLE_MEMSTORE:-true} \
-e EIGENDA_PROXY_MEMSTORE_EXPIRATION=120m \
-e EIGENDA_PROXY_EIGENDA_ETH_RPC=http://localhost:6969 \
-e EIGENDA_PROXY_EIGENDA_SERVICE_MANAGER_ADDR="0x0000000000000000000000000000000000000000" \
-e EIGENDA_PROXY_EIGENDA_SERVICE_MANAGER_ADDR=0x0000000000000000000000000000000000000000 \
-e EIGENDA_PROXY_EIGENDA_CERT_VERIFICATION_DISABLED=true \
ghcr.io/layr-labs/eigenda-proxy:2.3.1
-e EIGENDA_PROXY_EIGENDA_DISPERSER_RPC=${DISPERSER_RPC}"

# Add V2-specific configuration if V2 backend is enabled
if [[ "$STORAGE_BACKENDS" == *"V2"* ]]; then
# Use holesky_testnet network for default contract addresses
# This provides all necessary contract addresses automatically
DOCKER_CMD="$DOCKER_CMD \
-e EIGENDA_PROXY_EIGENDA_V2_NETWORK=holesky_testnet \
-e EIGENDA_PROXY_EIGENDA_V2_ETH_RPC=http://localhost:6969"
fi

# Add API configuration for V2 if enabled
if [ "${ENABLE_ADMIN_API:-false}" = "true" ]; then
if [ "${ENABLE_ARB_API:-false}" = "true" ]; then
DOCKER_CMD="$DOCKER_CMD -e EIGENDA_PROXY_API_ENABLED=admin,arb"
else
DOCKER_CMD="$DOCKER_CMD -e EIGENDA_PROXY_API_ENABLED=admin"
fi
elif [ "${ENABLE_ARB_API:-false}" = "true" ]; then
DOCKER_CMD="$DOCKER_CMD -e EIGENDA_PROXY_API_ENABLED=arb"
fi

# Run the container
eval "$DOCKER_CMD $PROXY_IMAGE"

# shellcheck disable=SC2181
if [ $? -ne 0 ]; then
echo "==== Failed to start eigenda-proxy container ===="
echo "==== Failed to start eigenda-proxy $VERSION container ===="
exit 1
fi

echo "==== eigenda-proxy container started ===="
echo "==== eigenda-proxy $VERSION container started ===="
echo "Container name: $CONTAINER_NAME"
echo "Version: $VERSION"
echo "Image: $PROXY_IMAGE"

## TODO - support teardown or embed a docker client wrapper that spins up and tears down resource
## TODO - support teardown or embed a docker client wrapper that spins up and tears down resource
# within system tests. Since this is only used by one system test, it's not a large priority atm.
Loading
Loading