Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 27 additions & 4 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
################## 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

.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)..."
Expand Down Expand Up @@ -128,11 +132,11 @@ go-ubuntu-builder:

################## devnet 4 nodes ####################

devnet-up: 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

Expand All @@ -153,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)
Expand All @@ -178,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
2 changes: 1 addition & 1 deletion bindings/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion contracts/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 13 additions & 1 deletion node/cmd/node/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,10 +120,17 @@ 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
}

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, nodedb)
if err != nil {
return err
}
Expand All @@ -137,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)
}
Expand Down
218 changes: 218 additions & 0 deletions node/core/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -351,3 +352,220 @@ 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) {
// 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) < 2 {
return nil, nil, nil
}
point2 := blocks[len(blocks)-1]
point2BatchHeader := types.BatchHeaderBytes(point2.Data.L2BatchHeader.Bytes())
point2Height := point2.Height

// [batchpoint,...,batchpoint)
blocks = blocks[:len(blocks)-1]

return e.BlocksToBatch(blocks, point2BatchHeader, point2Height)

}

// [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() {
return nil, nil, fmt.Errorf("invalid blocks, first block is not batch point")
}
blocks = blocks[:len(blocks)-1]
// get batchIndex at the last batchPoint
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 := point2BatchHeaer.Version()
if err != nil {
return nil, nil, fmt.Errorf("failed to get batch version from batch header, error: %v", err)
}
hash, err := point2BatchHeaer.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 := point2BatchHeaer.PrevStateRoot()
if err != nil {
return nil, nil, fmt.Errorf("failed to get prev state root: %w", err)
}
l1MsgPopped, err := point2BatchHeaer.L1MessagePopped()
if err != nil {
return nil, nil, fmt.Errorf("failed to get l1 message popped: %w", err)
}
postStateRoot, err := point2BatchHeaer.PostStateRoot()
if err != nil {
return nil, nil, fmt.Errorf("failed to get post state root: %w", err)
}
withdrawRoot, err := point2BatchHeaer.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.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)
}
batchSigs, err := e.ConvertBlsDatas(blsDatas)
if err != nil {
return nil, nil, fmt.Errorf("failed to convert BLS data: %w", err)
}

batch := &eth.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
}
14 changes: 9 additions & 5 deletions node/core/batch_commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package node

import (
"bytes"
"context"
"fmt"
"math/big"
"morph-l2/node/types"
Expand Down Expand Up @@ -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(), &eth.RollupBatch{

// batchsigs type convert
var ptrBatchSigs []*eth.BatchSignature
for _, sig := range batchSigs {
ptrBatchSigs = append(ptrBatchSigs, &sig)
}
if err = e.nodeDB.ImportBatch(&eth.RollupBatch{
Version: uint(version),
Index: parentBatchIndex + 1,
Hash: hash,
Expand All @@ -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
Expand Down
Loading