diff --git a/optimism/devnet.go b/optimism/devnet.go index cae2de04eb..0af6cc927f 100644 --- a/optimism/devnet.go +++ b/optimism/devnet.go @@ -231,7 +231,7 @@ func (d *Devnet) AddOpProposer(eth1Index int, l2EngIndex int, opNodeIndex int, o oppf.ResubmissionTimeoutFlag.EnvVar: "30s", oppf.MnemonicFlag.EnvVar: d.MnemonicCfg.Mnemonic, oppf.L2OutputHDPathFlag.EnvVar: d.MnemonicCfg.Proposer, - oppf.LogLevelFlag.EnvVar: "debug", + "OP_PROPOSER_LOG_LEVEL": "debug", } input := []hivesim.StartOption{defaultSettings.Params()} input = append(input, opts...) @@ -272,7 +272,7 @@ func (d *Devnet) AddOpBatcher(eth1Index int, l2EngIndex int, opNodeIndex int, op opbf.MnemonicFlag.EnvVar: d.MnemonicCfg.Mnemonic, opbf.SequencerHDPathFlag.EnvVar: d.MnemonicCfg.Batcher, opbf.SequencerBatchInboxAddressFlag.EnvVar: d.RollupCfg.BatchInboxAddress.String(), - opbf.LogLevelFlag.EnvVar: "debug", + "OP_BATCHER_LOG_LEVEL": "debug", } input := []hivesim.StartOption{defaultSettings.Params()} input = append(input, opts...) diff --git a/optimism/hardhat.go b/optimism/hardhat.go index 24de648da9..99da43b7aa 100644 --- a/optimism/hardhat.go +++ b/optimism/hardhat.go @@ -88,7 +88,7 @@ func (d *Devnet) RunScript(name string, command ...string) *hivesim.ExecInfo { return execInfo } -func (d *Devnet) InitHardhatDeployConfig() { +func (d *Devnet) InitHardhatDeployConfig(maxSeqDrift uint64, seqWindowSize uint64, chanTimeout uint64) { d.mu.Lock() defer d.mu.Unlock() d.T.Log("creating hardhat deploy config") @@ -98,9 +98,9 @@ func (d *Devnet) InitHardhatDeployConfig() { L2ChainID: 902, L2BlockTime: 2, - MaxSequencerDrift: 100, - SequencerWindowSize: 4, - ChannelTimeout: 40, + MaxSequencerDrift: maxSeqDrift, + SequencerWindowSize: seqWindowSize, + ChannelTimeout: chanTimeout, P2pSequencerAddress: d.Addresses.SequencerP2P, OptimismL2FeeRecipient: common.Address{0: 0x42, 19: 0xf0}, // tbd BatchInboxAddress: common.Address{0: 0x42, 19: 0xff}, // tbd diff --git a/simulators/optimism/p2p/main.go b/simulators/optimism/p2p/main.go index 8479bba937..2c76b90089 100644 --- a/simulators/optimism/p2p/main.go +++ b/simulators/optimism/p2p/main.go @@ -2,10 +2,13 @@ package main import ( "context" + "math/big" + "time" + + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" - "github.com/stretchr/testify/assert" - "time" + "github.com/stretchr/testify/require" "github.com/ethereum/hive/hivesim" "github.com/ethereum/hive/optimism" @@ -33,7 +36,7 @@ func runP2PTests(t *hivesim.T) { d := optimism.NewDevnet(t) d.InitContracts() - d.InitHardhatDeployConfig() + d.InitHardhatDeployConfig(10, 4, 30) d.InitL1Hardhat() d.AddEth1() // l1 eth1 node is required for l2 config init d.WaitUpEth1(0, time.Second*10) @@ -62,40 +65,60 @@ func runP2PTests(t *hivesim.T) { d.AddOpNode(0, 2) t.Log("waiting for nodes to get onto the network") - time.Sleep(time.Second * 10) seq := d.GetOpNode(0) verifA := d.GetOpNode(1) verifB := d.GetOpNode(2) + seqEng := d.GetOpL2Engine(0) + seqEthCl := seqEng.EthClient() + seqCl := seq.RollupClient() verifACl := verifA.RollupClient() verifBCl := verifB.RollupClient() ctx, cancel := context.WithCancel(context.Background()) - go func() { - ticker := time.NewTicker(time.Second * 4) - defer ticker.Stop() - syncStat := func(name string, cl *rollupclient.RollupClient) *driver.SyncStatus { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) - seqStat, err := cl.SyncStatus(ctx) - cancel() - if err != nil { - t.Error("failed to get sync status from %s op-node: %v", name, err) - } - return seqStat // may be nil + checkCanon := func(name string, id eth.BlockID) { + bl, err := seqEthCl.BlockByNumber(ctx, big.NewInt(int64(id.Number))) + if err != nil { + t.Fatalf("%s: sequencer does not have block at height %d", name, id.Number) } + if h := bl.Hash(); h != id.Hash { + t.Fatalf("%s: sequencer diverged, height %d does not match: sequencer: %s <> verifier: %s", name, h, id.Hash) + } + } + + syncStat := func(name string, cl *rollupclient.RollupClient) *driver.SyncStatus { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) + seqStat, err := cl.SyncStatus(ctx) + cancel() + if err != nil { + t.Errorf("failed to get sync status from %s op-node: %v", name, err) + } + t.Log(name, + "currentL1", seqStat.CurrentL1.TerminalString(), + "headL1", seqStat.HeadL1.TerminalString(), + "finalizedL2", seqStat.FinalizedL2.TerminalString(), + "safeL2", seqStat.SafeL2.TerminalString(), + "unsafeL2", seqStat.UnsafeL2.TerminalString()) + return seqStat // may be nil + } + go func() { + ticker := time.NewTicker(time.Second * 4) + defer ticker.Stop() for { select { case <-ticker.C: // Check that all clients are synced - seqStat := syncStat("sequencer", seqCl) + seqStat := syncStat("sequencer ", seqCl) verAStat := syncStat("verifier-A", verifACl) verBStat := syncStat("verifier-B", verifBCl) - assert.Equal(t, seqStat, verAStat, "sequencer and verifier A should be synced") - assert.Equal(t, verAStat, verBStat, "verifier A and verifier B should be synced") + checkCanon("verifier A", verAStat.UnsafeL2.ID()) + checkCanon("verifier B", verBStat.UnsafeL2.ID()) + require.LessOrEqual(t, seqStat.CurrentL1.Number, verAStat.CurrentL1.Number+d.RollupCfg.SeqWindowSize, "verifier A is not behind sequencer by more than the sequence window") + require.LessOrEqual(t, seqStat.CurrentL1.Number, verBStat.CurrentL1.Number+d.RollupCfg.SeqWindowSize, "verifier B is not behind sequencer by more than the sequence window") case <-ctx.Done(): t.Log("exiting sync checking loop") return diff --git a/simulators/optimism/rpc/main.go b/simulators/optimism/rpc/main.go index ccb5644cd3..6562eecef6 100644 --- a/simulators/optimism/rpc/main.go +++ b/simulators/optimism/rpc/main.go @@ -97,7 +97,7 @@ func runAllTests(t *hivesim.T) { d := optimism.NewDevnet(t) d.InitContracts() - d.InitHardhatDeployConfig() + d.InitHardhatDeployConfig(10, 4, 30) d.InitL1Hardhat() d.AddEth1() // l1 eth1 node is required for l2 config init d.WaitUpEth1(0, time.Second*10) diff --git a/simulators/optimism/testnet/main.go b/simulators/optimism/testnet/main.go index 154ee10f92..19ef07a723 100644 --- a/simulators/optimism/testnet/main.go +++ b/simulators/optimism/testnet/main.go @@ -2,10 +2,13 @@ package main import ( "context" + "math/big" + "time" + + "github.com/ethereum-optimism/optimism/op-node/eth" "github.com/ethereum-optimism/optimism/op-node/rollup/driver" "github.com/ethereum-optimism/optimism/op-proposer/rollupclient" - "github.com/stretchr/testify/assert" - "time" + "github.com/stretchr/testify/require" "github.com/ethereum/hive/hivesim" "github.com/ethereum/hive/optimism" @@ -35,7 +38,7 @@ func runTestnet(t *hivesim.T) { d := optimism.NewDevnet(t) d.InitContracts() - d.InitHardhatDeployConfig() + d.InitHardhatDeployConfig(10, 4, 30) d.InitL1Hardhat() d.AddEth1() // l1 eth1 node is required for l2 config init d.WaitUpEth1(0, time.Second*10) @@ -64,40 +67,60 @@ func runTestnet(t *hivesim.T) { d.AddOpNode(0, 2) t.Log("waiting for nodes to get onto the network") - time.Sleep(time.Second * 10) seq := d.GetOpNode(0) verifA := d.GetOpNode(1) verifB := d.GetOpNode(2) + seqEng := d.GetOpL2Engine(0) + seqEthCl := seqEng.EthClient() + seqCl := seq.RollupClient() verifACl := verifA.RollupClient() verifBCl := verifB.RollupClient() ctx, cancel := context.WithCancel(context.Background()) - go func() { - ticker := time.NewTicker(time.Second * 4) - defer ticker.Stop() - syncStat := func(name string, cl *rollupclient.RollupClient) *driver.SyncStatus { - ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) - seqStat, err := cl.SyncStatus(ctx) - cancel() - if err != nil { - t.Error("failed to get sync status from %s op-node: %v", name, err) - } - return seqStat // may be nil + checkCanon := func(name string, id eth.BlockID) { + bl, err := seqEthCl.BlockByNumber(ctx, big.NewInt(int64(id.Number))) + if err != nil { + t.Fatalf("%s: sequencer does not have block at height %d", name, id.Number) + } + if h := bl.Hash(); h != id.Hash { + t.Fatalf("%s: sequencer diverged, height %d does not match: sequencer: %s <> verifier: %s", name, h, id.Hash) } + } + + syncStat := func(name string, cl *rollupclient.RollupClient) *driver.SyncStatus { + ctx, cancel := context.WithTimeout(context.Background(), time.Second*4) + seqStat, err := cl.SyncStatus(ctx) + cancel() + if err != nil { + t.Errorf("failed to get sync status from %s op-node: %v", name, err) + } + t.Log(name, + "currentL1", seqStat.CurrentL1.TerminalString(), + "headL1", seqStat.HeadL1.TerminalString(), + "finalizedL2", seqStat.FinalizedL2.TerminalString(), + "safeL2", seqStat.SafeL2.TerminalString(), + "unsafeL2", seqStat.UnsafeL2.TerminalString()) + return seqStat // may be nil + } + go func() { + ticker := time.NewTicker(time.Second * 4) + defer ticker.Stop() for { select { case <-ticker.C: // Check that all clients are synced - seqStat := syncStat("sequencer", seqCl) + seqStat := syncStat("sequencer ", seqCl) verAStat := syncStat("verifier-A", verifACl) verBStat := syncStat("verifier-B", verifBCl) - assert.Equal(t, seqStat, verAStat, "sequencer and verifier A should be synced") - assert.Equal(t, verAStat, verBStat, "verifier A and verifier B should be synced") + checkCanon("verifier A", verAStat.UnsafeL2.ID()) + checkCanon("verifier B", verBStat.UnsafeL2.ID()) + require.LessOrEqual(t, seqStat.CurrentL1.Number, verAStat.CurrentL1.Number+d.RollupCfg.SeqWindowSize, "verifier A is not behind sequencer by more than the sequence window") + require.LessOrEqual(t, seqStat.CurrentL1.Number, verBStat.CurrentL1.Number+d.RollupCfg.SeqWindowSize, "verifier B is not behind sequencer by more than the sequence window") case <-ctx.Done(): t.Log("exiting sync checking loop") return @@ -108,6 +131,4 @@ func runTestnet(t *hivesim.T) { // Run testnet for duration of 3 sequence windows time.Sleep(time.Second * time.Duration(d.L1Cfg.Config.Clique.Period*d.RollupCfg.SeqWindowSize*3)) cancel() - - // TODO: Add P2P tests }