From bff700de7faa3b3ebaf7a4767ac2f3a501a60081 Mon Sep 17 00:00:00 2001 From: 2020xibao <2020xibao@gmail.com> Date: Fri, 28 Feb 2025 22:25:11 +0800 Subject: [PATCH] fix: make e2e succeed --- op-chain-ops/genesis/config.go | 8 ++++++-- op-e2e/actions/blocktime_test.go | 6 +++--- op-e2e/actions/dencun_fork_test.go | 5 ++++- op-e2e/actions/l2_sequencer_test.go | 4 ++-- op-e2e/actions/user_test.go | 8 ++++++-- op-e2e/e2eutils/setup.go | 5 +++++ op-e2e/op_geth.go | 2 +- op-e2e/op_geth_test.go | 3 +++ op-e2e/setup.go | 4 ++++ op-node/p2p/sync.go | 2 +- op-node/rollup/driver/origin_selector.go | 6 +++++- op-node/rollup/types.go | 12 ++++++------ op-node/rollup/types_test.go | 6 +++--- op-program/client/l2/engineapi/block_processor.go | 2 ++ op-service/sources/l2_client.go | 4 ++-- 15 files changed, 53 insertions(+), 24 deletions(-) diff --git a/op-chain-ops/genesis/config.go b/op-chain-ops/genesis/config.go index e8234d978a..2b614d66be 100644 --- a/op-chain-ops/genesis/config.go +++ b/op-chain-ops/genesis/config.go @@ -60,7 +60,7 @@ type DeployConfig struct { L1ChainID uint64 `json:"l1ChainID"` // L2ChainID is the chain ID of the L2 chain. L2ChainID uint64 `json:"l2ChainID"` - // L2BlockTime is the number of seconds between each L2 block. + // L2BlockTime is the number of seconds between each L2 block. // millisecond L2BlockTime uint64 `json:"l2BlockTime"` // FinalizationPeriodSeconds represents the number of seconds before an output is considered // finalized. This impacts the amount of time that withdrawals take to finalize and is @@ -434,8 +434,12 @@ func (d *DeployConfig) Check() error { return fmt.Errorf("%w: GovernanceToken owner cannot be address(0)", ErrInvalidDeployConfig) } } + if d.L2BlockTime <= 3 { + // convert ms l2 time interval + d.L2BlockTime = d.L2BlockTime * 1000 + } // L2 block time must always be smaller than L1 block time - if d.L1BlockTime < d.L2BlockTime { + if d.L1BlockTime*1000 < d.L2BlockTime { // TODO: tmp adjust, l1 interval is second timstamp and l2 interval is millisecond. return fmt.Errorf("L2 block time (%d) is larger than L1 block time (%d)", d.L2BlockTime, d.L1BlockTime) } if d.RequiredProtocolVersion == (params.ProtocolVersion{}) { diff --git a/op-e2e/actions/blocktime_test.go b/op-e2e/actions/blocktime_test.go index 90a38be9a3..2d75c68732 100644 --- a/op-e2e/actions/blocktime_test.go +++ b/op-e2e/actions/blocktime_test.go @@ -48,9 +48,9 @@ func BatchInLastPossibleBlocks(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp := e2eutils.MakeDeployParams(t, defaultRollupTestParams) applyDeltaTimeOffset(dp, deltaTimeOffset) dp.DeployConfig.SequencerWindowSize = 4 - dp.DeployConfig.L2BlockTime = 2 + dp.DeployConfig.L2BlockTime = 2 // second - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, defaultAlloc) // dp.DeployConfig.L2BlockTime will be changed to 2000 log := testlog.Logger(t, log.LevelDebug) sd, _, miner, sequencer, sequencerEngine, _, _, batcher := setupReorgTestActors(t, dp, sd, log) @@ -162,7 +162,7 @@ func LargeL1Gaps(gt *testing.T, deltaTimeOffset *hexutil.Uint64) { dp.DeployConfig.SequencerWindowSize = 4 dp.DeployConfig.MaxSequencerDrift = 32 applyDeltaTimeOffset(dp, deltaTimeOffset) - sd := e2eutils.Setup(t, dp, defaultAlloc) + sd := e2eutils.Setup(t, dp, defaultAlloc) // dp.DeployConfig.L2BlockTime = 2000 log := testlog.Logger(t, log.LevelDebug) sd, _, miner, sequencer, sequencerEngine, verifier, _, batcher := setupReorgTestActors(t, dp, sd, log) diff --git a/op-e2e/actions/dencun_fork_test.go b/op-e2e/actions/dencun_fork_test.go index 5e0f1706cb..6a607ecc7f 100644 --- a/op-e2e/actions/dencun_fork_test.go +++ b/op-e2e/actions/dencun_fork_test.go @@ -124,7 +124,10 @@ func TestDencunL2ForkAfterGenesis(gt *testing.T) { cancunOffset := hexutil.Uint64(0) dp.DeployConfig.L1CancunTimeOffset = &cancunOffset // This test wil fork on the second block - offset := hexutil.Uint64(dp.DeployConfig.L2BlockTime * 2) + if dp.DeployConfig.L2BlockTime <= 3 { + dp.DeployConfig.L2BlockTime = dp.DeployConfig.L2BlockTime * 1000 // millisecond + } + offset := hexutil.Uint64(dp.DeployConfig.L2BlockTime / 1000 * 2) // second dp.DeployConfig.L2GenesisCanyonTimeOffset = &offset dp.DeployConfig.L2GenesisDeltaTimeOffset = &offset dp.DeployConfig.L2GenesisEcotoneTimeOffset = &offset diff --git a/op-e2e/actions/l2_sequencer_test.go b/op-e2e/actions/l2_sequencer_test.go index 05fa0242d1..745a27855e 100644 --- a/op-e2e/actions/l2_sequencer_test.go +++ b/op-e2e/actions/l2_sequencer_test.go @@ -98,7 +98,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { origin := miner.l1Chain.CurrentBlock() // L2 makes blocks to catch up - for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime < origin.Time { + for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime/1000 < origin.Time { makeL2BlockWithAliceTx() require.Equal(t, uint64(0), sequencer.SyncStatus().UnsafeL2.L1Origin.Number, "no L1 origin change before time matches") } @@ -111,7 +111,7 @@ func TestL2Sequencer_SequencerDrift(gt *testing.T) { sequencer.ActL1HeadSignal(t) // Make blocks up till the sequencer drift is about to surpass, but keep the old L1 origin - for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime <= origin.Time+sd.ChainSpec.MaxSequencerDrift(origin.Time) { + for sequencer.SyncStatus().UnsafeL2.Time+sd.RollupCfg.BlockTime/1000 <= origin.Time+sd.ChainSpec.MaxSequencerDrift(origin.Time) { sequencer.ActL2KeepL1Origin(t) makeL2BlockWithAliceTx() require.Equal(t, uint64(1), sequencer.SyncStatus().UnsafeL2.L1Origin.Number, "expected to keep old L1 origin") diff --git a/op-e2e/actions/user_test.go b/op-e2e/actions/user_test.go index c9692c91f0..4f28c9f7fa 100644 --- a/op-e2e/actions/user_test.go +++ b/op-e2e/actions/user_test.go @@ -118,11 +118,15 @@ func runCrossLayerUserTest(gt *testing.T, test hardforkScheduledTest) { dp.DeployConfig.L2GenesisEcotoneTimeOffset = test.ecotoneTime dp.DeployConfig.L2GenesisFjordTimeOffset = test.fjordTime + if dp.DeployConfig.L2BlockTime <= 3 { + dp.DeployConfig.L2BlockTime = dp.DeployConfig.L2BlockTime * 1000 + } + if test.canyonTime != nil { - require.Zero(t, uint64(*test.canyonTime)%uint64(dp.DeployConfig.L2BlockTime), "canyon fork must be aligned") + require.Zero(t, uint64(*test.canyonTime)%uint64(dp.DeployConfig.L2BlockTime/1000), "canyon fork must be aligned") } if test.ecotoneTime != nil { - require.Zero(t, uint64(*test.ecotoneTime)%uint64(dp.DeployConfig.L2BlockTime), "ecotone fork must be aligned") + require.Zero(t, uint64(*test.ecotoneTime)%uint64(dp.DeployConfig.L2BlockTime/1000), "ecotone fork must be aligned") } sd := e2eutils.Setup(t, dp, defaultAlloc) diff --git a/op-e2e/e2eutils/setup.go b/op-e2e/e2eutils/setup.go index a86f28c5da..7f42ed56de 100644 --- a/op-e2e/e2eutils/setup.go +++ b/op-e2e/e2eutils/setup.go @@ -187,6 +187,11 @@ func Setup(t require.TestingT, deployParams *DeployParams, alloc *AllocParams) * PlasmaConfig: pcfg, } + if rollupCfg.BlockTime <= 3 { + // covert to ms timestamp + rollupCfg.BlockTime = rollupCfg.BlockTime * 1000 + } + require.NoError(t, rollupCfg.Check()) // Sanity check that the config is correct diff --git a/op-e2e/op_geth.go b/op-e2e/op_geth.go index 7cea17d43a..1422a23a55 100644 --- a/op-e2e/op_geth.go +++ b/op-e2e/op_geth.go @@ -212,7 +212,7 @@ func (d *OpGeth) StartBlockBuilding(ctx context.Context, attrs *eth.PayloadAttri // CreatePayloadAttributes creates a valid PayloadAttributes containing a L1Info deposit transaction followed by the supplied transactions. func (d *OpGeth) CreatePayloadAttributes(txs ...*types.Transaction) (*eth.PayloadAttributes, error) { timestamp := d.L2Head.Timestamp + 2 - l1Info, err := derive.L1InfoDepositBytes(d.l2Engine.RollupConfig(), d.SystemConfig, d.sequenceNum, d.L1Head, uint64(timestamp)) + l1Info, err := derive.L1InfoDepositBytes(d.l2Engine.RollupConfig(), d.SystemConfig, d.sequenceNum, d.L1Head, uint64(timestamp*1000) /*ms*/) if err != nil { return nil, err } diff --git a/op-e2e/op_geth_test.go b/op-e2e/op_geth_test.go index 90b117084c..a65bfe333c 100644 --- a/op-e2e/op_geth_test.go +++ b/op-e2e/op_geth_test.go @@ -435,6 +435,9 @@ func TestRegolith(t *testing.T) { // We also need to setup a L1 Genesis to create the rollup genesis. cfg := DefaultSystemConfig(t) cfg.DeployConfig.L2GenesisRegolithTimeOffset = &test.regolithTime + if cfg.DeployConfig.L2BlockTime <= 3 { + cfg.DeployConfig.L2BlockTime = cfg.DeployConfig.L2BlockTime * 1000 // ms + } ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second) defer cancel() diff --git a/op-e2e/setup.go b/op-e2e/setup.go index b0c969639a..acbb423df6 100644 --- a/op-e2e/setup.go +++ b/op-e2e/setup.go @@ -547,6 +547,10 @@ func (cfg SystemConfig) Start(t *testing.T, _opts ...SystemConfigOption) (*Syste return nil, err } sys.RollupConfig = &defaultConfig + if sys.RollupConfig.BlockTime <= 3 { + // covert ms timestamp + sys.RollupConfig.BlockTime = sys.RollupConfig.BlockTime * 1000 + } // Create a fake Beacon node to hold on to blobs created by the L1 miner, and to serve them to L2 bcn := fakebeacon.NewBeacon(testlog.Logger(t, log.LevelInfo).New("role", "l1_cl"), diff --git a/op-node/p2p/sync.go b/op-node/p2p/sync.go index c46eb6b365..3872526be0 100644 --- a/op-node/p2p/sync.go +++ b/op-node/p2p/sync.go @@ -878,7 +878,7 @@ func (srv *ReqRespServer) handleSyncRequest(ctx context.Context, stream network. if req < srv.cfg.Genesis.L2.Number { return req, fmt.Errorf("cannot serve request for L2 block %d before genesis %d: %w", req, srv.cfg.Genesis.L2.Number, invalidRequestErr) } - max, err := srv.cfg.TargetBlockNumber(uint64(time.Now().Unix())) + max, err := srv.cfg.TargetBlockNumber(uint64(time.Now().UnixMilli())) if err != nil { return req, fmt.Errorf("cannot determine max target block number to verify request: %w", invalidRequestErr) } diff --git a/op-node/rollup/driver/origin_selector.go b/op-node/rollup/driver/origin_selector.go index cc22135e35..5539d77f7d 100644 --- a/op-node/rollup/driver/origin_selector.go +++ b/op-node/rollup/driver/origin_selector.go @@ -57,7 +57,11 @@ func (los *L1OriginSelector) FindL1Origin(ctx context.Context, l2Head eth.L2Bloc refCtx, refCancel := context.WithTimeout(ctx, 100*time.Millisecond) defer refCancel() if pastSeqDrift { - log.Warn("Next L2 block time is past the sequencer drift + current origin time") + log.Warn("Next L2 block time is past the sequencer drift + current origin time", + "l2_head_ms_timestamp", l2Head.MillisecondTimestamp(), + "l2_block_ms_interval", los.cfg.BlockTime, + "l1_origin_ms_timestamp", currentOrigin.MilliTimestamp(), + "max_ms_drift", msd) // Must fetch next L1 block as long as it may take, cause we are pastSeqDrift refCtx = ctx } diff --git a/op-node/rollup/types.go b/op-node/rollup/types.go index 1c38fdf570..839d111aa0 100644 --- a/op-node/rollup/types.go +++ b/op-node/rollup/types.go @@ -193,18 +193,18 @@ func (cfg *Config) ValidateL2Config(ctx context.Context, client L2Client, skipL2 } func (cfg *Config) TimestampForBlock(blockNumber uint64) uint64 { - return cfg.Genesis.L2Time + ((blockNumber - cfg.Genesis.L2.Number) * cfg.BlockTime) + return cfg.Genesis.L2Time + ((blockNumber - cfg.Genesis.L2.Number) * cfg.BlockTime / 1000) } -func (cfg *Config) TargetBlockNumber(timestamp uint64) (num uint64, err error) { +func (cfg *Config) TargetBlockNumber(milliTimestamp uint64) (num uint64, err error) { // subtract genesis time from timestamp to get the time elapsed since genesis, and then divide that // difference by the block time to get the expected L2 block number at the current time. If the // unsafe head does not have this block number, then there is a gap in the queue. - genesisTimestamp := cfg.Genesis.L2Time - if timestamp < genesisTimestamp { - return 0, fmt.Errorf("did not reach genesis time (%d) yet", genesisTimestamp) + genesisMilliTimestamp := cfg.Genesis.L2Time * 1000 + if milliTimestamp < genesisMilliTimestamp { + return 0, fmt.Errorf("did not reach genesis time (%d) yet", genesisMilliTimestamp) } - wallClockGenesisDiff := timestamp - genesisTimestamp + wallClockGenesisDiff := milliTimestamp - genesisMilliTimestamp // Note: round down, we should not request blocks into the future. blocksSinceGenesis := wallClockGenesisDiff / cfg.BlockTime return cfg.Genesis.L2.Number + blocksSinceGenesis, nil diff --git a/op-node/rollup/types_test.go b/op-node/rollup/types_test.go index 248fe3eaad..d427104a58 100644 --- a/op-node/rollup/types_test.go +++ b/op-node/rollup/types_test.go @@ -534,7 +534,7 @@ func TestTimestampForBlock(t *testing.T) { name: "FirstBlock", genesisTime: 100, genesisBlock: 0, - blockTime: 2, + blockTime: 2000, blockNum: 0, expectedBlockTime: 100, }, @@ -542,7 +542,7 @@ func TestTimestampForBlock(t *testing.T) { name: "SecondBlock", genesisTime: 100, genesisBlock: 0, - blockTime: 2, + blockTime: 2000, blockNum: 1, expectedBlockTime: 102, }, @@ -550,7 +550,7 @@ func TestTimestampForBlock(t *testing.T) { name: "NBlock", genesisTime: 100, genesisBlock: 0, - blockTime: 2, + blockTime: 2000, blockNum: 25, expectedBlockTime: 150, }, diff --git a/op-program/client/l2/engineapi/block_processor.go b/op-program/client/l2/engineapi/block_processor.go index d81212db20..b8850f86e2 100644 --- a/op-program/client/l2/engineapi/block_processor.go +++ b/op-program/client/l2/engineapi/block_processor.go @@ -13,6 +13,7 @@ import ( "github.com/ethereum/go-ethereum/core/state" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/params" ) @@ -70,6 +71,7 @@ func NewBlockProcessorFromHeader(provider BlockDataProvider, h *types.Header) (* } parentHeader := provider.GetHeaderByHash(header.ParentHash) if header.Time <= parentHeader.Time { + log.Error("invalid timestamp", "header", header, "parent_header", parentHeader) return nil, errors.New("invalid timestamp") } statedb, err := provider.StateAt(parentHeader.Root) diff --git a/op-service/sources/l2_client.go b/op-service/sources/l2_client.go index 812ddcab7c..7c60087464 100644 --- a/op-service/sources/l2_client.go +++ b/op-service/sources/l2_client.go @@ -32,9 +32,9 @@ func L2ClientDefaultConfig(config *rollup.Config, trustRPC bool) *L2ClientConfig span := int(config.SeqWindowSize) * 3 / 2 // Estimate number of L2 blocks in this span of L1 blocks // (there's always one L2 block per L1 block, L1 is thus the minimum, even if block time is very high) - if config.BlockTime < 12 && config.BlockTime > 0 { + if config.BlockTime/1000 < 12 && config.BlockTime/1000 > 0 { span *= 12 - span /= int(config.BlockTime) + span /= int(config.BlockTime / 1000) } fullSpan := span if span > 1000 { // sanity cap. If a large sequencing window is configured, do not make the cache too large