4
4
"context"
5
5
"encoding/json"
6
6
"fmt"
7
+ "log/slog"
7
8
"math/big"
8
9
"net/http"
9
10
"reflect"
@@ -14,9 +15,12 @@ import (
14
15
15
16
"github.com/Layr-Labs/eigenda-proxy/clients/memconfig_client"
16
17
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/geth"
18
+ "github.com/ethereum-optimism/optimism/op-service/dial"
19
+ "github.com/ethereum-optimism/optimism/op-service/sources"
20
+ "github.com/ethereum-optimism/optimism/op-service/testlog"
17
21
"github.com/ethereum/go-ethereum/common"
18
22
"github.com/ethereum/go-ethereum/ethclient"
19
- "github.com/ethereum/go-ethereum/rpc "
23
+ "github.com/ethereum/go-ethereum/log "
20
24
"github.com/kurtosis-tech/kurtosis/api/golang/core/lib/enclaves"
21
25
"github.com/kurtosis-tech/kurtosis/api/golang/engine/lib/kurtosis_context"
22
26
"github.com/stretchr/testify/require"
@@ -35,20 +39,18 @@ const enclaveName = "eigenda-memstore-devnet"
35
39
//
36
40
// Note: because this test relies on modifying the proxy's memstore config, it should be run in isolation.
37
41
// That is, if we ever implement more kurtosis tests, they would currently need to be run sequentially.
38
- //
39
- // TODO: We will also need to test the failover behavior of the node, which currently doesn't finalize after failover (fixed in https://github.com/Layr-Labs/optimism/pull/23)
40
42
func TestFailoverToEthDACalldata (t * testing.T ) {
41
43
deadline , ok := t .Deadline ()
42
44
if ! ok {
43
- deadline = time .Now ().Add (1 * time .Minute )
45
+ deadline = time .Now ().Add (10 * time .Minute )
44
46
}
45
47
ctxWithDeadline , cancel := context .WithDeadline (context .Background (), deadline )
46
48
defer cancel ()
47
49
48
50
harness := newHarness (t )
49
51
t .Cleanup (func () {
50
52
// switch proxy back to normal mode, in case test gets cancelled
51
- ctx , cancel := context .WithTimeout (context .Background (), 5 * time .Second )
53
+ ctx , cancel := context .WithTimeout (context .Background (), 10 * time .Second )
52
54
defer cancel ()
53
55
err := harness .clients .proxyMemconfigClient .Failback (ctx )
54
56
if err != nil {
@@ -75,7 +77,7 @@ func TestFailoverToEthDACalldata(t *testing.T) {
75
77
harness .requireBatcherTxsToBeFromLayer (t , fromBlock , fromBlock + l1BlocksQueriedForBatcherTxs , DALayerEigenDA )
76
78
77
79
// 2. Failover and check that the commitments are now EthDACalldata
78
- t .Logf ("Failover over... changing proxy's config to return 503 errors" )
80
+ t .Logf ("Failing over... changing proxy's config to return 503 errors" )
79
81
err := harness .clients .proxyMemconfigClient .Failover (ctxWithDeadline )
80
82
require .NoError (t , err )
81
83
@@ -87,6 +89,16 @@ func TestFailoverToEthDACalldata(t *testing.T) {
87
89
88
90
harness .requireBatcherTxsToBeFromLayer (t , afterFailoverFromBlockNum , afterFailoverToBlockNum , DALayerEthCalldata )
89
91
92
+ // We also check that the op-node is still finalizing blocks after the failover
93
+ syncStatus , err := harness .clients .opNodeClient .SyncStatus (ctxWithDeadline )
94
+ require .NoError (t , err )
95
+ afterFailoverFinalizedL2 := syncStatus .FinalizedL2
96
+ t .Logf ("Current finalized L2 block: %d. Waiting for next block to finalize to make sure finalization is still happening." , afterFailoverFinalizedL2 .Number )
97
+ // On average would expect this to take half an epoch, aka 16 L1 blocks, which at 6 sec/block means 1.5 minutes.
98
+ // This generally takes longer (3-6 minutes), but I'm not quite sure why.
99
+ _ , err = geth .WaitForBlockToBeFinalized (new (big.Int ).SetUint64 (afterFailoverFinalizedL2 .Number + 1 ), harness .clients .opGethClient , 6 * time .Minute )
100
+ require .NoError (t , err , "op-node should still be finalizing blocks after failover" )
101
+
90
102
// 3. Failback and check that the commitments are EigenDA again
91
103
t .Logf ("Failing back... changing proxy's config to start processing PUT requests normally again" )
92
104
err = harness .clients .proxyMemconfigClient .Failback (ctxWithDeadline )
@@ -105,13 +117,16 @@ func TestFailoverToEthDACalldata(t *testing.T) {
105
117
// Test Harness, which contains all the state needed to run the tests.
106
118
// harness also defines some higher-level "require" methods that are used in the tests.
107
119
type harness struct {
120
+ logger log.Logger
108
121
endpoints * EnclaveServicePublicEndpoints
109
122
clients * EnclaveServiceClients
110
123
batchInboxAddr common.Address
111
124
testStartL1BlockNum uint64
112
125
}
113
126
114
127
func newHarness (t * testing.T ) * harness {
128
+ logger := testlog .Logger (t , slog .LevelInfo )
129
+
115
130
// We leave 20 seconds to build the entire testHarness.
116
131
ctxWithTimeout , cancel := context .WithTimeout (context .Background (), 20 * time .Second )
117
132
defer cancel ()
@@ -128,24 +143,22 @@ func newHarness(t *testing.T) *harness {
128
143
require .NoError (t , err )
129
144
t .Logf ("Endpoints: %+v" , endpoints )
130
145
131
- clients , err := getClientsFromEndpoints (endpoints )
146
+ clients , err := getClientsFromEndpoints (ctxWithTimeout , logger , endpoints )
132
147
require .NoError (t , err )
133
148
134
- // Get the batch inbox address
135
- var rollupConfigMap struct {
136
- BatchInboxAddress string `json:"batch_inbox_address"`
137
- }
138
- err = clients .opNodeClient .CallContext (ctxWithTimeout , & rollupConfigMap , "optimism_rollupConfig" )
149
+ // Get the batch inbox address from the rollup config
150
+ rollupConfig , err := clients .opNodeClient .RollupConfig (ctxWithTimeout )
139
151
require .NoError (t , err )
140
152
141
153
// Get the current L1 block number
142
154
testStartL1BlockNum , err := clients .gethL1Client .BlockNumber (ctxWithTimeout )
143
155
require .NoError (t , err )
144
156
145
157
return & harness {
158
+ logger : logger ,
146
159
endpoints : endpoints ,
147
160
clients : clients ,
148
- batchInboxAddr : common . HexToAddress ( rollupConfigMap . BatchInboxAddress ) ,
161
+ batchInboxAddr : rollupConfig . BatchInboxAddress ,
149
162
testStartL1BlockNum : testStartL1BlockNum ,
150
163
}
151
164
}
@@ -315,6 +328,7 @@ func fetchBatcherTxs(gethL1Endpoint string, batchInbox string, fromBlockNum, toB
315
328
// The public endpoints are the ones that are exposed to the host machine.
316
329
type EnclaveServicePublicEndpoints struct {
317
330
OpNodeEndpoint string `kurtosis:"op-cl-1-op-node-op-geth-op-kurtosis,http"`
331
+ OpGethEndpoint string `kurtosis:"op-el-1-op-geth-op-node-op-kurtosis,rpc"`
318
332
GethL1Endpoint string `kurtosis:"el-1-geth-teku,rpc"`
319
333
EigendaProxyEndpoint string `kurtosis:"da-server-op-kurtosis,http"`
320
334
// Adding new endpoints is as simple as adding a new field with a kurtosis tag
@@ -374,17 +388,29 @@ func getPublicEndpointsFromKurtosis(enclaveCtx *enclaves.EnclaveContext) (*Encla
374
388
}
375
389
376
390
type EnclaveServiceClients struct {
377
- opNodeClient * rpc.Client
378
- gethL1Client * ethclient.Client
391
+ // opNode and opGeth are the L2 clients for the rollup.
392
+ opNodeClient * sources.RollupClient
393
+ // opGeth is the client for the L2 execution layer client.
394
+ opGethClient * ethclient.Client
395
+ // gethL1 is the client for the L1 chain execution layer client.
396
+ gethL1Client * ethclient.Client
397
+ // proxyMemconfigClient is the client for the eigenda-proxy's memstore config API.
398
+ // It allows us to toggle the proxy's failover behavior.
379
399
proxyMemconfigClient * ProxyMemconfigClient
380
400
}
381
401
382
- func getClientsFromEndpoints (endpoints * EnclaveServicePublicEndpoints ) (* EnclaveServiceClients , error ) {
383
- opNodeClient , err := rpc .Dial (endpoints .OpNodeEndpoint )
402
+ func getClientsFromEndpoints (ctx context.Context , logger log.Logger , endpoints * EnclaveServicePublicEndpoints ) (* EnclaveServiceClients , error ) {
403
+ opNodeClient , err := dial .DialRollupClientWithTimeout (ctx , 10 * time .Second , logger , endpoints .OpNodeEndpoint )
404
+ if err != nil {
405
+ return nil , fmt .Errorf ("dial.DialRollupClientWithTimeout: %w" , err )
406
+ }
407
+
408
+ opGethClient , err := dial .DialEthClientWithTimeout (ctx , 10 * time .Second , logger , endpoints .OpGethEndpoint )
384
409
if err != nil {
385
- return nil , fmt .Errorf ("rpc.Dial : %w" , err )
410
+ return nil , fmt .Errorf ("dial.DialEthClientWithTimeout : %w" , err )
386
411
}
387
412
413
+ // TODO: prob also change to use dial.DialEthClient?
388
414
gethL1Client , err := ethclient .Dial (endpoints .GethL1Endpoint )
389
415
if err != nil {
390
416
return nil , fmt .Errorf ("ethclient.Dial: %w" , err )
@@ -396,6 +422,7 @@ func getClientsFromEndpoints(endpoints *EnclaveServicePublicEndpoints) (*Enclave
396
422
397
423
return & EnclaveServiceClients {
398
424
opNodeClient : opNodeClient ,
425
+ opGethClient : opGethClient ,
399
426
gethL1Client : gethL1Client ,
400
427
proxyMemconfigClient : proxyMemconfigClient ,
401
428
}, nil
0 commit comments