From 83541dd71eb9328db0d5477578276b6639c80f39 Mon Sep 17 00:00:00 2001 From: "allen.wu" Date: Wed, 4 Feb 2026 11:32:15 +0800 Subject: [PATCH] feature: support sequencer rotate --- node/node.go | 47 +++++------------ sequencer/broadcast_reactor.go | 93 ++++++++++++++++++++-------------- sequencer/interfaces.go | 22 ++++++++ sequencer/state_v2.go | 83 +++++++++++++++--------------- sequencer/state_v2_test.go | 79 +++++++++++++++++++---------- upgrade/upgrade.go | 24 --------- 6 files changed, 183 insertions(+), 165 deletions(-) create mode 100644 sequencer/interfaces.go diff --git a/node/node.go b/node/node.go index 6ead8ec33b9..8daca33aa92 100644 --- a/node/node.go +++ b/node/node.go @@ -3,20 +3,15 @@ package node import ( "bytes" "context" - "crypto/ecdsa" - "encoding/hex" "errors" "fmt" "net" "net/http" - "os" "strings" "time" "github.com/tendermint/tendermint/upgrade" - ethcrypto "github.com/morph-l2/go-ethereum/crypto" - "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/promhttp" "github.com/rs/cors" @@ -128,6 +123,8 @@ func DefaultNewNode(config *cfg.Config, logger log.Logger) (*Node, error) { DefaultDBProvider, DefaultMetricsProvider(config.Instrumentation), logger, + nil, + nil, ) } @@ -253,7 +250,6 @@ type Node struct { // Sequencer mode (after upgrade) stateV2 *sequencer.StateV2 blockBroadcastReactor *sequencer.BlockBroadcastReactor - sequencerPrivKey *ecdsa.PrivateKey // ECDSA key for signing blocks in sequencer mode } func initDBs(config *cfg.Config, dbProvider DBProvider) (blockStore *store.BlockStore, stateDB dbm.DB, err error) { @@ -508,17 +504,19 @@ func createConsensusReactor( // These components are created but not started - they will be started when switching to sequencer mode. func createSequencerComponents( l2Node l2node.L2Node, - sequencerPrivKey *ecdsa.PrivateKey, pool *bc.BlockPool, waitSync bool, logger log.Logger, + verifier sequencer.SequencerVerifier, + signer sequencer.Signer, ) (*sequencer.StateV2, *sequencer.BlockBroadcastReactor, error) { // Create StateV2 stateV2, err := sequencer.NewStateV2( l2Node, - sequencerPrivKey, sequencer.DefaultBlockInterval, logger, + verifier, + signer, ) if err != nil { return nil, nil, fmt.Errorf("failed to create StateV2: %w", err) @@ -530,6 +528,7 @@ func createSequencerComponents( stateV2, waitSync, logger, + verifier, ) broadcastReactor.SetLogger(logger.With("module", "sequencer")) @@ -784,6 +783,8 @@ func NewNode( dbProvider DBProvider, metricsProvider MetricsProvider, logger log.Logger, + sequencerVerifier sequencer.SequencerVerifier, + sequencerSigner sequencer.Signer, options ...Option, ) ( *Node, error, @@ -1007,17 +1008,15 @@ func NewNode( if bcR, ok := bcReactor.(*bc.Reactor); ok { l2NodeRef := bcR.L2Node() - // TODO: just for Phase1, will update in future - if err := node.SetSequencerPrivKey(); err != nil { - return nil, err - } // Create sequencer components if node.stateV2, node.blockBroadcastReactor, err = createSequencerComponents( l2NodeRef, - node.sequencerPrivKey, bcR.Pool(), blockSync || stateSync, - logger); err != nil { + logger, + sequencerVerifier, + sequencerSigner, + ); err != nil { return nil, err } @@ -1597,26 +1596,6 @@ func splitAndTrimEmpty(s, sep, cutset string) []string { // Sequencer Mode Methods // ============================================================================ -// TODO: optimize SetSequencerPrivKey in the future -// SetSequencerPrivKey sets the ECDSA private key for signing blocks in sequencer mode. -func (n *Node) SetSequencerPrivKey() error { - // Load sequencer private key from environment variable - if seqKeyHex := os.Getenv("SEQUENCER_PRIVATE_KEY"); seqKeyHex != "" { - seqKeyHex = strings.TrimPrefix(seqKeyHex, "0x") - keyBytes, err := hex.DecodeString(seqKeyHex) - if err != nil { - return fmt.Errorf("failed to decode SEQUENCER_PRIVATE_KEY: %w", err) - } - n.sequencerPrivKey, err = ethcrypto.ToECDSA(keyBytes) - if err != nil { - return fmt.Errorf("failed to parse SEQUENCER_PRIVATE_KEY: %w", err) - } - n.Logger.Info("Loaded sequencer private key", - "address", ethcrypto.PubkeyToAddress(n.sequencerPrivKey.PublicKey).Hex()) - } - return nil -} - // startSequencerMode starts the sequencer mode components with logging. // This is an internal method used by upgrade callbacks and startup logic. func (n *Node) startSequencerMode() { diff --git a/sequencer/broadcast_reactor.go b/sequencer/broadcast_reactor.go index 6b58db9622a..857dad07a6f 100644 --- a/sequencer/broadcast_reactor.go +++ b/sequencer/broadcast_reactor.go @@ -1,6 +1,7 @@ package sequencer import ( + "context" "fmt" "math/big" "math/rand" @@ -8,8 +9,6 @@ import ( "sync" "time" - "github.com/tendermint/tendermint/upgrade" - "github.com/cosmos/gogoproto/proto" "github.com/morph-l2/go-ethereum/common" "github.com/morph-l2/go-ethereum/crypto" @@ -26,11 +25,12 @@ const ( SequencerSyncChannel = byte(0x51) // For block sync requests (no signature verification) // TODO: make these parameters configurable - smallGapThreshold = 5 // Gap for direct block request + smallGapThreshold = 20 // Gap for direct block request recentBlocksCapacity = 1000 // Recent applied blocks cache seenBlocksCapacity = 2000 // Seen blocks for dedup peerSentCapacity = 500 // Per-peer sent tracking - applyInterval = 500 * time.Millisecond + applyInterval = 10 * time.Second + syncInterval = 10 * time.Second ) // BlockPool interface (avoids import cycle) @@ -58,10 +58,18 @@ type BlockBroadcastReactor struct { applyMtx sync.Mutex // Protects applyBlock to ensure sequential block application sequencerStarted bool // True when sequencer mode is actually running (not just registered) logger log.Logger + + verifier SequencerVerifier } // NewBlockBroadcastReactor creates a new reactor. -func NewBlockBroadcastReactor(pool BlockPool, stateV2 *StateV2, waitSync bool, logger log.Logger) *BlockBroadcastReactor { +func NewBlockBroadcastReactor( + pool BlockPool, + stateV2 *StateV2, + waitSync bool, + logger log.Logger, + verifier SequencerVerifier, +) *BlockBroadcastReactor { r := &BlockBroadcastReactor{ pool: pool, stateV2: stateV2, @@ -71,6 +79,7 @@ func NewBlockBroadcastReactor(pool BlockPool, stateV2 *StateV2, waitSync bool, l seenBlocks: NewHashSet(seenBlocksCapacity), peerSent: NewPeerHashSet(peerSentCapacity), logger: logger.With("module", "broadcastReactor"), + verifier: verifier, } r.BaseReactor = *p2p.NewBaseReactor("BlockBroadcast", r) return r @@ -104,7 +113,7 @@ func (r *BlockBroadcastReactor) StartSequencerRoutines() error { } } - if upgrade.IsSequencer(r.stateV2.seqAddr) { + if r.stateV2.IsSequencerMode() { go r.broadcastRoutine() } else { go r.applyRoutine() @@ -118,12 +127,6 @@ func (r *BlockBroadcastReactor) OnStop() { r.logger.Info("Stopping BlockBroadcastReactor") } -// func (r *BlockBroadcastReactor) SwitchToSequencer() error { -// r.logger.Info("Sync mode switching to sequencer mode") -// r.waitSync = false -// return r.StartSequencerRoutines() -// } - func (r *BlockBroadcastReactor) GetChannels() []*p2p.ChannelDescriptor { return []*p2p.ChannelDescriptor{ {ID: BlockBroadcastChannel, Priority: 6, SendQueueCapacity: 1000, RecvBufferCapacity: 50 * 4096}, @@ -220,15 +223,18 @@ func (r *BlockBroadcastReactor) broadcastRoutine() { // applyRoutine: periodically try to apply blocks from unlink cache func (r *BlockBroadcastReactor) applyRoutine() { r.logger.Info("Starting block apply routine") - ticker := time.NewTicker(applyInterval) - defer ticker.Stop() + tickerApply := time.NewTicker(applyInterval) + tickerSync := time.NewTicker(syncInterval) + defer tickerSync.Stop() + defer tickerApply.Stop() for { select { case <-r.Quit(): return - case <-ticker.C: + case <-tickerApply.C: r.tryApplyFromCache() + case <-tickerSync.C: r.checkSyncGap() } } @@ -242,9 +248,10 @@ func (r *BlockBroadcastReactor) applyRoutine() { // verifySig: true for broadcast channel, false for sync channel func (r *BlockBroadcastReactor) onBlockV2(block *BlockV2, src p2p.Peer, verifySig bool) { r.logger.Debug("onBlockV2", "number", block.Number, "hash", block.Hash.Hex(), "verifySig", verifySig) - // Dedup: skip if already seen - if r.markSeen(block.Hash) { - r.logger.Debug("onBlockV2 dedup", "number", block.Number, "hash", block.Hash.Hex(), "verifySig", verifySig) + // Dedup: skip if already seen, only for broadcast channel. + // Sync channel should not check dedup. + if r.markSeen(block.Hash) && verifySig { + r.logger.Debug("onBlockV2 broadcast dedup", "number", block.Number, "hash", block.Hash.Hex(), "verifySig", verifySig) return } @@ -256,18 +263,22 @@ func (r *BlockBroadcastReactor) onBlockV2(block *BlockV2, src p2p.Peer, verifySi // Try apply if it's the next block (height + parent match) if r.isNextBlock(block) { if err := r.applyBlock(block, verifySig); err != nil { - r.logger.Error("Apply failed, caching", "number", block.Number, "err", err) - r.pendingCache.Add(block, uint64(localHeight)) + r.logger.Error("Apply failed", "number", block.Number, "hash", block.Hash.Hex(), "err", err) + if verifySig { + r.logger.Debug("Apply failed, caching block", "number", block.Number, "hash", block.Hash.Hex()) + r.pendingCache.Add(block, uint64(localHeight)) + } + return } - } else { + // Gossip the latest block to other peers + if verifySig { + r.gossipBlock(block, src.ID()) + } + } else if verifySig { // Cache all other blocks (future or past for potential reorg) + r.logger.Debug("future block, caching", "number", block.Number, "hash", block.Hash.Hex()) r.pendingCache.Add(block, uint64(localHeight)) } - - // Gossip the latest block to other peers - if verifySig { - r.gossipBlock(block, src.ID()) - } } // tryApplyFromCache: apply blocks from unlink cache (called by applyRoutine) @@ -290,7 +301,7 @@ func (r *BlockBroadcastReactor) tryApplyFromCache() { break } r.logger.Debug("Trying to apply from cache", "number", block.Number, "hash", block.Hash.Hex()) - if err := r.applyBlock(block, false); err != nil { // no signature verification + if err := r.applyBlock(block, true); err != nil { // should signature verification r.logger.Error("Apply from cache failed", "number", block.Number, "err", err) break } @@ -310,16 +321,12 @@ func (r *BlockBroadcastReactor) checkSyncGap() { maxPeerHeight := r.pool.MaxPeerHeight() gap := maxPeerHeight - localHeight r.logger.Debug("Checking sync goroutines", "gap", gap, "localHeight", localHeight, "maxPeerHeight", maxPeerHeight) - if gap <= 0 { + if gap <= smallGapThreshold { return } // Request missing blocks (limited to smallGapThreshold per cycle to avoid spam) - end := localHeight + int64(smallGapThreshold) - if end > maxPeerHeight { - end = maxPeerHeight - } - r.requestMissingBlocks(localHeight+1, end) + r.requestMissingBlocks(localHeight+1, maxPeerHeight) } // requestMissingBlocks requests blocks in range [start, end] from peers @@ -421,12 +428,24 @@ func (r *BlockBroadcastReactor) verifySignature(block *BlockV2) bool { return false } recoveredAddr := crypto.PubkeyToAddress(*pubKey) - expectedAddr := upgrade.SequencerAddress - if !upgrade.IsSequencer(recoveredAddr) { - r.logger.Error("Signature verification failed: address mismatch", + + if r.verifier == nil { + r.logger.Error("Sequencer verifier not set", "block", block.Number) + return false + } + + isSeq, err := r.verifier.IsSequencer(context.Background(), recoveredAddr) + if err != nil { + r.logger.Error("Signature verification failed: verifier error", "block", block.Number, "recovered", recoveredAddr.Hex(), - "expected", expectedAddr.Hex()) + "err", err) + return false + } + if !isSeq { + r.logger.Error("Signature verification failed: not a valid sequencer", + "block", block.Number, + "recovered", recoveredAddr.Hex()) return false } return true diff --git a/sequencer/interfaces.go b/sequencer/interfaces.go new file mode 100644 index 00000000000..3063b15fb2c --- /dev/null +++ b/sequencer/interfaces.go @@ -0,0 +1,22 @@ +package sequencer + +import ( + "context" + + "github.com/morph-l2/go-ethereum/common" +) + +// SequencerVerifier verifies if an address is the current L1 sequencer +type SequencerVerifier interface { + IsSequencer(ctx context.Context, addr common.Address) (bool, error) +} + +// Signer interface for sequencer block signing +type Signer interface { + // Sign signs the data with the sequencer's private key + Sign(data []byte) ([]byte, error) + // Address returns the sequencer's address + Address() common.Address + // IsActiveSequencer checks if this signer is the current L1 sequencer + IsActiveSequencer(ctx context.Context) (bool, error) +} diff --git a/sequencer/state_v2.go b/sequencer/state_v2.go index c856daa324d..14833973de1 100644 --- a/sequencer/state_v2.go +++ b/sequencer/state_v2.go @@ -1,16 +1,11 @@ package sequencer import ( - "crypto/ecdsa" + "context" "fmt" "sync" "time" - "github.com/tendermint/tendermint/upgrade" - - "github.com/morph-l2/go-ethereum/common" - "github.com/morph-l2/go-ethereum/crypto" - "github.com/tendermint/tendermint/l2node" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/service" @@ -19,7 +14,7 @@ import ( const ( // DefaultBlockInterval is the default interval between blocks // TODO: make this configurable - DefaultBlockInterval = 300 * time.Millisecond + DefaultBlockInterval = 3000 * time.Millisecond ) // StateV2 manages the state for centralized sequencer mode. @@ -30,14 +25,14 @@ type StateV2 struct { mtx sync.RWMutex // Core state - latestBlock *BlockV2 - isSequencer bool + latestBlock *BlockV2 + sequencerMode bool // Whether the node is started in sequencer mode (has signer configured) // Dependencies - l2Node l2node.L2Node - privKey *ecdsa.PrivateKey - seqAddr common.Address - logger log.Logger + l2Node l2node.L2Node + signer Signer + verifier SequencerVerifier + logger log.Logger // Block production blockTicker *time.Ticker @@ -51,26 +46,23 @@ type StateV2 struct { } // NewStateV2 creates a new StateV2 instance. +// sequencerMode is determined by whether a signer is provided. func NewStateV2( l2Node l2node.L2Node, - privKey *ecdsa.PrivateKey, blockInterval time.Duration, logger log.Logger, + verifier SequencerVerifier, + signer Signer, ) (*StateV2, error) { if blockInterval <= 0 { blockInterval = DefaultBlockInterval } - // Derive sequencer address from private key - var seqAddr common.Address - if privKey != nil { - seqAddr = crypto.PubkeyToAddress(privKey.PublicKey) - } - s := &StateV2{ l2Node: l2Node, - privKey: privKey, - seqAddr: seqAddr, + signer: signer, + verifier: verifier, + sequencerMode: signer != nil, blockInterval: blockInterval, logger: logger.With("module", "stateV2"), broadcastCh: make(chan *BlockV2, 100), @@ -83,7 +75,7 @@ func NewStateV2( } // OnStart implements service.Service. -// It initializes state from geth and starts block production if this node is the sequencer. +// It initializes state from geth and starts block production if this node is the active sequencer. func (s *StateV2) OnStart() error { // Initialize latest block from geth latestBlock, err := s.l2Node.GetLatestBlockV2() @@ -93,19 +85,29 @@ func (s *StateV2) OnStart() error { s.mtx.Lock() s.latestBlock = latestBlock - - // Check if this node is the sequencer - s.isSequencer = upgrade.IsSequencer(s.seqAddr) s.mtx.Unlock() + var seqAddr string + var isActiveSequencer bool + if s.signer != nil { + seqAddr = s.signer.Address().Hex() + // Check if this node is the active sequencer via L1 contract + isActiveSequencer, err = s.signer.IsActiveSequencer(context.Background()) + if err != nil { + s.logger.Error("Failed to check sequencer status", "error", err) + isActiveSequencer = false + } + } + s.logger.Info("StateV2 initialized", "latestHeight", s.latestBlock.Number, "latestHash", s.latestBlock.Hash.Hex(), - "isSequencer", s.isSequencer, - "seqAddr", s.seqAddr.Hex()) + "sequencerMode", s.sequencerMode, + "isActiveSequencer", isActiveSequencer, + "seqAddr", seqAddr) - // Start block production if this node is the sequencer - if s.isSequencer { + // Start block production if sequencer mode is enabled and this node is the active sequencer + if s.sequencerMode && isActiveSequencer { go s.produceBlockRoutine() } @@ -184,23 +186,21 @@ func (s *StateV2) produceBlock() { } } -// signBlock signs the block hash with the sequencer's private key. +// signBlock signs the block hash with the signer. func (s *StateV2) signBlock(block *BlockV2) error { - if s.privKey == nil { - return fmt.Errorf("private key not set") + if s.signer == nil { + return fmt.Errorf("signer not set") } // Sign the block hash - signature, err := crypto.Sign(block.Hash.Bytes(), s.privKey) + signature, err := s.signer.Sign(block.Hash.Bytes()) if err != nil { return fmt.Errorf("failed to sign block: %w", err) } block.Signature = signature - // Debug: log signer address - signerAddr := crypto.PubkeyToAddress(s.privKey.PublicKey) - s.logger.Debug("Block signed", "number", block.Number, "hash", block.Hash.Hex(), "signer", signerAddr.Hex()) + s.logger.Debug("Block signed", "number", block.Number, "hash", block.Hash.Hex(), "signer", s.signer.Address().Hex()) return nil } @@ -249,9 +249,8 @@ func (s *StateV2) GetBlockByNumber(number uint64) (*BlockV2, error) { return s.l2Node.GetBlockByNumber(number) } -// IsSequencerNode returns whether this node is the sequencer. -func (s *StateV2) IsSequencerNode() bool { - s.mtx.RLock() - defer s.mtx.RUnlock() - return s.isSequencer +// IsSequencerMode returns whether this node is started in sequencer mode. +// This means the node has a signer configured and can potentially produce blocks. +func (s *StateV2) IsSequencerMode() bool { + return s.sequencerMode } diff --git a/sequencer/state_v2_test.go b/sequencer/state_v2_test.go index af0c0c711ba..d33f25293fb 100644 --- a/sequencer/state_v2_test.go +++ b/sequencer/state_v2_test.go @@ -1,16 +1,38 @@ package sequencer import ( - "crypto/ecdsa" + "context" "testing" "time" - "github.com/morph-l2/go-ethereum/crypto" + "github.com/morph-l2/go-ethereum/common" "github.com/tendermint/tendermint/l2node" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/types" ) +// mockSignerImpl is a mock implementation of Signer for testing +type mockSignerImpl struct { + address common.Address + signature []byte + isActive bool +} + +func (m *mockSignerImpl) Sign(data []byte) ([]byte, error) { + if m.signature != nil { + return m.signature, nil + } + return make([]byte, 65), nil +} + +func (m *mockSignerImpl) Address() common.Address { + return m.address +} + +func (m *mockSignerImpl) IsActiveSequencer(ctx context.Context) (bool, error) { + return m.isActive, nil +} + // newTestMockL2Node creates a mock L2Node for testing func newTestMockL2Node() l2node.L2Node { return l2node.NewMockL2Node(0, "") @@ -20,7 +42,7 @@ func TestStateV2_NewStateV2(t *testing.T) { mockL2Node := newTestMockL2Node() logger := log.NewNopLogger() - stateV2, err := NewStateV2(mockL2Node, nil, time.Second, logger) + stateV2, err := NewStateV2(mockL2Node, time.Second, logger, nil, nil) if err != nil { t.Fatalf("NewStateV2 failed: %v", err) } @@ -34,7 +56,7 @@ func TestStateV2_LatestHeight(t *testing.T) { mockL2Node := newTestMockL2Node() logger := log.NewNopLogger() - stateV2, err := NewStateV2(mockL2Node, nil, time.Second, logger) + stateV2, err := NewStateV2(mockL2Node, time.Second, logger, nil, nil) if err != nil { t.Fatalf("NewStateV2 failed: %v", err) } @@ -46,24 +68,29 @@ func TestStateV2_LatestHeight(t *testing.T) { } } -func TestStateV2_IsSequencerNode(t *testing.T) { +func TestStateV2_IsSequencerMode(t *testing.T) { mockL2Node := newTestMockL2Node() logger := log.NewNopLogger() - // Generate a test private key - privKey, err := crypto.GenerateKey() + // Without signer, sequencerMode should be false + stateV2, err := NewStateV2(mockL2Node, time.Second, logger, nil, nil) if err != nil { - t.Fatalf("Failed to generate key: %v", err) + t.Fatalf("NewStateV2 failed: %v", err) } - stateV2, err := NewStateV2(mockL2Node, privKey, time.Second, logger) + if stateV2.IsSequencerMode() { + t.Error("IsSequencerMode should be false when signer is nil") + } + + // With mock signer, sequencerMode should be true + mockSigner := &mockSignerImpl{} + stateV2WithSigner, err := NewStateV2(mockL2Node, time.Second, logger, nil, mockSigner) if err != nil { t.Fatalf("NewStateV2 failed: %v", err) } - // Before start, isSequencer is not set - if stateV2.IsSequencerNode() { - t.Error("IsSequencerNode should be false before start") + if !stateV2WithSigner.IsSequencerMode() { + t.Error("IsSequencerMode should be true when signer is provided") } } @@ -71,13 +98,12 @@ func TestStateV2_SignBlock(t *testing.T) { mockL2Node := newTestMockL2Node() logger := log.NewNopLogger() - // Generate a test private key - privKey, err := crypto.GenerateKey() - if err != nil { - t.Fatalf("Failed to generate key: %v", err) + // Create mock signer + mockSigner := &mockSignerImpl{ + signature: make([]byte, 65), // Mock 65-byte signature } - stateV2, err := NewStateV2(mockL2Node, privKey, time.Second, logger) + stateV2, err := NewStateV2(mockL2Node, time.Second, logger, nil, mockSigner) if err != nil { t.Fatalf("NewStateV2 failed: %v", err) } @@ -104,12 +130,12 @@ func TestStateV2_SignBlock(t *testing.T) { } } -func TestStateV2_SignBlockWithoutKey(t *testing.T) { +func TestStateV2_SignBlockWithoutSigner(t *testing.T) { mockL2Node := newTestMockL2Node() logger := log.NewNopLogger() - // Create StateV2 without private key - stateV2, err := NewStateV2(mockL2Node, nil, time.Second, logger) + // Create StateV2 without signer + stateV2, err := NewStateV2(mockL2Node, time.Second, logger, nil, nil) if err != nil { t.Fatalf("NewStateV2 failed: %v", err) } @@ -119,22 +145,19 @@ func TestStateV2_SignBlockWithoutKey(t *testing.T) { Hash: [32]byte{1, 2, 3, 4}, } - // Sign should fail without private key + // Sign should fail without signer err = stateV2.signBlock(block) if err == nil { - t.Error("signBlock should fail without private key") + t.Error("signBlock should fail without signer") } } -// TestStateV2_UpdateLatestBlock and TestStateV2_UpdateLatestBlock_NonContinuous -// were removed because UpdateLatestBlock was merged into ApplyBlock - -// Helper to create a test StateV2 with a running state -func createTestStateV2(t *testing.T, privKey *ecdsa.PrivateKey) *StateV2 { +// Helper to create a test StateV2 +func createTestStateV2(t *testing.T, signer Signer) *StateV2 { mockL2Node := newTestMockL2Node() logger := log.NewNopLogger() - stateV2, err := NewStateV2(mockL2Node, privKey, time.Second, logger) + stateV2, err := NewStateV2(mockL2Node, time.Second, logger, nil, signer) if err != nil { t.Fatalf("NewStateV2 failed: %v", err) } diff --git a/upgrade/upgrade.go b/upgrade/upgrade.go index d093384921b..6068cbcce14 100644 --- a/upgrade/upgrade.go +++ b/upgrade/upgrade.go @@ -1,38 +1,14 @@ package upgrade -import ( - "github.com/morph-l2/go-ethereum/common" -) - // Hardcoded upgrade parameters var ( // UpgradeBlockHeight is the block height at which the sequencer upgrade activates // For testing, set this to a low value (e.g., 50) // TODO: add sequencer update logic UpgradeBlockHeight int64 = 10 - - // SequencerAddress is the address of the centralized sequencer - // Default: Hardhat test account #0 - // TODO: add sequencer update logic - SequencerAddress = common.HexToAddress("0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266") ) // IsUpgraded returns true if the given height is at or after the upgrade height func IsUpgraded(height int64) bool { return height >= UpgradeBlockHeight } - -// IsSequencer returns true if the given address is the sequencer address -func IsSequencer(addr common.Address) bool { - return addr == SequencerAddress -} - -// SetUpgradeBlockHeight sets the upgrade block height (for testing) -func SetUpgradeBlockHeight(height int64) { - UpgradeBlockHeight = height -} - -// SetSequencerAddress sets the sequencer address (for testing) -func SetSequencerAddress(addr common.Address) { - SequencerAddress = addr -}