Skip to content

Commit 5a18b06

Browse files
authored
op-e2e: Pass multiple chain configs through when running op-program in interop tests (#13731)
1 parent dd90204 commit 5a18b06

File tree

11 files changed

+158
-192
lines changed

11 files changed

+158
-192
lines changed

op-e2e/actions/interop/interop_test.go

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99
"github.com/ethereum-optimism/optimism/op-program/client/claim"
1010
"github.com/ethereum-optimism/optimism/op-program/client/interop/types"
1111
"github.com/ethereum-optimism/optimism/op-service/testlog"
12+
"github.com/ethereum/go-ethereum/common"
1213
"github.com/ethereum/go-ethereum/crypto"
1314
"github.com/stretchr/testify/require"
1415

@@ -355,20 +356,35 @@ func TestInteropFaultProofs(gt *testing.T) {
355356
t,
356357
logger,
357358
actors.L1Miner,
358-
actors.ChainA.Sequencer.L2Verifier,
359-
actors.ChainA.SequencerEngine,
360-
actors.ChainA.L2Genesis,
361-
chain1End.BlockRef.Number,
362359
checkResult,
363-
fpHelpers.WithInteropEnabled(),
364-
fpHelpers.WithAgreedPrestate(test.agreedClaim),
365-
fpHelpers.WithL2Claim(crypto.Keccak256Hash(test.disputedClaim)),
366-
fpHelpers.WithL2BlockNumber(endBlockNumA),
360+
WithInteropEnabled(actors, test.agreedClaim, crypto.Keccak256Hash(test.disputedClaim), endTimestamp),
367361
)
368362
})
369363
}
370364
}
371365

366+
func WithInteropEnabled(actors *InteropActors, agreedPrestate []byte, disputedClaim common.Hash, claimTimestamp uint64) fpHelpers.FixtureInputParam {
367+
return func(f *fpHelpers.FixtureInputs) {
368+
f.InteropEnabled = true
369+
f.AgreedPrestate = agreedPrestate
370+
f.L2OutputRoot = crypto.Keccak256Hash(agreedPrestate)
371+
f.L2Claim = disputedClaim
372+
f.L2BlockNumber = claimTimestamp
373+
374+
// TODO: Remove these once hints all specify the L2 chain ID
375+
f.L2ChainID = actors.ChainA.ChainID.ToBig().Uint64()
376+
f.L2Head = actors.ChainA.SequencerEngine.L2Chain().CurrentHeader().ParentHash
377+
378+
for _, chain := range []*Chain{actors.ChainA, actors.ChainB} {
379+
f.L2Sources = append(f.L2Sources, &fpHelpers.FaultProofProgramL2Source{
380+
Node: chain.Sequencer.L2Verifier,
381+
Engine: chain.SequencerEngine,
382+
ChainConfig: chain.L2Genesis.Config,
383+
})
384+
}
385+
}
386+
}
387+
372388
type transitionTest struct {
373389
name string
374390
startTimestamp uint64

op-e2e/actions/proofs/helpers/env.go

Lines changed: 13 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,14 @@ import (
66
"github.com/ethereum-optimism/optimism/op-chain-ops/genesis"
77
e2ecfg "github.com/ethereum-optimism/optimism/op-e2e/config"
88
"github.com/ethereum-optimism/optimism/op-node/rollup"
9-
"github.com/ethereum/go-ethereum/crypto"
9+
"github.com/ethereum-optimism/optimism/op-program/client/boot"
1010
"github.com/ethereum/go-ethereum/params"
1111

1212
altda "github.com/ethereum-optimism/optimism/op-alt-da"
1313
batcherFlags "github.com/ethereum-optimism/optimism/op-batcher/flags"
1414
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
1515
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils"
1616
"github.com/ethereum-optimism/optimism/op-program/host/config"
17-
hostTypes "github.com/ethereum-optimism/optimism/op-program/host/types"
1817
"github.com/ethereum-optimism/optimism/op-service/sources"
1918
"github.com/ethereum-optimism/optimism/op-service/testlog"
2019
"github.com/ethereum/go-ethereum/common"
@@ -152,27 +151,17 @@ func WithL2Claim(claim common.Hash) FixtureInputParam {
152151
}
153152
}
154153

155-
func WithAgreedPrestate(prestate []byte) FixtureInputParam {
156-
return func(f *FixtureInputs) {
157-
f.AgreedPrestate = prestate
158-
f.L2OutputRoot = crypto.Keccak256Hash(prestate)
159-
}
160-
}
161-
162154
func WithL2BlockNumber(num uint64) FixtureInputParam {
163155
return func(f *FixtureInputs) {
164156
f.L2BlockNumber = num
165157
}
166158
}
167159

168-
func WithInteropEnabled() FixtureInputParam {
169-
return func(f *FixtureInputs) {
170-
f.InteropEnabled = true
171-
}
172-
}
173-
174160
func (env *L2FaultProofEnv) RunFaultProofProgram(t helpers.Testing, l2ClaimBlockNum uint64, checkResult CheckResult, fixtureInputParams ...FixtureInputParam) {
175-
RunFaultProofProgram(t, env.log, env.Miner, env.Sequencer.L2Verifier, env.Engine, env.Sd.L2Cfg, l2ClaimBlockNum, checkResult, fixtureInputParams...)
161+
defaultParam := WithPreInteropDefaults(t, l2ClaimBlockNum, env.Sequencer.L2Verifier, env.Engine)
162+
combinedParams := []FixtureInputParam{defaultParam}
163+
combinedParams = append(combinedParams, fixtureInputParams...)
164+
RunFaultProofProgram(t, env.log, env.Miner, checkResult, combinedParams...)
176165
}
177166

178167
type TestParam func(p *e2eutils.TestParams)
@@ -210,17 +199,17 @@ func NewBatcherCfg(params ...BatcherCfgParam) *helpers.BatcherCfg {
210199
}
211200

212201
func NewOpProgramCfg(
213-
t helpers.Testing,
214-
rollupCfg *rollup.Config,
215-
l2Genesis *params.ChainConfig,
216202
fi *FixtureInputs,
217203
) *config.Config {
218-
dfault := config.NewConfig(rollupCfg, l2Genesis, fi.L1Head, fi.L2Head, fi.L2OutputRoot, fi.L2Claim, fi.L2BlockNumber)
219-
220-
if dumpFixtures {
221-
dfault.DataDir = t.TempDir()
222-
dfault.DataFormat = hostTypes.DataFormatPebble
204+
var rollupConfigs []*rollup.Config
205+
var chainConfigs []*params.ChainConfig
206+
for _, source := range fi.L2Sources {
207+
rollupConfigs = append(rollupConfigs, source.Node.RollupCfg)
208+
chainConfigs = append(chainConfigs, source.ChainConfig)
223209
}
210+
211+
dfault := config.NewConfig(rollupConfigs, chainConfigs, fi.L1Head, fi.L2Head, fi.L2OutputRoot, fi.L2Claim, fi.L2BlockNumber)
212+
dfault.L2ChainID = boot.CustomChainIDIndicator
224213
if fi.InteropEnabled {
225214
dfault.AgreedPrestate = fi.AgreedPrestate
226215
}
Lines changed: 8 additions & 114 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,23 @@
11
package helpers
22

33
import (
4-
"encoding/json"
5-
"errors"
6-
"io/fs"
7-
"os"
8-
"os/exec"
9-
"path/filepath"
10-
"regexp"
11-
"strings"
12-
134
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
14-
"github.com/ethereum-optimism/optimism/op-node/rollup"
15-
"github.com/ethereum-optimism/optimism/op-program/client/claim"
165
"github.com/ethereum/go-ethereum/common"
17-
"github.com/ethereum/go-ethereum/core"
18-
"github.com/naoina/toml"
19-
"github.com/stretchr/testify/require"
20-
)
21-
22-
var (
23-
dumpFixtures = false
24-
fixtureDir string
6+
"github.com/ethereum/go-ethereum/params"
257
)
268

27-
func init() {
28-
fixtureDir = os.Getenv("OP_E2E_FPP_FIXTURE_DIR")
29-
if fixtureDir != "" {
30-
dumpFixtures = true
31-
}
32-
}
33-
349
type TestFixture struct {
3510
Name string `toml:"name"`
3611
ExpectedStatus uint8 `toml:"expected-status"`
3712
Inputs FixtureInputs `toml:"inputs"`
3813
}
3914

15+
type FaultProofProgramL2Source struct {
16+
Node *helpers.L2Verifier
17+
Engine *helpers.L2Engine
18+
ChainConfig *params.ChainConfig
19+
}
20+
4021
type FixtureInputs struct {
4122
L2BlockNumber uint64 `toml:"l2-block-number"`
4223
L2Claim common.Hash `toml:"l2-claim"`
@@ -46,93 +27,6 @@ type FixtureInputs struct {
4627
L1Head common.Hash `toml:"l1-head"`
4728
AgreedPrestate []byte `toml:"agreed-prestate"`
4829
InteropEnabled bool `toml:"use-interop"`
49-
}
50-
51-
// Dumps a `fp-tests` test fixture to disk if the `OP_E2E_FPP_FIXTURE_DIR` environment variable is set.
52-
//
53-
// [fp-tests]: https://github.com/ethereum-optimism/fp-tests
54-
func tryDumpTestFixture(
55-
t helpers.Testing,
56-
result error,
57-
name string,
58-
rollupCfg *rollup.Config,
59-
l2Genesis *core.Genesis,
60-
inputs FixtureInputs,
61-
workDir string,
62-
) {
63-
if !dumpFixtures {
64-
return
65-
}
66-
67-
name = convertToKebabCase(name)
68-
69-
var expectedStatus uint8
70-
if result == nil {
71-
expectedStatus = 0
72-
} else if errors.Is(result, claim.ErrClaimNotValid) {
73-
expectedStatus = 1
74-
} else {
75-
expectedStatus = 2
76-
}
77-
78-
fixture := TestFixture{
79-
Name: name,
80-
ExpectedStatus: expectedStatus,
81-
Inputs: inputs,
82-
}
83-
84-
fixturePath := filepath.Join(fixtureDir, name)
85-
86-
err := os.MkdirAll(filepath.Join(fixturePath), fs.ModePerm)
87-
require.NoError(t, err, "failed to create fixture dir")
88-
89-
fixtureFilePath := filepath.Join(fixturePath, "fixture.toml")
90-
serFixture, err := toml.Marshal(fixture)
91-
require.NoError(t, err, "failed to serialize fixture")
92-
require.NoError(t, os.WriteFile(fixtureFilePath, serFixture, fs.ModePerm), "failed to write fixture")
93-
94-
genesisPath := filepath.Join(fixturePath, "genesis.json")
95-
serGenesis, err := l2Genesis.MarshalJSON()
96-
require.NoError(t, err, "failed to serialize genesis")
97-
require.NoError(t, os.WriteFile(genesisPath, serGenesis, fs.ModePerm), "failed to write genesis")
98-
99-
rollupPath := filepath.Join(fixturePath, "rollup.json")
100-
serRollup, err := json.Marshal(rollupCfg)
101-
require.NoError(t, err, "failed to serialize rollup")
102-
require.NoError(t, os.WriteFile(rollupPath, serRollup, fs.ModePerm), "failed to write rollup")
103-
104-
// Copy the witness database into the fixture directory.
105-
cmd := exec.Command("cp", "-r", workDir, filepath.Join(fixturePath, "witness-db"))
106-
require.NoError(t, cmd.Run(), "Failed to copy witness DB")
107-
108-
// Compress the genesis file.
109-
cmd = exec.Command("zstd", genesisPath)
110-
_ = cmd.Run()
111-
require.NoError(t, os.Remove(genesisPath), "Failed to remove uncompressed genesis file")
112-
113-
// Compress the witness database.
114-
cmd = exec.Command(
115-
"tar",
116-
"--zstd",
117-
"-cf",
118-
filepath.Join(fixturePath, "witness-db.tar.zst"),
119-
filepath.Join(fixturePath, "witness-db"),
120-
)
121-
cmd.Dir = filepath.Join(fixturePath)
122-
require.NoError(t, cmd.Run(), "Failed to compress witness DB")
123-
require.NoError(t, os.RemoveAll(filepath.Join(fixturePath, "witness-db")), "Failed to remove uncompressed witness DB")
124-
}
125-
126-
// Convert to lower kebab case for strings containing `/`
127-
func convertToKebabCase(input string) string {
128-
if !strings.Contains(input, "/") {
129-
return input
130-
}
131-
132-
// Replace non-alphanumeric characters with underscores
133-
re := regexp.MustCompile(`[^a-zA-Z0-9]+`)
134-
snake := re.ReplaceAllString(input, "-")
13530

136-
// Convert to lower case
137-
return strings.ToLower(snake)
31+
L2Sources []*FaultProofProgramL2Source
13832
}

op-e2e/actions/proofs/helpers/runner.go

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import (
55

66
"github.com/ethereum-optimism/optimism/op-e2e/actions/helpers"
77
"github.com/ethereum-optimism/optimism/op-e2e/e2eutils/fakebeacon"
8-
"github.com/ethereum-optimism/optimism/op-node/rollup"
98
"github.com/ethereum-optimism/optimism/op-program/host"
109
hostcommon "github.com/ethereum-optimism/optimism/op-program/host/common"
1110
"github.com/ethereum-optimism/optimism/op-program/host/config"
@@ -14,7 +13,6 @@ import (
1413
"github.com/ethereum-optimism/optimism/op-service/client"
1514
"github.com/ethereum-optimism/optimism/op-service/sources"
1615
"github.com/ethereum/go-ethereum/common"
17-
"github.com/ethereum/go-ethereum/core"
1816
"github.com/ethereum/go-ethereum/log"
1917
"github.com/stretchr/testify/require"
2018
)
@@ -26,33 +24,50 @@ type L2 interface {
2624
RollupClient() *sources.RollupClient
2725
}
2826

29-
func RunFaultProofProgram(t helpers.Testing, logger log.Logger, l1 *helpers.L1Miner, l2 *helpers.L2Verifier, l2Eng *helpers.L2Engine, l2ChainConfig *core.Genesis, l2ClaimBlockNum uint64, checkResult CheckResult, fixtureInputParams ...FixtureInputParam) {
30-
// Fetch the pre and post output roots for the fault proof.
31-
l2PreBlockNum := l2ClaimBlockNum - 1
32-
if l2ClaimBlockNum == 0 {
33-
// If we are at genesis, we assert that we don't move the chain at all.
34-
l2PreBlockNum = 0
27+
func WithPreInteropDefaults(t helpers.Testing, l2ClaimBlockNum uint64, l2 *helpers.L2Verifier, l2Eng *helpers.L2Engine) FixtureInputParam {
28+
return func(f *FixtureInputs) {
29+
// Fetch the pre and post output roots for the fault proof.
30+
l2PreBlockNum := l2ClaimBlockNum - 1
31+
if l2ClaimBlockNum == 0 {
32+
// If we are at genesis, we assert that we don't move the chain at all.
33+
l2PreBlockNum = 0
34+
}
35+
rollupClient := l2.RollupClient()
36+
preRoot, err := rollupClient.OutputAtBlock(t.Ctx(), l2PreBlockNum)
37+
require.NoError(t, err)
38+
claimRoot, err := rollupClient.OutputAtBlock(t.Ctx(), l2ClaimBlockNum)
39+
require.NoError(t, err)
40+
41+
f.L2BlockNumber = l2ClaimBlockNum
42+
f.L2Claim = common.Hash(claimRoot.OutputRoot)
43+
f.L2Head = preRoot.BlockRef.Hash
44+
f.L2OutputRoot = common.Hash(preRoot.OutputRoot)
45+
f.L2ChainID = l2.RollupCfg.L2ChainID.Uint64()
46+
47+
f.L2Sources = []*FaultProofProgramL2Source{
48+
{
49+
Node: l2,
50+
Engine: l2Eng,
51+
ChainConfig: l2Eng.L2Chain().Config(),
52+
},
53+
}
3554
}
36-
preRoot, err := l2.RollupClient().OutputAtBlock(t.Ctx(), l2PreBlockNum)
37-
require.NoError(t, err)
38-
claimRoot, err := l2.RollupClient().OutputAtBlock(t.Ctx(), l2ClaimBlockNum)
39-
require.NoError(t, err)
55+
}
56+
57+
func RunFaultProofProgram(t helpers.Testing, logger log.Logger, l1 *helpers.L1Miner, checkResult CheckResult, fixtureInputParams ...FixtureInputParam) {
4058
l1Head := l1.L1Chain().CurrentBlock()
4159

4260
fixtureInputs := &FixtureInputs{
43-
L2BlockNumber: l2ClaimBlockNum,
44-
L2Claim: common.Hash(claimRoot.OutputRoot),
45-
L2Head: preRoot.BlockRef.Hash,
46-
L2OutputRoot: common.Hash(preRoot.OutputRoot),
47-
L2ChainID: l2.RollupCfg.L2ChainID.Uint64(),
48-
L1Head: l1Head.Hash(),
61+
L1Head: l1Head.Hash(),
4962
}
5063
for _, apply := range fixtureInputParams {
5164
apply(fixtureInputs)
5265
}
66+
require.Greater(t, len(fixtureInputs.L2Sources), 0, "Must specify at least one L2 source")
5367

5468
// Run the fault proof program from the state transition from L2 block l2ClaimBlockNum - 1 -> l2ClaimBlockNum.
5569
workDir := t.TempDir()
70+
var err error
5671
if IsKonaConfigured() {
5772
fakeBeacon := fakebeacon.NewBeacon(
5873
logger,
@@ -63,29 +78,28 @@ func RunFaultProofProgram(t helpers.Testing, logger log.Logger, l1 *helpers.L1Mi
6378
require.NoError(t, fakeBeacon.Start("127.0.0.1:0"))
6479
defer fakeBeacon.Close()
6580

66-
err := RunKonaNative(t, workDir, l2.RollupCfg, l1.HTTPEndpoint(), fakeBeacon.BeaconAddr(), l2Eng.HTTPEndpoint(), *fixtureInputs)
81+
l2Source := fixtureInputs.L2Sources[0]
82+
err = RunKonaNative(t, workDir, l2Source.Node.RollupCfg, l1.HTTPEndpoint(), fakeBeacon.BeaconAddr(), l2Source.Engine.HTTPEndpoint(), *fixtureInputs)
6783
checkResult(t, err)
6884
} else {
69-
programCfg := NewOpProgramCfg(
70-
t,
71-
l2.RollupCfg,
72-
l2ChainConfig.Config,
73-
fixtureInputs,
74-
)
85+
programCfg := NewOpProgramCfg(fixtureInputs)
7586
withInProcessPrefetcher := hostcommon.WithPrefetcher(func(ctx context.Context, logger log.Logger, kv kvstore.KV, cfg *config.Config) (hostcommon.Prefetcher, error) {
7687
// Set up in-process L1 sources
77-
l1Cl := l1.L1Client(t, l2.RollupCfg)
88+
l1Cl := l1.L1ClientSimple(t)
7889
l1BlobFetcher := l1.BlobSource()
7990

8091
// Set up in-process L2 source
81-
sources, err := prefetcher.NewRetryingL2Sources(ctx, logger, []*rollup.Config{l2.RollupCfg}, []client.RPC{l2Eng.RPCClient()}, nil)
92+
var rpcClients []client.RPC
93+
for _, source := range fixtureInputs.L2Sources {
94+
rpcClients = append(rpcClients, source.Engine.RPCClient())
95+
}
96+
sources, err := prefetcher.NewRetryingL2Sources(ctx, logger, programCfg.Rollups, rpcClients, nil)
8297
require.NoError(t, err, "failed to create L2 client")
8398

8499
executor := host.MakeProgramExecutor(logger, programCfg)
85-
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, l2.RollupCfg.L2ChainID.Uint64(), sources, kv, executor, cfg.L2Head, cfg.AgreedPrestate), nil
100+
return prefetcher.NewPrefetcher(logger, l1Cl, l1BlobFetcher, fixtureInputs.L2ChainID, sources, kv, executor, cfg.L2Head, cfg.AgreedPrestate), nil
86101
})
87102
err = hostcommon.FaultProofProgram(t.Ctx(), logger, programCfg, withInProcessPrefetcher)
88103
checkResult(t, err)
89104
}
90-
tryDumpTestFixture(t, err, t.Name(), l2.RollupCfg, l2ChainConfig, *fixtureInputs, workDir)
91105
}

0 commit comments

Comments
 (0)