diff --git a/mise.toml b/mise.toml index 67e6168603993..241457394dc46 100644 --- a/mise.toml +++ b/mise.toml @@ -38,7 +38,7 @@ anvil = "1.1.0" codecov-uploader = "0.8.0" goreleaser-pro = "2.3.2-pro" kurtosis = "1.6.0" -op-acceptor = "op-acceptor/v0.2.0" +op-acceptor = "op-acceptor/v0.2.1" # Fake dependencies # Put things here if you need to track versions of tools or projects that can't diff --git a/op-acceptance-tests/acceptance-tests.yaml b/op-acceptance-tests/acceptance-tests.yaml index 27ef7596e1dcd..81db5d83fe7b9 100644 --- a/op-acceptance-tests/acceptance-tests.yaml +++ b/op-acceptance-tests/acceptance-tests.yaml @@ -8,10 +8,7 @@ gates: - id: base description: "Sanity/smoke acceptance tests for all networks." tests: - - name: TestRPCConnectivity - package: github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/base - - name: TestChainFork - package: github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/base + - package: github.com/ethereum-optimism/optimism/op-acceptance-tests/tests/base - id: holocene inherits: diff --git a/op-acceptance-tests/tests/base/advance_test.go b/op-acceptance-tests/tests/base/advance_test.go new file mode 100644 index 0000000000000..3a4826f8ec055 --- /dev/null +++ b/op-acceptance-tests/tests/base/advance_test.go @@ -0,0 +1,31 @@ +package base + +import ( + "testing" + "time" + + "github.com/ethereum-optimism/optimism/op-devstack/devtest" + "github.com/ethereum-optimism/optimism/op-devstack/presets" + "github.com/stretchr/testify/require" +) + +func TestCLAdvance(gt *testing.T) { + t := devtest.ParallelT(gt) + sys := presets.NewMinimal(t) + tracer := t.Tracer() + ctx := t.Ctx() + + blockTime := sys.L2Chain.Escape().RollupConfig().BlockTime + waitTime := time.Duration(blockTime+1) * time.Second + + num := sys.L2CL.SafeL2BlockRef().Number + new_num := num + require.Eventually(t, func() bool { + ctx, span := tracer.Start(ctx, "check head") + defer span.End() + + new_num, num = sys.L2CL.SafeL2BlockRef().Number, new_num + t.Logger().WithContext(ctx).Info("safe head", "number", new_num) + return new_num > num + }, 30*time.Second, waitTime) +} diff --git a/op-acceptance-tests/tests/base/faucet_test.go b/op-acceptance-tests/tests/base/faucet_test.go new file mode 100644 index 0000000000000..1846a2a87c4e0 --- /dev/null +++ b/op-acceptance-tests/tests/base/faucet_test.go @@ -0,0 +1,27 @@ +package base + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-devstack/devtest" + "github.com/ethereum-optimism/optimism/op-devstack/presets" + "github.com/ethereum-optimism/optimism/op-service/eth" +) + +func TestFaucetFund(gt *testing.T) { + t := devtest.ParallelT(gt) + sys := presets.NewMinimal(t) + tracer := t.Tracer() + ctx := t.Ctx() + + ctx, span := tracer.Start(ctx, "acquire wallets") + funded := sys.Funder.NewFundedEOA(eth.Ether(2)) + unfunded := sys.Wallet.NewEOA(sys.L2EL) + span.End() + + _, span = tracer.Start(ctx, "transfer funds") + amount := eth.OneEther + funded.Transfer(unfunded.Address(), amount) + t.Logger().WithContext(ctx).Info("funds transferred", "amount", amount) + span.End() +} diff --git a/op-acceptance-tests/tests/base/init_test.go b/op-acceptance-tests/tests/base/init_test.go new file mode 100644 index 0000000000000..b1fadd34b9081 --- /dev/null +++ b/op-acceptance-tests/tests/base/init_test.go @@ -0,0 +1,13 @@ +package base + +import ( + "testing" + + "github.com/ethereum-optimism/optimism/op-devstack/presets" +) + +// TestMain creates the test-setups against the shared backend +func TestMain(m *testing.M) { + presets.DoMain(m, presets.WithMinimal()) + +} diff --git a/op-devstack/presets/minimal.go b/op-devstack/presets/minimal.go new file mode 100644 index 0000000000000..d124606dba956 --- /dev/null +++ b/op-devstack/presets/minimal.go @@ -0,0 +1,63 @@ +package presets + +import ( + "github.com/ethereum/go-ethereum/log" + + "github.com/ethereum-optimism/optimism/op-chain-ops/devkeys" + "github.com/ethereum-optimism/optimism/op-devstack/devtest" + "github.com/ethereum-optimism/optimism/op-devstack/dsl" + "github.com/ethereum-optimism/optimism/op-devstack/shim" + "github.com/ethereum-optimism/optimism/op-devstack/stack" + "github.com/ethereum-optimism/optimism/op-devstack/stack/match" + "github.com/ethereum-optimism/optimism/op-devstack/sysgo" +) + +type Minimal struct { + Log log.Logger + T devtest.T + ControlPlane stack.ControlPlane + + L1Network *dsl.L1Network + + L2Chain *dsl.L2Network + L2Batcher *dsl.L2Batcher + L2EL *dsl.L2ELNode + L2CL *dsl.L2CLNode + + Wallet *dsl.HDWallet + + Faucet *dsl.Faucet + Funder *dsl.Funder +} + +func (m *Minimal) L2Networks() []*dsl.L2Network { + return []*dsl.L2Network{ + m.L2Chain, + } +} + +func WithMinimal() stack.CommonOption { + return stack.MakeCommon(sysgo.DefaultMinimalSystem(&sysgo.DefaultMinimalSystemIDs{})) +} + +func NewMinimal(t devtest.T) *Minimal { + system := shim.NewSystem(t) + orch := Orchestrator() + orch.Hydrate(system) + + l2 := system.L2Network(match.Assume(t, match.L2ChainA)) + out := &Minimal{ + Log: t.Logger(), + T: t, + ControlPlane: orch.ControlPlane(), + L1Network: dsl.NewL1Network(system.L1Network(match.FirstL1Network)), + L2Chain: dsl.NewL2Network(l2), + L2Batcher: dsl.NewL2Batcher(l2.L2Batcher(match.Assume(t, match.FirstL2Batcher))), + L2EL: dsl.NewL2ELNode(l2.L2ELNode(match.Assume(t, match.FirstL2EL))), + L2CL: dsl.NewL2CLNode(l2.L2CLNode(match.Assume(t, match.FirstL2CL)), orch.ControlPlane(), l2.ChainID()), + Wallet: dsl.NewHDWallet(t, devkeys.TestMnemonic, 30), + Faucet: dsl.NewFaucet(l2.Faucet(match.Assume(t, match.FirstFaucet))), + } + out.Funder = dsl.NewFunder(out.Wallet, out.Faucet, out.L2EL) + return out +} diff --git a/op-devstack/sysgo/l2_cl.go b/op-devstack/sysgo/l2_cl.go index 23acc8aea4f4f..ed5871f60b421 100644 --- a/op-devstack/sysgo/l2_cl.go +++ b/op-devstack/sysgo/l2_cl.go @@ -71,12 +71,14 @@ func (n *L2CLNode) hydrate(system stack.ExtensibleSystem) { func (n *L2CLNode) rememberPort() { userRPCPort, err := n.opNode.UserRPCPort() n.p.Require().NoError(err) - interopRPCPort, err := n.opNode.InteropRPCPort() - n.p.Require().NoError(err) n.cfg.RPC.ListenPort = userRPCPort + cfg, ok := n.cfg.InteropConfig.(*interop.Config) n.p.Require().True(ok) - cfg.RPCPort = interopRPCPort + + if interopRPCPort, err := n.opNode.InteropRPCPort(); err == nil { + cfg.RPCPort = interopRPCPort + } n.cfg.InteropConfig = cfg } diff --git a/op-devstack/sysgo/system.go b/op-devstack/sysgo/system.go index c6ca56bf4f6d5..b62389acce860 100644 --- a/op-devstack/sysgo/system.go +++ b/op-devstack/sysgo/system.go @@ -6,6 +6,70 @@ import ( "github.com/ethereum-optimism/optimism/op-service/eth" ) +type DefaultMinimalSystemIDs struct { + L1 stack.L1NetworkID + L1EL stack.L1ELNodeID + L1CL stack.L1CLNodeID + + L2 stack.L2NetworkID + L2CL stack.L2CLNodeID + L2EL stack.L2ELNodeID + + L2Batcher stack.L2BatcherID + L2Proposer stack.L2ProposerID +} + +func NewDefaultMinimalSystemIDs(l1ID, l2ID eth.ChainID) DefaultMinimalSystemIDs { + ids := DefaultMinimalSystemIDs{ + L1: stack.L1NetworkID(l1ID), + L1EL: stack.L1ELNodeID{Key: "l1", ChainID: l1ID}, + L1CL: stack.L1CLNodeID{Key: "l1", ChainID: l1ID}, + L2: stack.L2NetworkID(l2ID), + L2CL: stack.L2CLNodeID{Key: "sequencer", ChainID: l2ID}, + L2EL: stack.L2ELNodeID{Key: "sequencer", ChainID: l2ID}, + L2Batcher: stack.L2BatcherID{Key: "main", ChainID: l2ID}, + L2Proposer: stack.L2ProposerID{Key: "main", ChainID: l2ID}, + } + return ids +} + +func DefaultMinimalSystem(dest *DefaultMinimalSystemIDs) stack.Option[*Orchestrator] { + l1ID := eth.ChainIDFromUInt64(900) + l2ID := eth.ChainIDFromUInt64(901) + ids := NewDefaultMinimalSystemIDs(l1ID, l2ID) + + opt := stack.Combine[*Orchestrator]() + opt.Add(stack.BeforeDeploy(func(o *Orchestrator) { + o.P().Logger().Info("Setting up") + })) + + opt.Add(WithMnemonicKeys(devkeys.TestMnemonic)) + + opt.Add(WithDeployer(), + WithDeployerOptions( + WithLocalContractSources(), + WithCommons(ids.L1.ChainID()), + WithPrefundedL2(ids.L2.ChainID()), + ), + ) + + opt.Add(WithL1Nodes(ids.L1EL, ids.L1CL)) + + opt.Add(WithL2ELNode(ids.L2EL, nil)) + opt.Add(WithL2CLNode(ids.L2CL, true, ids.L1CL, ids.L1EL, ids.L2EL)) + + opt.Add(WithBatcher(ids.L2Batcher, ids.L1EL, ids.L2CL, ids.L2EL)) + opt.Add(WithProposer(ids.L2Proposer, ids.L1EL, &ids.L2CL, nil)) + + opt.Add(WithFaucets([]stack.L1ELNodeID{ids.L1EL}, []stack.L2ELNodeID{ids.L2EL})) + + opt.Add(stack.Finally(func(orch *Orchestrator) { + *dest = ids + })) + + return opt +} + // struct of the services, so we can access them later and do not have to guess their IDs. type DefaultInteropSystemIDs struct { L1 stack.L1NetworkID