Skip to content

Commit 89ac40d

Browse files
authored
test: add eigenda v1 to v2 migration kurtosis test (#44)
* test(kt-devnet): add v1->v2 migration test Using the proxy v1.7.0-rc docker image updated the test harness to add a client for the new proxy admin API which allows changing dispersal backend (v1 -> v2) added test to test this migration * test(kt-devnet): fix test harness proxyClient was not being initialized properly, causing a nil pointer error. * ci(kt-devnet): add v2 files to test matrix * docs(kt-devnet): fix comment on TestEigenDAV2Migration_Memstore test * test(kt-devnet): make GetDispersalBackend use passed ctx * test(kt-devnet): add finalization assert to migration test We check that op-node is still finalizing after the migration, just like we do in the failover test. * test(kt-devnet): also test migration against holesky * test(kt-devnet): fix wrong context bug was passing old context in places, causing context timed out error * chore(kt-devnet): add max-blob-length flag to make proxy load faster proxy takes ~1min to load and sometimes longer. add the --eigenda.v2.max-blob-length flag set to 1MiB to make loading faster (loads fewer SRS points at startup) * chore(kt-devnet): add justfile command to switch proxy backend allows switching from v1 to v2 when doing manual testing locally * test(kt-devnet): add log line to show discarded commitments in failover test * test(kt-devnet): skip migration test on holesky to make CI faster Copy paste of code comment explaining reasoning: // The issue is that because of the holocene strict ordering rules, // after migrating from v1 to v2, the v2 certs, even though they finalize very quickly // and are returned to op-batcher, op-batcher cannot send them to the batch-inbox until // the v1 certs have been sent. So we need to wait at least 10-15 mins for the v1 certs to be returned // from proxy to op-batcher and submitted to batch-inbox. // starting kurtosis devnet takes ~10 mins and batcher logs tests take 15 mins, // so we are already at 25 mins. Trying to keep CI time under 30 mins, // so we skip this test for now. We could turn on if we had a nice inabox eigenda that would allow // for much faster v1 finalization. * test(kt-devnet): reenable v2migration test on holesky Decided to live with increased CI time in order to be safe. * test(kt-devnet): fix migration test by increasing waitForBlock timer * chore(kt-devnet): bump eigenda.yaml proxy to v1.7.0 * test(kt-devnet): add extra minute to WaitForBlock to prevent timeout * test(kt-devnet): increase go test timeout to 30/40mins * test(kt-devnet): bump v1 stage to 40 l1 blocks in migration test * test(kt-devnet): add extra minute to WaitForBlock to prevent timeout * test(kt-devnet): add -v flags to get more info in ci * test(kt-devnet): change max-channel-duration 150->10 for holesky tests * ci(kt-devnet): remove holesky-sequential-large-blobs v1 test Kept having flukes. It was taking super long. Test getting throttled. Was just a ci nightmare, so opted to remove.
1 parent f349a50 commit 89ac40d

File tree

10 files changed

+317
-42
lines changed

10 files changed

+317
-42
lines changed

.github/workflows/kurtosis-devnet.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ jobs:
5252
# This list should be kept up-to-date with the files in eigenda-template-values
5353
valuesFile:
5454
[
55-
"holesky-sequential-large-blobs.json",
55+
# v1 is too slow for sequential large blobs.
56+
# Could send a single massive blob every few minutes, but then migration test
57+
# takes too long waiting for the few certs to land onchain, so opted to just not run it.
5658
"holesky-concurrent-small-blobs.json",
59+
"holesky-v2-sequential-large-blobs.json",
60+
"holesky-v2-concurrent-small-blobs.json",
5761
]
5862
steps:
5963
- uses: actions/checkout@v4
@@ -68,6 +72,7 @@ jobs:
6872
"eigenda-proxy": {
6973
"secrets": {
7074
"eigenda.signer-private-key-hex": "${{ secrets.EIGENDA_V1_HOLESKY_TESTNET_SIGNER_KEY }}",
75+
"eigenda.v2.signer-payment-key-hex": "${{ secrets.EIGENDA_V2_HOLESKY_TESTNET_SIGNER_KEY }}",
7176
"eigenda.eth_rpc": "https://ethereum-holesky-rpc.publicnode.com"
7277
}
7378
}

kurtosis-devnet/eigenda-template-values/holesky-concurrent-small-blobs.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
{
22
"eigenda-proxy": {
33
"useMemstore": false,
4+
"dispersalBackend": "v1",
45
"secrets": {
56
"eigenda.signer-private-key-hex": "",
7+
"eigenda.v2.signer-payment-key-hex": "",
68
"eigenda.eth_rpc": ""
79
}
810
},
911
"batcher": {
10-
"max-channel-duration": 150,
12+
"max-channel-duration": 10,
1113
"altda.max-concurrent-da-requests": 100,
1214
"target-num-frames": 10,
1315
"max-l1-tx-size-bytes": 1000,
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
{
2+
"eigenda-proxy": {
3+
"useMemstore": false,
4+
"dispersalBackend": "v2",
5+
"secrets": {
6+
"eigenda.signer-private-key-hex": "",
7+
"eigenda.v2.signer-payment-key-hex": "",
8+
"eigenda.eth_rpc": ""
9+
}
10+
},
11+
"batcher": {
12+
"max-channel-duration": 10,
13+
"altda.max-concurrent-da-requests": 100,
14+
"target-num-frames": 10,
15+
"max-l1-tx-size-bytes": 1000,
16+
"batch-type": 1
17+
}
18+
}

kurtosis-devnet/eigenda-template-values/holesky-sequential-large-blobs.json renamed to kurtosis-devnet/eigenda-template-values/holesky-v2-sequential-large-blobs.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,15 @@
11
{
22
"eigenda-proxy": {
33
"useMemstore": false,
4+
"dispersalBackend": "v2",
45
"secrets": {
56
"eigenda.signer-private-key-hex": "",
7+
"eigenda.v2.signer-payment-key-hex": "",
68
"eigenda.eth_rpc": ""
79
}
810
},
911
"batcher": {
10-
"max-channel-duration": 150,
12+
"max-channel-duration": 10,
1113
"altda.max-concurrent-da-requests": 1,
1214
"target-num-frames": 1000,
1315
"max-l1-tx-size-bytes": 1000,

kurtosis-devnet/eigenda.yaml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88
# TODO: I hate yaml templating... should really move to something more reasonable. CUE perhaps?
99
# use proxy by default, otherwise connect with eigenda holesky backend
1010
{{- $useProxyMemstore := dig "eigenda-proxy" "useMemstore" true $context }}
11-
{{- $eigendaBackendSignerKey := dig "eigenda-proxy" "secrets" "eigenda.signer-private-key-hex" "" $context }}
11+
{{- $proxyDispersalBackend := dig "eigenda-proxy" "dispersalBackend" "v1" $context }}
12+
{{- $eigendaV1SignerKey := dig "eigenda-proxy" "secrets" "eigenda.signer-private-key-hex" "" $context }}
13+
{{- $eigendaV2SignerKey := dig "eigenda-proxy" "secrets" "eigenda.v2.signer-payment-key-hex" "" $context }}
1214
{{- $eigendaBackendEthRpc := dig "eigenda-proxy" "secrets" "eigenda.eth_rpc" "" $context }}
1315
{{- if not $useProxyMemstore}}
1416
# make sure the secrets are populated when using eigenda-holesky backend
15-
{{- if or (eq $eigendaBackendSignerKey "") (eq $eigendaBackendEthRpc "") }}
17+
{{- if or (eq $eigendaV1SignerKey "") (eq $eigendaV2SignerKey "") (eq $eigendaBackendEthRpc "") }}
1618
{{- fail "Missing required eigenda-proxy eigenda-backend secrets." }}
1719
{{- end }}
1820
{{- end }}
@@ -90,19 +92,29 @@ optimism_package:
9092
cannon_prestates_url: "http://fileserver/proofs/op-program/cannon"
9193
extra_params: []
9294
da_server_params:
93-
image: ghcr.io/layr-labs/eigenda-proxy:v1.6.5
95+
image: ghcr.io/layr-labs/eigenda-proxy:v1.7.0
9496
cmd:
9597
- --addr=0.0.0.0
9698
- --port=3100
99+
- --storage.backends-to-enable=V1,V2
100+
- --storage.dispersal-backend={{ $proxyDispersalBackend }} #v1 or v2
101+
- --api-enabled=admin # to enable changing dispersal-backend to v2 without restarting
102+
- --eigenda.v2.max-blob-length=1MiB # makes startup faster by only loading 1MiB/2MiB of G1/G2 SRS points.
97103
{{- if $useProxyMemstore }}
98104
- --memstore.enabled
99105
- --memstore.expiration=30m
100106
{{- else }} # connect to eigenda holesky backend
107+
# V1 flags
101108
- --eigenda.disperser-rpc=disperser-holesky.eigenda.xyz:443
102109
- --eigenda.svc-manager-addr=0xD4A7E1Bd8015057293f0D0A557088c286942e84b
103110
# The two params below are loaded from the eigenda-secrets.json file
104-
- --eigenda.signer-private-key-hex={{ $eigendaBackendSignerKey }}
111+
- --eigenda.signer-private-key-hex={{ $eigendaV1SignerKey }}
105112
- --eigenda.eth-rpc={{ $eigendaBackendEthRpc }}
113+
# V2 flags
114+
- --eigenda.v2.disperser-rpc=disperser-holesky.eigenda.xyz:443
115+
- --eigenda.v2.cert-verifier-addr=0xFe52fE1940858DCb6e12153E2104aD0fDFbE1162
116+
- --eigenda.v2.signer-payment-key-hex={{ $eigendaV2SignerKey }}
117+
- --eigenda.v2.eth-rpc={{ $eigendaBackendEthRpc }}
106118
{{- end }}
107119
additional_services:
108120
- da_server

kurtosis-devnet/justfile

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,13 +121,13 @@ eigenda-devnet-clean ENCLAVE_NAME="eigenda-devnet":
121121
# meaning with a config file in eigenda-template-values/memstore-* .
122122
[group('eigenda')]
123123
eigenda-devnet-test-memstore *ARGS="":
124-
go test ./tests/eigenda/... -run "_Memstore$" -timeout 20m {{ARGS}}
124+
go test ./tests/eigenda/... -run "_Memstore$" -v -timeout 30m {{ARGS}}
125125
# Runs all tests that end with the `_Holesky` suffix, assuming the devnet was started with proxy using holesky backend.
126126
# To start the devnet with holesky backend, the files in eigenda-template-values/holesky-* need have secrets injected.
127127
# Take a look at how CI does it in .github/workflows/kurtosis-devnet.yml .
128128
[group('eigenda')]
129129
eigenda-devnet-test-holesky *ARGS="":
130-
go test ./tests/eigenda/... -run "_Holesky$" -timeout 20m {{ARGS}}
130+
go test ./tests/eigenda/... -run "_Holesky$" -v -timeout 40m {{ARGS}}
131131
[group('eigenda')]
132132
eigenda-devnet-add-tx-fuzzer ENCLAVE_NAME="eigenda-devnet" *ARGS="":
133133
kurtosis service add {{ENCLAVE_NAME}} tx-fuzz ethpandaops/tx-fuzz:master -- \
@@ -174,6 +174,14 @@ eigenda-devnet-configs ENCLAVE_NAME="eigenda-devnet":
174174
echo "PROXY MEMSTORE CONFIG:"
175175
PROXY_ENDPOINT=$(kurtosis port print {{ENCLAVE_NAME}} da-server-op-kurtosis http)
176176
curl $PROXY_ENDPOINT/memstore/config | jq
177+
curl $PROXY_ENDPOINT/admin/eigenda-dispersal-backend | jq
178+
[group('eigenda')]
179+
eigenda-devnet-change-proxy-backend backend="V1" ENCLAVE_NAME="eigenda-devnet":
180+
#!/usr/bin/env bash
181+
PROXY_ENDPOINT=$(kurtosis port print {{ENCLAVE_NAME}} da-server-op-kurtosis http)
182+
curl -X PUT $PROXY_ENDPOINT/admin/eigenda-dispersal-backend \
183+
-H "Content-Type: application/json" \
184+
-d '{"eigenDADispersalBackend": "{{backend}}"}'
177185
# We unfortunately have to restart the batcher in this ugly way right now just to change even a single flag.
178186
# This is b/c op's kurtosis setup right now is not idempotent so if we change a param in a values file
179187
# and rerun `just eigenda-devnet-start`, the entire devnet gets respun up which takes a long time.

kurtosis-devnet/tests/eigenda/batcher_logs_test.go

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,16 @@ func TestBatcherFromLogs_Holesky(t *testing.T) {
1515
t.Logf("TestBatcherFromLogs_Holesky needs a timeout of at least 15 minutes to run.")
1616
t.FailNow()
1717
}
18+
harness := NewHarness(t)
1819
// Batching time on Holesky can be up to 10 minutes, so we need long time to see a tx getting confirmed.
19-
testBatcherFromLogs(t, 15*time.Minute)
20+
testBatcherFromLogs(t, harness, 15*time.Minute)
2021
}
2122

2223
func TestBatcherFromLogs_Memstore(t *testing.T) {
24+
harness := NewHarness(t)
2325
// 2 minutes is arbitrary here but should be long enough to observe interesting behavior using memstore.
2426
// Also need to run the failover test which takes quite a while and can't run in parallel with these tests (or can it..?)
25-
testBatcherFromLogs(t, 2*time.Minute)
27+
testBatcherFromLogs(t, harness, 2*time.Minute)
2628
}
2729

2830
// These tests are log driven. The batcher doesn't expose an API to query its state outside of logs and metrics,
@@ -32,13 +34,11 @@ func TestBatcherFromLogs_Memstore(t *testing.T) {
3234
// A better approach might be to generate txs from inside the golang test instead of relying on the external tx-fuzzer.
3335
// We could then increase traffic until the point where DA gets throttled, then change batcher parameters to increase blob size, etc.
3436
// Updating the batcher params is currently hard to do however; see comments above the eigenda-devnet-restart-batcher command in the justfile.
35-
func testBatcherFromLogs(t *testing.T, testTimeout time.Duration) {
37+
func testBatcherFromLogs(t *testing.T, harness *Harness, testTimeout time.Duration) {
3638
// We stream logs for testTimeout, and run all the below tests in parallel (they read the same log outputs)
3739
ctxWithTestTimeout, cancel := context.WithTimeout(context.Background(), testTimeout)
3840
t.Cleanup(cancel)
3941

40-
harness := NewHarness(t)
41-
4242
// Make sure that no channel is ever timing out (fails to be sent to L1 in timely manner).
4343
// Make sure the testsTimer is longer than max-channel-duration in the batcher config (found in the eigenda-template-values/ files).
4444
// Currently max-channel-duration is set to 10 L1 blocks, meaning 10*6 seconds = 60 seconds.

kurtosis-devnet/tests/eigenda/failover_test.go

Lines changed: 34 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ func TestFailoverToEthDACalldata_Memstore(t *testing.T) {
4141
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
4242
defer cancel()
4343
t.Logf("Cleanup; Failing back to eigenda... resetting enclave proxy to start posting to eigenda again")
44-
err := harness.Clients.ProxyMemconfigClient.Failback(ctx)
44+
err := harness.Clients.ProxyClients.Failback(ctx)
4545
if err != nil {
4646
t.Logf("Error failing back... you might need to reset proxy to normal mode manually: %v", err)
4747
}
@@ -61,13 +61,18 @@ func TestFailoverToEthDACalldata_Memstore(t *testing.T) {
6161
require.GreaterOrEqual(t, harness.TestStartL1BlockNum, l1BlocksQueriedForBatcherTxs, "Test started too early in the chain")
6262
fromBlock := harness.TestStartL1BlockNum - l1BlocksQueriedForBatcherTxs
6363

64+
eigenDABackend, err := harness.Clients.ProxyClients.GetDispersalBackend(ctxWithDeadline)
65+
require.NoError(t, err)
66+
DALayerEigenDA, err := certVersionToDALayer(eigenDABackend)
67+
require.NoError(t, err)
68+
6469
// 1. Check that the original commitments are EigenDA
6570
t.Logf("[Stage1: EigenDA] Checking that the initial commitments are EigenDA")
6671
requireBatcherTxsToBeFromLayer(t, fromBlock, fromBlock+l1BlocksQueriedForBatcherTxs, DALayerEigenDA, harness.Endpoints.GethL1Endpoint, harness.BatchInboxAddr)
6772

6873
// 2. Failover and check that the commitments are now EthDACalldata
6974
t.Logf("[Stage2: EthDA-Calldata] Failing over... changing proxy's config to return 503 errors")
70-
err := harness.Clients.ProxyMemconfigClient.Failover(ctxWithDeadline)
75+
err = harness.Clients.ProxyClients.Failover(ctxWithDeadline)
7176
require.NoError(t, err)
7277

7378
afterFailoverFromBlockNum, err := harness.Clients.GethL1Client.BlockNumber(ctxWithDeadline)
@@ -90,7 +95,7 @@ func TestFailoverToEthDACalldata_Memstore(t *testing.T) {
9095

9196
// 3. Failback and check that the commitments are EigenDA again
9297
t.Logf("[Stage3: EigenDA] Failing back... changing proxy's config to start processing PUT requests normally again")
93-
err = harness.Clients.ProxyMemconfigClient.Failback(ctxWithDeadline)
98+
err = harness.Clients.ProxyClients.Failback(ctxWithDeadline)
9499
require.NoError(t, err)
95100

96101
afterFailbackFromBlockNum, err := harness.Clients.GethL1Client.BlockNumber(ctxWithDeadline)
@@ -115,6 +120,7 @@ func requireBatcherTxsToBeFromLayer(t *testing.T, fromBlockNum, toBlockNum uint6
115120
wrongCommitmentsToDiscard := 0
116121
for _, batcherTx := range batcherTxs {
117122
if batcherTx.daLayer != expectedLayer {
123+
t.Logf("Discarding batcher tx @ block %d with wrong commitment type %s (expected %s)", batcherTx.block, batcherTx.daLayer, expectedLayer)
118124
wrongCommitmentsToDiscard++
119125
}
120126
// as soon as we see a commitment from expectedLayer, we stop discarding.
@@ -138,15 +144,28 @@ func requireBatcherTxsToBeFromLayer(t *testing.T, fromBlockNum, toBlockNum uint6
138144
// Note that 4844 txs are completely different and don't use normal txs with a prefix in the calldata,
139145
// see https://github.com/ethereum-optimism/optimism/blob/develop/op-node/rollup/derive/blob_data_source.go#L134-L137
140146
const ethDACalldataCommitmentPrefix = "0x00"
141-
const eigenDACommitmentPrefix = "0x010100"
147+
const eigenDAV1CommitmentPrefix = "0x01010000"
148+
const eigenDAV2CommitmentPrefix = "0x01010001"
142149

143150
type DALayer string
144151

145152
const (
146153
DALayerEthCalldata DALayer = "ethda-calldata"
147-
DALayerEigenDA DALayer = "eigenda"
154+
DALayerEigenDAV1 DALayer = "eigendaV1"
155+
DALayerEigenDAV2 DALayer = "eigendaV2"
148156
)
149157

158+
func certVersionToDALayer(certVersion EigenDACertVersion) (DALayer, error) {
159+
switch certVersion {
160+
case EigenDACertVersionV1:
161+
return DALayerEigenDAV1, nil
162+
case EigenDACertVersionV2:
163+
return DALayerEigenDAV2, nil
164+
default:
165+
return "", fmt.Errorf("unknown EigenDA cert version: %s", certVersion)
166+
}
167+
}
168+
150169
type BatcherTx struct {
151170
commitment string
152171
daLayer DALayer // commitment starts with respective prefix
@@ -241,19 +260,20 @@ func fetchBatcherTxs(gethL1Endpoint string, batchInbox string, fromBlockNum, toB
241260
for _, block := range graphQLResp.Data.Blocks {
242261
for _, tx := range block.Transactions {
243262
if strings.EqualFold(tx.To.Address, batchInbox) {
244-
var daLayer DALayer
245-
if strings.HasPrefix(tx.InputData, eigenDACommitmentPrefix) {
246-
daLayer = DALayerEigenDA
263+
batcherTx := BatcherTx{
264+
commitment: tx.InputData,
265+
block: uint64(tx.Block.Number),
266+
}
267+
if strings.HasPrefix(tx.InputData, eigenDAV1CommitmentPrefix) {
268+
batcherTx.daLayer = DALayerEigenDAV1
269+
} else if strings.HasPrefix(tx.InputData, eigenDAV2CommitmentPrefix) {
270+
batcherTx.daLayer = DALayerEigenDAV2
247271
} else if strings.HasPrefix(tx.InputData, ethDACalldataCommitmentPrefix) {
248-
daLayer = DALayerEthCalldata
272+
batcherTx.daLayer = DALayerEthCalldata
249273
} else {
250274
return nil, fmt.Errorf("unknown commitment prefix: %s", tx.InputData)
251275
}
252-
batcherTxs = append(batcherTxs, BatcherTx{
253-
commitment: tx.InputData,
254-
daLayer: daLayer,
255-
block: uint64(tx.Block.Number),
256-
})
276+
batcherTxs = append(batcherTxs, batcherTx)
257277
}
258278
}
259279
}

0 commit comments

Comments
 (0)