From 42c4ca1b0b3fcd44b3882c136e5cd225e8045cf7 Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Tue, 18 Feb 2025 11:47:50 +0800 Subject: [PATCH 1/8] feat: add batch query logic --- node/cmd/node/main.go | 13 ++- node/core/batch.go | 210 +++++++++++++++++++++++++++++++++++++++++ node/core/executor.go | 8 +- node/db/store_batch.go | 82 ++++++++++++++++ node/db/tmstore.go | 51 ++++++++++ 5 files changed, 362 insertions(+), 2 deletions(-) create mode 100644 node/db/store_batch.go create mode 100644 node/db/tmstore.go diff --git a/node/cmd/node/main.go b/node/cmd/node/main.go index 25a5a0a05..f1575cc16 100644 --- a/node/cmd/node/main.go +++ b/node/cmd/node/main.go @@ -120,10 +120,21 @@ func L2NodeMain(ctx *cli.Context) error { if err != nil { return err } + dbConfig := db.DefaultConfig() + dbConfig.SetCliContext(ctx) + nodedb, err := db.NewStore(dbConfig, home) + if err != nil { + return err + } + tmdb, err := db.NewTmDB(tmCfg) + if err != nil { + return err + } + tmVal := privval.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()) pubKey, _ := tmVal.GetPubKey() newSyncerFunc := func() (*sync.Syncer, error) { return node.NewSyncer(ctx, home, nodeConfig) } - executor, err = node.NewExecutor(newSyncerFunc, nodeConfig, pubKey) + executor, err = node.NewExecutor(newSyncerFunc, nodeConfig, pubKey, tmdb, nodedb) if err != nil { return err } diff --git a/node/core/batch.go b/node/core/batch.go index 987c4bf03..856f1b6ba 100644 --- a/node/core/batch.go +++ b/node/core/batch.go @@ -8,6 +8,7 @@ import ( "morph-l2/node/types" + "github.com/morph-l2/go-ethereum/accounts/abi/bind" "github.com/morph-l2/go-ethereum/common" eth "github.com/morph-l2/go-ethereum/core/types" "github.com/morph-l2/go-ethereum/crypto" @@ -351,3 +352,212 @@ func (e *Executor) ConvertBlsData(blsData l2node.BlsData) (*eth.BatchSignature, func (e *Executor) isBatchUpgraded(blockTime uint64) bool { return blockTime >= e.UpgradeBatchTime } + +func (e *Executor) BatchByIndex(index uint64) (*eth.RollupBatch, []*eth.BatchSignature, error) { + + //todo: batch index = 1 ,genesis batch header + // query batch db + batch, sigs, err := e.nodeDB.GetBatchByIndex(index) + if err != nil { + return nil, nil, fmt.Errorf("failed to read batch from nodedb, index: %d, error: %v", index, err) + } + + if batch != nil { + return batch, sigs, nil + } + // query tendermint db + batch, sigs, err = e.batchByIndex(index) + if err != nil { + return nil, nil, fmt.Errorf("failed to read batch from tmdb, index: %d, error: %v", index, err) + } + // store in nodedb + if err := e.nodeDB.ImportBatch(batch, sigs); err != nil { + return nil, nil, fmt.Errorf("failed to write batch to nodedb, index: %d, error: %v", index, err) + } + return batch, sigs, nil +} + +// batchByIndex extract batch from tmdb +func (e *Executor) batchByIndex(index uint64) (*eth.RollupBatch, []*eth.BatchSignature, error) { + // query batch db + h := e.tmDB.BlockStore.Height() + var curIndex uint64 + var err error + var blocks []*tmtypes.Block + // var blocks + for i := h; i >= 1; i-- { + block := e.tmDB.BlockStore.LoadBlock(i) + if block == nil { + return nil, nil, fmt.Errorf("failed to load block from db, index: %d", i) + } + if block.IsBatchPoint() { + if curIndex == 0 { + batcherHeader := types.BatchHeaderBytes(block.Data.L2BatchHeader.Bytes()) + curIndex, err = batcherHeader.BatchIndex() + if err != nil { + return nil, nil, fmt.Errorf("failed to get batch index from batch header, error: %v", err) + } + } else { + curIndex-- + } + } + if curIndex == index { + blocks = append(blocks, nil) + copy(blocks[1:], blocks) + blocks[0] = block + } + if curIndex < index { + break + } + + } + + // [batchpoint,batchpoint) + if len(blocks) > 0 { + blocks = blocks[:len(blocks)-1] + } + + return e.BlocksToBatch(blocks) + +} + +func (e *Executor) BlocksToBatch(blocks []*tmtypes.Block) (*eth.RollupBatch, []*eth.BatchSignature, error) { + // [batchPoint,batchPoint) + if len(blocks) < 2 { + return nil, nil, fmt.Errorf("invalid blocks length: %d", len(blocks)) + } + if !blocks[0].IsBatchPoint() && !blocks[len(blocks)-1].IsBatchPoint() { + return nil, nil, fmt.Errorf("invalid blocks, need batchPoint at the start and end") + } + point2 := blocks[len(blocks)-1] + blocks = blocks[:len(blocks)-1] + // get batchIndex at the last batchPoint + batchHeader := types.BatchHeaderBytes(point2.Data.L2BatchHeader.Bytes()) + index, err := batchHeader.BatchIndex() + if err != nil { + return nil, nil, fmt.Errorf("failed to get batch index from batch header, error: %v", err) + } + version, err := batchHeader.Version() + if err != nil { + return nil, nil, fmt.Errorf("failed to get batch version from batch header, error: %v", err) + } + hash, err := batchHeader.Hash() + if err != nil { + return nil, nil, fmt.Errorf("failed to get batch hash from batch header, error: %v", err) + } + parentBatchHeader := types.BatchHeaderBytes(blocks[0].Data.L2BatchHeader.Bytes()) + + batchData := types.NewBatchData() + var txsPayload []byte + var l1TxHashes []common.Hash + var lastHeightBeforeCurrentBatch uint64 + var l2TxNum int + + totalL1MessagePopped, err := parentBatchHeader.TotalL1MessagePopped() + if err != nil { + e.logger.Error("failed to get totalL1MessagePopped from parentBatchHeader", "error", err) + return nil, nil, err + } + lastBlockNum, err := parentBatchHeader.LastBlockNumber() + if err != nil { + return nil, nil, fmt.Errorf("failed to get last block number from parentBatchHeader, error: %v", err) + } + for _, block := range blocks { + wBlock := new(types.WrappedBlock) + if err = wBlock.UnmarshalBinary(block.Data.L2BlockMeta); err != nil { + return nil, nil, fmt.Errorf("failed to unmarshal wrapped block: %w", err) + } + + totalL1MessagePoppedBefore := totalL1MessagePopped + txsPayload, l1TxHashes, totalL1MessagePopped, l2TxNum, err = ParsingTxs(block.Data.Txs, totalL1MessagePoppedBefore) + if err != nil { + return nil, nil, fmt.Errorf("failed to parse txs: %w", err) + } + l1TxNum := int(totalL1MessagePopped - totalL1MessagePoppedBefore) + blockContext := wBlock.BlockContextBytes(l2TxNum+l1TxNum, l1TxNum) + batchData.Append(blockContext, txsPayload, l1TxHashes) + } + blockContexts, err := batchData.Encode() + if err != nil { + return nil, nil, fmt.Errorf("failed to encode block contexts: %w", err) + } + + // Get the sequencer set at current height - 1 + callOpts := &bind.CallOpts{BlockNumber: big.NewInt(int64(lastHeightBeforeCurrentBatch))} + sequencerSetBytes, err := e.sequencerCaller.GetSequencerSetBytes(callOpts) + if err != nil { + return nil, nil, fmt.Errorf("failed to get sequencer set bytes: %w", err) + } + prevStateRoot, err := batchHeader.PrevStateRoot() + if err != nil { + return nil, nil, fmt.Errorf("failed to get prev state root: %w", err) + } + l1MsgPopped, err := batchHeader.L1MessagePopped() + if err != nil { + return nil, nil, fmt.Errorf("failed to get l1 message popped: %w", err) + } + postStateRoot, err := batchHeader.PostStateRoot() + if err != nil { + return nil, nil, fmt.Errorf("failed to get post state root: %w", err) + } + withdrawRoot, err := batchHeader.WithdrawalRoot() + if err != nil { + return nil, nil, fmt.Errorf("failed to get withdraw root: %w", err) + } + + var ( + compressedPayload []byte + ) + blockTimestamp := uint64(blocks[len(blocks)-1].Header.Time.Unix()) + if e.isBatchUpgraded(blockTimestamp) { + compressedPayload, err = types.CompressBatchBytes(batchData.TxsPayloadV2()) + if err != nil { + return nil, nil, fmt.Errorf("failed to compress upgraded payload: %w", err) + } + } else { + compressedPayload, err = types.CompressBatchBytes(e.batchingCache.batchData.TxsPayload()) + if err != nil { + return nil, nil, fmt.Errorf("failed to compress payload: %w", err) + } + } + + sidecar, err := types.MakeBlobTxSidecar(compressedPayload) + if err != nil { + return nil, nil, fmt.Errorf("failed to create blob sidecar: %w", err) + } + + // sigs + commit := e.tmDB.BlockStore.LoadSeenCommit(point2.Height) + validatorSet, err := e.tmDB.StateStore.LoadValidators(point2.Height) + blsDatas, err := l2node.GetBLSDatas(commit, validatorSet) + if err != nil { + return nil, nil, fmt.Errorf("failed to get BLS data: %w", err) + } + batchSigs, err := e.ConvertBlsDatas(blsDatas) + if err != nil { + return nil, nil, fmt.Errorf("failed to convert BLS data: %w", err) + } + + batch := ð.RollupBatch{ + Index: index, + Hash: hash, + Version: uint(version), + ParentBatchHeader: parentBatchHeader.Bytes(), + BlockContexts: blockContexts, + SkippedL1MessageBitmap: nil, + CurrentSequencerSetBytes: sequencerSetBytes, + PrevStateRoot: prevStateRoot, + PostStateRoot: postStateRoot, + WithdrawRoot: withdrawRoot, + LastBlockNumber: lastBlockNum, + NumL1Messages: uint16(l1MsgPopped), + Sidecar: sidecar, + } + + batchSigsPtr := make([]*eth.BatchSignature, len(batchSigs)) + for i := range batchSigs { + batchSigsPtr[i] = &batchSigs[i] + } + + return batch, batchSigsPtr, nil +} diff --git a/node/core/executor.go b/node/core/executor.go index a7209526e..b35249b92 100644 --- a/node/core/executor.go +++ b/node/core/executor.go @@ -22,6 +22,7 @@ import ( tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "morph-l2/bindings/bindings" + "morph-l2/node/db" "morph-l2/node/sync" "morph-l2/node/types" ) @@ -57,6 +58,9 @@ type Executor struct { logger tmlog.Logger metrics *Metrics + + tmDB *db.TmDB + nodeDB *db.Store } func getNextL1MsgIndex(client *types.RetryableClient) (uint64, error) { @@ -67,7 +71,7 @@ func getNextL1MsgIndex(client *types.RetryableClient) (uint64, error) { return currentHeader.NextL1MsgIndex, nil } -func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubKey) (*Executor, error) { +func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubKey, tmdb *db.TmDB, nodedb *db.Store) (*Executor, error) { logger := config.Logger logger = logger.With("module", "executor") aClient, err := authclient.DialContext(context.Background(), config.L2.EngineAddr, config.L2.JwtSecret) @@ -123,6 +127,8 @@ func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubK UpgradeBatchTime: config.UpgradeBatchTime, logger: logger, metrics: PrometheusMetrics("morphnode"), + tmDB: tmdb, + nodeDB: nodedb, } if config.DevSequencer { diff --git a/node/db/store_batch.go b/node/db/store_batch.go new file mode 100644 index 000000000..63c913dd6 --- /dev/null +++ b/node/db/store_batch.go @@ -0,0 +1,82 @@ +package db + +import ( + "errors" + + "github.com/morph-l2/go-ethereum/core/rawdb" + "github.com/morph-l2/go-ethereum/core/types" + eth "github.com/morph-l2/go-ethereum/eth" +) + +func (s *Store) ImportBatch(batch *types.RollupBatch, signatures []*types.BatchSignature) error { + + dbBatch := s.db.NewBatch() + rawdb.WriteRollupBatch(dbBatch, batch) + for _, signature := range signatures { + rawdb.WriteBatchSignature(dbBatch, batch.Hash, *signature) + } + return dbBatch.Write() +} + +func (s *Store) GetBatchByIndex(index uint64) (*types.RollupBatch, []*types.BatchSignature, error) { + rollupBatch, err := rawdb.ReadRollupBatch(s.db, index) + if err != nil { + return nil, nil, errors.New("failed to read batch") + } + if rollupBatch == nil { + return nil, nil, nil + } + signatures, err := rawdb.ReadBatchSignatures(s.db, rollupBatch.Hash) + if err != nil { + return nil, nil, errors.New("failed to read signatures") + } + return rollupBatch, signatures, nil +} + +func (s *Store) GetRollupBatchByIndex(index uint64) (*eth.RPCRollupBatch, error) { + rollupBatch, err := rawdb.ReadRollupBatch(s.db, index) + if err != nil { + return nil, errors.New("failed to read batch") + } + if rollupBatch == nil { + return nil, nil + } + signatures, err := rawdb.ReadBatchSignatures(s.db, rollupBatch.Hash) + if err != nil { + return nil, errors.New("failed to read signatures") + } + + rpcSignatures := make([]eth.RPCBatchSignature, len(signatures)) + for i, sig := range signatures { + rpcSignatures[i] = eth.RPCBatchSignature{ + Signer: sig.Signer, + SignerPubKey: sig.SignerPubKey, + Signature: sig.Signature, + } + } + + var sidecar types.BlobTxSidecar + if rollupBatch.Sidecar != nil { + sidecar = *rollupBatch.Sidecar + } + + // var collectedL1Fee *hexutil.Big + // l1DataFee := rawdb.ReadBatchL1DataFee(s.db, index) + // if l1DataFee != nil { + // collectedL1Fee = (*hexutil.Big)(l1DataFee) + // } + + return ð.RPCRollupBatch{ + Version: rollupBatch.Version, + Hash: rollupBatch.Hash, + ParentBatchHeader: rollupBatch.ParentBatchHeader, + BlockContexts: rollupBatch.BlockContexts, + CurrentSequencerSetBytes: rollupBatch.CurrentSequencerSetBytes, + PrevStateRoot: rollupBatch.PrevStateRoot, + PostStateRoot: rollupBatch.PostStateRoot, + WithdrawRoot: rollupBatch.WithdrawRoot, + Sidecar: sidecar, + Signatures: rpcSignatures, + // CollectedL1Fee: collectedL1Fee, + }, nil +} diff --git a/node/db/tmstore.go b/node/db/tmstore.go new file mode 100644 index 000000000..87f735697 --- /dev/null +++ b/node/db/tmstore.go @@ -0,0 +1,51 @@ +package db + +import ( + "fmt" + "path/filepath" + + "github.com/tendermint/tendermint/config" + "github.com/tendermint/tendermint/libs/os" + "github.com/tendermint/tendermint/state" + "github.com/tendermint/tendermint/store" + dbm "github.com/tendermint/tm-db" +) + +type TmDB struct { + BlockStore *store.BlockStore + StateStore state.Store +} + +func NewTmDB(config *config.Config) (*TmDB, error) { + + dbType := dbm.BackendType(config.DBBackend) + + if !os.FileExists(filepath.Join(config.DBDir(), "blockstore.db")) { + return nil, fmt.Errorf("no blockstore found in %v", config.DBDir()) + } + + // Get BlockStore + blockStoreDB, err := dbm.NewDB("blockstore", dbType, config.DBDir()) + if err != nil { + return nil, err + } + blockStore := store.NewBlockStore(blockStoreDB) + + if !os.FileExists(filepath.Join(config.DBDir(), "state.db")) { + return nil, fmt.Errorf("no statestore found in %v", config.DBDir()) + } + + // Get StateStore + stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) + if err != nil { + return nil, err + } + stateStore := state.NewStore(stateDB, state.StoreOptions{ + DiscardABCIResponses: config.Storage.DiscardABCIResponses, + }) + + return &TmDB{ + BlockStore: blockStore, + StateStore: stateStore, + }, nil +} From 5357336b0392ec8c51fe595256710218e7b63d5c Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Tue, 18 Feb 2025 18:13:07 +0800 Subject: [PATCH 2/8] refactor: remove tmDB from executor initialization and update batch processing logic --- node/cmd/node/main.go | 11 +++++---- node/core/batch.go | 55 ++++++++++++++++++++++++++----------------- node/core/executor.go | 7 ++++-- node/db/tmstore.go | 37 ++--------------------------- 4 files changed, 46 insertions(+), 64 deletions(-) diff --git a/node/cmd/node/main.go b/node/cmd/node/main.go index f1575cc16..c77f50a61 100644 --- a/node/cmd/node/main.go +++ b/node/cmd/node/main.go @@ -126,15 +126,11 @@ func L2NodeMain(ctx *cli.Context) error { if err != nil { return err } - tmdb, err := db.NewTmDB(tmCfg) - if err != nil { - return err - } tmVal := privval.LoadOrGenFilePV(tmCfg.PrivValidatorKeyFile(), tmCfg.PrivValidatorStateFile()) pubKey, _ := tmVal.GetPubKey() newSyncerFunc := func() (*sync.Syncer, error) { return node.NewSyncer(ctx, home, nodeConfig) } - executor, err = node.NewExecutor(newSyncerFunc, nodeConfig, pubKey, tmdb, nodedb) + executor, err = node.NewExecutor(newSyncerFunc, nodeConfig, pubKey, nodedb) if err != nil { return err } @@ -148,6 +144,11 @@ func L2NodeMain(ctx *cli.Context) error { if tmNode, err = sequencer.SetupNode(tmCfg, tmVal, executor, nodeConfig.Logger); err != nil { return fmt.Errorf("failed to setup consensus node, error: %v", err) } + tmDB := &db.TmDB{ + BlockStore: tmNode.BlockStore(), + StateStore: tmNode.StateStore(), + } + executor.SetTmDB(tmDB) if err = tmNode.Start(); err != nil { return fmt.Errorf("failed to start consensus node, error: %v", err) } diff --git a/node/core/batch.go b/node/core/batch.go index 856f1b6ba..9e50a17b0 100644 --- a/node/core/batch.go +++ b/node/core/batch.go @@ -401,7 +401,7 @@ func (e *Executor) batchByIndex(index uint64) (*eth.RollupBatch, []*eth.BatchSig curIndex-- } } - if curIndex == index { + if curIndex <= index { blocks = append(blocks, nil) copy(blocks[1:], blocks) blocks[0] = block @@ -412,36 +412,43 @@ func (e *Executor) batchByIndex(index uint64) (*eth.RollupBatch, []*eth.BatchSig } - // [batchpoint,batchpoint) - if len(blocks) > 0 { - blocks = blocks[:len(blocks)-1] + // [batchpoint,...,batchpoint] + if len(blocks) < 2 { + return nil, nil, nil } + point2 := blocks[len(blocks)-1] + point2BatchHeader := types.BatchHeaderBytes(point2.Data.L2BatchHeader.Bytes()) + point2Height := point2.Height - return e.BlocksToBatch(blocks) + // [batchpoint,...,batchpoint) + blocks = blocks[:len(blocks)-1] + + return e.BlocksToBatch(blocks, point2BatchHeader, point2Height) } -func (e *Executor) BlocksToBatch(blocks []*tmtypes.Block) (*eth.RollupBatch, []*eth.BatchSignature, error) { - // [batchPoint,batchPoint) - if len(blocks) < 2 { - return nil, nil, fmt.Errorf("invalid blocks length: %d", len(blocks)) +// [batchPoint,batchPoint) +// point 1,2,3,4 point2 +// batchblocks,point2 batchheader,point2 height) +func (e *Executor) BlocksToBatch(blocks []*tmtypes.Block, point2BatchHeaer types.BatchHeaderBytes, point2Height int64) (*eth.RollupBatch, []*eth.BatchSignature, error) { + + if len(blocks) < 1 { + return nil, nil, nil } - if !blocks[0].IsBatchPoint() && !blocks[len(blocks)-1].IsBatchPoint() { - return nil, nil, fmt.Errorf("invalid blocks, need batchPoint at the start and end") + if !blocks[0].IsBatchPoint() { + return nil, nil, fmt.Errorf("invalid blocks, first block is not batch point") } - point2 := blocks[len(blocks)-1] blocks = blocks[:len(blocks)-1] // get batchIndex at the last batchPoint - batchHeader := types.BatchHeaderBytes(point2.Data.L2BatchHeader.Bytes()) - index, err := batchHeader.BatchIndex() + index, err := point2BatchHeaer.BatchIndex() if err != nil { return nil, nil, fmt.Errorf("failed to get batch index from batch header, error: %v", err) } - version, err := batchHeader.Version() + version, err := point2BatchHeaer.Version() if err != nil { return nil, nil, fmt.Errorf("failed to get batch version from batch header, error: %v", err) } - hash, err := batchHeader.Hash() + hash, err := point2BatchHeaer.Hash() if err != nil { return nil, nil, fmt.Errorf("failed to get batch hash from batch header, error: %v", err) } @@ -488,19 +495,19 @@ func (e *Executor) BlocksToBatch(blocks []*tmtypes.Block) (*eth.RollupBatch, []* if err != nil { return nil, nil, fmt.Errorf("failed to get sequencer set bytes: %w", err) } - prevStateRoot, err := batchHeader.PrevStateRoot() + prevStateRoot, err := point2BatchHeaer.PrevStateRoot() if err != nil { return nil, nil, fmt.Errorf("failed to get prev state root: %w", err) } - l1MsgPopped, err := batchHeader.L1MessagePopped() + l1MsgPopped, err := point2BatchHeaer.L1MessagePopped() if err != nil { return nil, nil, fmt.Errorf("failed to get l1 message popped: %w", err) } - postStateRoot, err := batchHeader.PostStateRoot() + postStateRoot, err := point2BatchHeaer.PostStateRoot() if err != nil { return nil, nil, fmt.Errorf("failed to get post state root: %w", err) } - withdrawRoot, err := batchHeader.WithdrawalRoot() + withdrawRoot, err := point2BatchHeaer.WithdrawalRoot() if err != nil { return nil, nil, fmt.Errorf("failed to get withdraw root: %w", err) } @@ -527,8 +534,12 @@ func (e *Executor) BlocksToBatch(blocks []*tmtypes.Block) (*eth.RollupBatch, []* } // sigs - commit := e.tmDB.BlockStore.LoadSeenCommit(point2.Height) - validatorSet, err := e.tmDB.StateStore.LoadValidators(point2.Height) + // todo + commit := e.tmDB.BlockStore.LoadBlockCommit(point2Height) + validatorSet, err := e.tmDB.StateStore.LoadValidators(point2Height) + if err != nil { + return nil, nil, fmt.Errorf("failed to load validator set: %w", err) + } blsDatas, err := l2node.GetBLSDatas(commit, validatorSet) if err != nil { return nil, nil, fmt.Errorf("failed to get BLS data: %w", err) diff --git a/node/core/executor.go b/node/core/executor.go index b35249b92..65f3a57b3 100644 --- a/node/core/executor.go +++ b/node/core/executor.go @@ -71,7 +71,7 @@ func getNextL1MsgIndex(client *types.RetryableClient) (uint64, error) { return currentHeader.NextL1MsgIndex, nil } -func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubKey, tmdb *db.TmDB, nodedb *db.Store) (*Executor, error) { +func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubKey, nodedb *db.Store) (*Executor, error) { logger := config.Logger logger = logger.With("module", "executor") aClient, err := authclient.DialContext(context.Background(), config.L2.EngineAddr, config.L2.JwtSecret) @@ -127,7 +127,6 @@ func NewExecutor(newSyncFunc NewSyncerFunc, config *Config, tmPubKey crypto.PubK UpgradeBatchTime: config.UpgradeBatchTime, logger: logger, metrics: PrometheusMetrics("morphnode"), - tmDB: tmdb, nodeDB: nodedb, } @@ -410,3 +409,7 @@ func (e *Executor) getParamsAndValsAtHeight(height int64) (*tmproto.BatchParams, func (e *Executor) L2Client() *types.RetryableClient { return e.l2Client } + +func (e *Executor) SetTmDB(tmdb *db.TmDB) { + e.tmDB = tmdb +} diff --git a/node/db/tmstore.go b/node/db/tmstore.go index 87f735697..6890019be 100644 --- a/node/db/tmstore.go +++ b/node/db/tmstore.go @@ -1,14 +1,8 @@ package db import ( - "fmt" - "path/filepath" - - "github.com/tendermint/tendermint/config" - "github.com/tendermint/tendermint/libs/os" "github.com/tendermint/tendermint/state" "github.com/tendermint/tendermint/store" - dbm "github.com/tendermint/tm-db" ) type TmDB struct { @@ -16,36 +10,9 @@ type TmDB struct { StateStore state.Store } -func NewTmDB(config *config.Config) (*TmDB, error) { - - dbType := dbm.BackendType(config.DBBackend) - - if !os.FileExists(filepath.Join(config.DBDir(), "blockstore.db")) { - return nil, fmt.Errorf("no blockstore found in %v", config.DBDir()) - } - - // Get BlockStore - blockStoreDB, err := dbm.NewDB("blockstore", dbType, config.DBDir()) - if err != nil { - return nil, err - } - blockStore := store.NewBlockStore(blockStoreDB) - - if !os.FileExists(filepath.Join(config.DBDir(), "state.db")) { - return nil, fmt.Errorf("no statestore found in %v", config.DBDir()) - } - - // Get StateStore - stateDB, err := dbm.NewDB("state", dbType, config.DBDir()) - if err != nil { - return nil, err - } - stateStore := state.NewStore(stateDB, state.StoreOptions{ - DiscardABCIResponses: config.Storage.DiscardABCIResponses, - }) - +func NewTmDB(blockStore *store.BlockStore, stateStore state.Store) *TmDB { return &TmDB{ BlockStore: blockStore, StateStore: stateStore, - }, nil + } } From bb0b20e9c717d7746d180a1fede4bdfaa9aeda3b Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Thu, 20 Feb 2025 16:16:07 +0800 Subject: [PATCH 3/8] refactor: remove unused todo comments in batch.go for clarity --- node/core/batch.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/node/core/batch.go b/node/core/batch.go index 9e50a17b0..5b8604955 100644 --- a/node/core/batch.go +++ b/node/core/batch.go @@ -354,8 +354,6 @@ func (e *Executor) isBatchUpgraded(blockTime uint64) bool { } func (e *Executor) BatchByIndex(index uint64) (*eth.RollupBatch, []*eth.BatchSignature, error) { - - //todo: batch index = 1 ,genesis batch header // query batch db batch, sigs, err := e.nodeDB.GetBatchByIndex(index) if err != nil { @@ -534,7 +532,6 @@ func (e *Executor) BlocksToBatch(blocks []*tmtypes.Block, point2BatchHeaer types } // sigs - // todo commit := e.tmDB.BlockStore.LoadBlockCommit(point2Height) validatorSet, err := e.tmDB.StateStore.LoadValidators(point2Height) if err != nil { From 18ed44d588d09218beefbb62ad8adca9508c26e0 Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Thu, 20 Feb 2025 16:31:13 +0800 Subject: [PATCH 4/8] feat: store batch directly in nodedb --- node/core/batch_commit.go | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/node/core/batch_commit.go b/node/core/batch_commit.go index c0f161768..b9aab2a64 100644 --- a/node/core/batch_commit.go +++ b/node/core/batch_commit.go @@ -2,7 +2,6 @@ package node import ( "bytes" - "context" "fmt" "math/big" "morph-l2/node/types" @@ -66,8 +65,13 @@ func (e *Executor) CommitBatch(currentBlockBytes []byte, currentTxs tmtypes.Txs, parentBatchIndex, _ := e.batchingCache.parentBatchHeader.BatchIndex() hash, _ := e.batchingCache.sealedBatchHeader.Hash() l1MessagePopped, _ := e.batchingCache.sealedBatchHeader.L1MessagePopped() - // Construct the batch and commit it - if err = e.l2Client.CommitBatch(context.Background(), ð.RollupBatch{ + + // batchsigs type convert + var ptrBatchSigs []*eth.BatchSignature + for _, sig := range batchSigs { + ptrBatchSigs = append(ptrBatchSigs, &sig) + } + if err = e.nodeDB.ImportBatch(ð.RollupBatch{ Version: uint(version), Index: parentBatchIndex + 1, Hash: hash, @@ -80,8 +84,8 @@ func (e *Executor) CommitBatch(currentBlockBytes []byte, currentTxs tmtypes.Txs, Sidecar: e.batchingCache.sealedSidecar, LastBlockNumber: e.batchingCache.lastPackedBlockHeight, NumL1Messages: uint16(l1MessagePopped), - }, batchSigs); err != nil { - return fmt.Errorf("failed to commit batch to L2 client: %w", err) + }, ptrBatchSigs); err != nil { + return fmt.Errorf("failed to store batch: %w", err) } // Update batch index metric From c828c058c6abaad9d16f7cdb4633ee67d94464a2 Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Thu, 20 Feb 2025 17:54:47 +0800 Subject: [PATCH 5/8] chore: update tendermint dependency to v0.3.2-0.20250220094332-83d54a49cbba --- Makefile | 2 +- bindings/go.mod | 2 +- contracts/go.mod | 2 +- node/go.mod | 2 +- node/go.sum | 4 ++-- ops/l2-genesis/go.mod | 2 +- ops/tools/go.mod | 2 +- ops/tools/go.sum | 4 ++-- oracle/go.mod | 2 +- oracle/go.sum | 4 ++-- tx-submitter/go.mod | 2 +- tx-submitter/go.sum | 4 ++-- 12 files changed, 16 insertions(+), 16 deletions(-) diff --git a/Makefile b/Makefile index 59a959ce4..fda681fc6 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ ################## update dependencies #################### ETHEREUM_TARGET_VERSION := v1.10.14-0.20241226065029-3b9465a03a8c -TENDERMINT_TARGET_VERSION := v0.3.2-0.20250115141431-c84dfe5c8533 +TENDERMINT_TARGET_VERSION := v0.3.2-0.20250220094332-83d54a49cbba ETHEREUM_MODULE_NAME := github.com/morph-l2/go-ethereum TENDERMINT_MODULE_NAME := github.com/morph-l2/tendermint diff --git a/bindings/go.mod b/bindings/go.mod index 746274140..3600bbd10 100644 --- a/bindings/go.mod +++ b/bindings/go.mod @@ -2,7 +2,7 @@ module morph-l2/bindings go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c diff --git a/contracts/go.mod b/contracts/go.mod index c1f676f6e..042c76fec 100644 --- a/contracts/go.mod +++ b/contracts/go.mod @@ -2,7 +2,7 @@ module morph-l2/contract go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require ( github.com/iden3/go-iden3-crypto v0.0.16 diff --git a/node/go.mod b/node/go.mod index 560d05a0f..e3dac9493 100644 --- a/node/go.mod +++ b/node/go.mod @@ -2,7 +2,7 @@ module morph-l2/node go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require ( github.com/cenkalti/backoff/v4 v4.1.3 diff --git a/node/go.sum b/node/go.sum index 0791c3e4f..7f2847635 100644 --- a/node/go.sum +++ b/node/go.sum @@ -362,8 +362,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c h1:We0UnGcfs8wOSegGa97NjUE/6dZHE4ASuIWDuYBa+u8= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c/go.mod h1:sMJCfHOBzVRDkM2yF/Hy+oUk2rgC0CQZHTLs0cyzhhk= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 h1:qhBMCyTQ/ezOpeqHGKjr4qSN/B/bGFByuYjQqDt5wiw= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba h1:mnDz+BOGbESVmSxpi617IOohYZHAqFQR/xnpIwEGStI= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= diff --git a/ops/l2-genesis/go.mod b/ops/l2-genesis/go.mod index baee14bf0..43c480c11 100644 --- a/ops/l2-genesis/go.mod +++ b/ops/l2-genesis/go.mod @@ -2,7 +2,7 @@ module morph-l2/morph-deployer go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require ( github.com/holiman/uint256 v1.2.4 diff --git a/ops/tools/go.mod b/ops/tools/go.mod index 348b937a5..d337b46d8 100644 --- a/ops/tools/go.mod +++ b/ops/tools/go.mod @@ -2,7 +2,7 @@ module morph-l2/tools go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require ( github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c diff --git a/ops/tools/go.sum b/ops/tools/go.sum index 22b9bac33..22952b414 100644 --- a/ops/tools/go.sum +++ b/ops/tools/go.sum @@ -165,8 +165,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c h1:We0UnGcfs8wOSegGa97NjUE/6dZHE4ASuIWDuYBa+u8= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c/go.mod h1:sMJCfHOBzVRDkM2yF/Hy+oUk2rgC0CQZHTLs0cyzhhk= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 h1:qhBMCyTQ/ezOpeqHGKjr4qSN/B/bGFByuYjQqDt5wiw= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba h1:mnDz+BOGbESVmSxpi617IOohYZHAqFQR/xnpIwEGStI= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= diff --git a/oracle/go.mod b/oracle/go.mod index 5622af61e..c43a82181 100644 --- a/oracle/go.mod +++ b/oracle/go.mod @@ -2,7 +2,7 @@ module morph-l2/oracle go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require ( github.com/go-kit/kit v0.12.0 diff --git a/oracle/go.sum b/oracle/go.sum index d087a3498..f09e219f6 100644 --- a/oracle/go.sum +++ b/oracle/go.sum @@ -177,8 +177,8 @@ github.com/morph-l2/externalsign v0.3.1 h1:UYFDZFB0L85A4rDvuwLNBiGEi0kSmg9AZ2v8Q github.com/morph-l2/externalsign v0.3.1/go.mod h1:b6NJ4GUiiG/gcSJsp3p8ExsIs4ZdphlrVALASnVoGJE= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c h1:We0UnGcfs8wOSegGa97NjUE/6dZHE4ASuIWDuYBa+u8= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c/go.mod h1:sMJCfHOBzVRDkM2yF/Hy+oUk2rgC0CQZHTLs0cyzhhk= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 h1:qhBMCyTQ/ezOpeqHGKjr4qSN/B/bGFByuYjQqDt5wiw= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba h1:mnDz+BOGbESVmSxpi617IOohYZHAqFQR/xnpIwEGStI= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= diff --git a/tx-submitter/go.mod b/tx-submitter/go.mod index ed2e824bd..4a072a8f2 100644 --- a/tx-submitter/go.mod +++ b/tx-submitter/go.mod @@ -2,7 +2,7 @@ module morph-l2/tx-submitter go 1.22 -replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 +replace github.com/tendermint/tendermint => github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba require ( github.com/holiman/uint256 v1.2.4 diff --git a/tx-submitter/go.sum b/tx-submitter/go.sum index f47a4ef96..956d100fe 100644 --- a/tx-submitter/go.sum +++ b/tx-submitter/go.sum @@ -166,8 +166,8 @@ github.com/morph-l2/externalsign v0.3.1 h1:UYFDZFB0L85A4rDvuwLNBiGEi0kSmg9AZ2v8Q github.com/morph-l2/externalsign v0.3.1/go.mod h1:b6NJ4GUiiG/gcSJsp3p8ExsIs4ZdphlrVALASnVoGJE= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c h1:We0UnGcfs8wOSegGa97NjUE/6dZHE4ASuIWDuYBa+u8= github.com/morph-l2/go-ethereum v1.10.14-0.20241226065029-3b9465a03a8c/go.mod h1:sMJCfHOBzVRDkM2yF/Hy+oUk2rgC0CQZHTLs0cyzhhk= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533 h1:qhBMCyTQ/ezOpeqHGKjr4qSN/B/bGFByuYjQqDt5wiw= -github.com/morph-l2/tendermint v0.3.2-0.20250115141431-c84dfe5c8533/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba h1:mnDz+BOGbESVmSxpi617IOohYZHAqFQR/xnpIwEGStI= +github.com/morph-l2/tendermint v0.3.2-0.20250220094332-83d54a49cbba/go.mod h1:TtCzp9l6Z6yDUiwv3TbqKqw8Q8RKp3fSz5+adO1/Y8w= github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= From 8c98c7e74d1286c29dd1f416915442203e55571e Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Thu, 27 Feb 2025 00:13:34 +0800 Subject: [PATCH 6/8] feat: add dependency check for 'cast' command in Makefile --- Makefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index fda681fc6..30c3ebf3c 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,9 @@ TENDERMINT_TARGET_VERSION := v0.3.2-0.20250220094332-83d54a49cbba ETHEREUM_MODULE_NAME := github.com/morph-l2/go-ethereum TENDERMINT_MODULE_NAME := github.com/morph-l2/tendermint +.PHONY: check_deps +check_deps: + @command -v cast > /dev/null 2>&1 || { echo "Error: 'cast' command not found."; exit 1; } .PHONY: update_mod update_mod: @echo "Updating go.mod in $(MODULE)..." @@ -34,7 +37,7 @@ update_all_mod: update: go work sync - @$(MAKE) update_all_mod + # @$(MAKE) update_all_mod .PHONY: update submodules: @@ -128,7 +131,7 @@ go-ubuntu-builder: ################## devnet 4 nodes #################### -devnet-up: submodules go-ubuntu-builder +devnet-up: check_deps submodules go-ubuntu-builder python3 ops/devnet-morph/main.py --polyrepo-dir=. .PHONY: devnet-up From c6b73f4956551f0082b0aa6b7270eede3dffe0cb Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Thu, 27 Feb 2025 00:17:00 +0800 Subject: [PATCH 7/8] fix: enable update_all_mod in Makefile update target --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 30c3ebf3c..aef13cd51 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ update_all_mod: update: go work sync - # @$(MAKE) update_all_mod + @$(MAKE) update_all_mod .PHONY: update submodules: From 73453b519538601d4adc048b38f9fd71d1318887 Mon Sep 17 00:00:00 2001 From: WorldDogs Date: Thu, 27 Feb 2025 11:15:12 +0800 Subject: [PATCH 8/8] feat: add deploy config checks in Makefile --- Makefile | 26 +++++++++++++++++++++++--- 1 file changed, 23 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index aef13cd51..f14f0d46e 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,7 @@ TENDERMINT_MODULE_NAME := github.com/morph-l2/tendermint .PHONY: check_deps check_deps: @command -v cast > /dev/null 2>&1 || { echo "Error: 'cast' command not found."; exit 1; } + @command -v yarn > /dev/null 2>&1 || { echo "Error: 'yarn' command not found."; exit 1; } .PHONY: update_mod update_mod: @echo "Updating go.mod in $(MODULE)..." @@ -131,11 +132,11 @@ go-ubuntu-builder: ################## devnet 4 nodes #################### -devnet-up: check_deps submodules go-ubuntu-builder +devnet-up: check_deps submodules go-ubuntu-builder check-deploy-config python3 ops/devnet-morph/main.py --polyrepo-dir=. .PHONY: devnet-up -devnet-up-debugccc: +devnet-up-debugccc: check-deploy-config python3 ops/devnet-morph/main.py --polyrepo-dir=. --debugccc .PHONY: devnet-up-debugccc @@ -156,8 +157,9 @@ devnet-clean: devnet-clean-build docker image ls '*sentry-*' --format='{{.Repository}}' | xargs -r docker rmi .PHONY: devnet-clean -devnet-l1: +devnet-l1: check-deploy-config python3 ops/devnet-morph/main.py --polyrepo-dir=. --only-l1 +.PHONY: devnet-l1 devnet-logs: @(cd ops/docker && docker-compose logs -f) @@ -181,3 +183,21 @@ start-all-tx-submitter: # build geth geth: submodules cd go-ethereum && env GO111MODULE=on GOWORK=off go run build/ci.go install ./cmd/geth + +################## deploy config checks #################### + +check-deploy-config: + @echo "Checking deploy config file..." + @if [ -f ops/l2-genesis/deploy-config/devnet-deploy-config.json ]; then \ + if ! jq -e 'has("l2StakingPks")' ops/l2-genesis/deploy-config/devnet-deploy-config.json > /dev/null; then \ + echo "l2StakingPks field not found in deploy config, adding it..."; \ + jq '. + {"l2StakingPks": []}' ops/l2-genesis/deploy-config/devnet-deploy-config.json > ops/l2-genesis/deploy-config/temp.json && \ + mv ops/l2-genesis/deploy-config/temp.json ops/l2-genesis/deploy-config/devnet-deploy-config.json; \ + echo "l2StakingPks field added to deploy config."; \ + else \ + echo "l2StakingPks field already exists in deploy config."; \ + fi; \ + else \ + echo "Deploy config file not found at ops/l2-genesis/deploy-config/devnet-deploy-config.json"; \ + fi +.PHONY: check-deploy-config