Skip to content
Merged
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
47 changes: 0 additions & 47 deletions .github/workflows/oracle.yml

This file was deleted.

1 change: 0 additions & 1 deletion go.work
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,5 @@ use (
./node
./ops/l2-genesis
./ops/tools
./oracle
./tx-submitter
)
4 changes: 0 additions & 4 deletions node/core/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,3 @@ func (e *Executor) ConvertBlsData(blsData l2node.BlsData) (*eth.BatchSignature,
}
return &bs, nil
}

func (e *Executor) isBatchUpgraded(blockTime uint64) bool {
return blockTime >= e.UpgradeBatchTime
}
218 changes: 126 additions & 92 deletions node/derivation/batch_info.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,19 @@ import (
"morph-l2/node/zstd"
)

const (
// BlockContextLegacyLength is the length of a legacy block context without coinbase
BlockContextLegacyLength = 60
)

type BlockContext struct {
Number uint64 `json:"number"`
Timestamp uint64 `json:"timestamp"`
BaseFee *big.Int
GasLimit uint64
txsNum uint16
l1MsgNum uint16
coinbase common.Address

SafeL2Data *catalyst.SafeL2Data
L2TxHashes []byte
Expand All @@ -36,15 +42,18 @@ func (b *BlockContext) Decode(bc []byte) error {
if err != nil {
return err
}
b.Number = wb.Number
b.Timestamp = wb.Timestamp
b.BaseFee = wb.BaseFee
b.GasLimit = wb.GasLimit
b.txsNum = txsNum
b.l1MsgNum = l1MsgNum
b.coinbase = wb.Miner
return nil
}

func decodeCoinbase(bc []byte) (common.Address, error) {
return types.DecodeCoinbase(bc)
}

type BatchInfo struct {
batchIndex uint64
blockNum uint64
Expand Down Expand Up @@ -79,143 +88,168 @@ func (bi *BatchInfo) TxNum() uint64 {
}

// ParseBatch This method is externally referenced for parsing Batch
func (bi *BatchInfo) ParseBatch(batch geth.RPCRollupBatch) error {
func (bi *BatchInfo) ParseBatch(batch geth.RPCRollupBatch, morph204Time uint64) error {
if len(batch.Sidecar.Blobs) == 0 {
return fmt.Errorf("blobs length can not be zero")
}

// Parse parent batch header
parentBatchHeader := types.BatchHeaderBytes(batch.ParentBatchHeader)
parentBatchIndex, err := parentBatchHeader.BatchIndex()
if err != nil {
return fmt.Errorf("decode batch header index error:%v", err)
return fmt.Errorf("decode batch header index error: %v", err)
}

totalL1MessagePopped, err := parentBatchHeader.TotalL1MessagePopped()
if err != nil {
return fmt.Errorf("decode batch header totalL1MessagePopped error:%v", err)
return fmt.Errorf("decode batch header totalL1MessagePopped error: %v", err)
}

// Initialize batch info fields
bi.parentTotalL1MessagePopped = totalL1MessagePopped
bi.root = batch.PostStateRoot
bi.batchIndex = parentBatchIndex + 1
bi.withdrawalRoot = batch.WithdrawRoot
bi.version = uint64(batch.Version)

tq := newTxQueue()
var rawBlockContexts hexutil.Bytes
var txsData []byte
var rawBlockContextsAndTxs hexutil.Bytes

// Handle version upgrade scenario
blobData, err := types.RetrieveBlobBytes(&batch.Sidecar.Blobs[0])
if err != nil {
return fmt.Errorf("retrieve blob bytes error: %v", err)
}

batchBytes, err := zstd.DecompressBatchBytes(blobData)
if err != nil {
return fmt.Errorf("decompress batch bytes error: %v", err)
}

// Calculate block count based on version
var blockCount uint64
if batch.Version > 0 {
parentVersion, err := parentBatchHeader.Version()
if err != nil {
return fmt.Errorf("decode batch header version error:%v", err)
}
if parentVersion == 0 {
if len(batch.Sidecar.Blobs) == 0 {
return fmt.Errorf("blobs length can not be zero")
}
blobData, err := types.RetrieveBlobBytes(&batch.Sidecar.Blobs[0])
if err != nil {
return err
}
batchBytes, err := zstd.DecompressBatchBytes(blobData)
if err != nil {
return fmt.Errorf("decompress batch bytes error:%v", err)
}
var startBlock BlockContext
if err := startBlock.Decode(batchBytes[:60]); err != nil {
return fmt.Errorf("decode chunk block context error:%v", err)
}
blockCount = batch.LastBlockNumber - startBlock.Number + 1
} else {
parentBatchBlock, err := parentBatchHeader.LastBlockNumber()
if err != nil {
return fmt.Errorf("decode batch header lastBlockNumber error:%v", err)
}
blockCount = batch.LastBlockNumber - parentBatchBlock
rawBlockContextsAndTxs = batchBytes
// Ensure we have enough data for block context
if len(batchBytes) < 60 {
return fmt.Errorf("insufficient batch bytes for block context, got %d bytes", len(batchBytes))
}

}
// If BlockContexts is not nil, the block context should not be included in the blob.
// Therefore, the required length must be zero.
length := blockCount * 60
for _, blob := range batch.Sidecar.Blobs {
blobCopy := blob
blobData, err := types.RetrieveBlobBytes(&blobCopy)
if err != nil {
return err
var startBlock BlockContext
// coinbase does not enter batch at this time
if err := startBlock.Decode(batchBytes[:60]); err != nil {
return fmt.Errorf("decode chunk block context error: %v", err)
}
batchBytes, err := zstd.DecompressBatchBytes(blobData)
if err != nil {
return err
}
reader := bytes.NewReader(batchBytes)
if batch.BlockContexts == nil {
if len(batchBytes) < int(length) {
rawBlockContexts = append(rawBlockContexts, batchBytes...)
length -= uint64(len(batchBytes))
reader.Reset(nil)
} else {
bcBytes := make([]byte, length)
_, err = reader.Read(bcBytes)
if err != nil {
return fmt.Errorf("read block context error:%s", err.Error())
}
rawBlockContexts = append(rawBlockContexts, bcBytes...)
length = 0
}
}
data, err := io.ReadAll(reader)
if err != nil {
return fmt.Errorf("read txBytes error:%s", err.Error())

blockCount = batch.LastBlockNumber - startBlock.Number + 1
} else {
// First 2 bytes contain the block count
if len(batch.BlockContexts) < 2 {
return fmt.Errorf("insufficient block contexts data: %d bytes", len(batch.BlockContexts))
}
txsData = append(txsData, data...)
}
if batch.BlockContexts != nil {

blockCount = uint64(binary.BigEndian.Uint16(batch.BlockContexts[:2]))
rawBlockContexts = batch.BlockContexts[2 : 60*blockCount+2]
rawBlockContextsAndTxs = append(rawBlockContextsAndTxs, batch.BlockContexts[2:]...)
rawBlockContextsAndTxs = append(rawBlockContextsAndTxs, batchBytes...)
}
data, err := types.DecodeTxsFromBytes(txsData)
if err != nil {
return err
}
tq.enqueue(data)

var txsNum uint64
var l1MsgNum uint64
blockContexts := make([]*BlockContext, int(blockCount))

reader := bytes.NewReader(rawBlockContextsAndTxs)
// Process block contexts
for i := 0; i < int(blockCount); i++ {
var block BlockContext
if err := block.Decode(rawBlockContexts[i*60 : i*60+60]); err != nil {
return fmt.Errorf("decode chunk block context error:%v", err)
bcBytes := make([]byte, BlockContextLegacyLength)
_, err = reader.Read(bcBytes)
if err != nil {
return fmt.Errorf("read block context numberAndTimeBytes error:%s", err.Error())
}
if err := block.Decode(bcBytes); err != nil {
return fmt.Errorf("decode number and timestamp error: %v", err)
}
var coinbase common.Address
// handle coinbase
if morph204Time != 0 && block.Timestamp >= morph204Time {
coinbaseBytes := make([]byte, common.AddressLength)
_, err = reader.Read(coinbaseBytes)
if err != nil {
return fmt.Errorf("read skipped block context error:%s", err.Error())
}

coinbase, err = decodeCoinbase(coinbaseBytes)
if err != nil {
return err
}
}

// Set boundary block numbers
if i == 0 {
bi.firstBlockNumber = block.Number
}
if i == int(blockCount)-1 {
bi.lastBlockNumber = block.Number
}

// Setup SafeL2Data
var safeL2Data catalyst.SafeL2Data
safeL2Data.Number = block.Number
safeL2Data.GasLimit = block.GasLimit
safeL2Data.BaseFee = block.BaseFee
safeL2Data.Timestamp = block.Timestamp
// TODO coinbase
fmt.Println(coinbase)

// Handle zero BaseFee case
if block.BaseFee != nil && block.BaseFee.Cmp(big.NewInt(0)) == 0 {
safeL2Data.BaseFee = nil
}

// Validate transaction numbers
if block.txsNum < block.l1MsgNum {
return fmt.Errorf("txsNum must be or equal to or greater than l1MsgNum,txsNum:%v,l1MsgNum:%v", block.txsNum, block.l1MsgNum)
}
var txs []*eth.Transaction
var err error
if len(batch.Sidecar.Blobs) != 0 {
txs, err = tq.dequeue(int(block.txsNum) - int(block.l1MsgNum))
if err != nil {
return fmt.Errorf("decode txsPayload error:%v", err)
}
return fmt.Errorf("txsNum must be greater than or equal to l1MsgNum, txsNum: %v, l1MsgNum: %v",
block.txsNum, block.l1MsgNum)
}
txsNum += uint64(block.txsNum)
l1MsgNum += uint64(block.l1MsgNum)
// l1 transactions will be inserted later in front of L2 transactions
safeL2Data.Transactions = encodeTransactions(txs)
block.SafeL2Data = &safeL2Data

block.SafeL2Data = &safeL2Data
blockContexts[i] = &block
}

// Read transaction data
txsData, err := io.ReadAll(reader)
if err != nil {
return fmt.Errorf("read transaction data error: %s", err.Error())
}

// Decode transactions
data, err := types.DecodeTxsFromBytes(txsData)
if err != nil {
return fmt.Errorf("decode transactions error: %v", err)
}

// Process transactions
tq.enqueue(data)

for i := 0; i < int(blockCount); i++ {
// Skip if index is out of bounds
if i >= len(blockContexts) {
return fmt.Errorf("block context index out of bounds: %d >= %d", i, len(blockContexts))
}

txCount := int(blockContexts[i].txsNum) - int(blockContexts[i].l1MsgNum)
txs, err := tq.dequeue(txCount)
if err != nil {
return fmt.Errorf("decode transaction payload error: %v", err)
}

txsNum += uint64(blockContexts[i].txsNum)
// l1 transactions will be inserted later in front of L2 transactions
blockContexts[i].SafeL2Data.Transactions = encodeTransactions(txs)
}

bi.txNum += txsNum
bi.blockContexts = blockContexts

return nil
}

Expand Down
5 changes: 5 additions & 0 deletions node/derivation/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ type Config struct {
MetricsPort uint64 `json:"metrics_port"`
MetricsHostname string `json:"metrics_hostname"`
MetricsServerEnable bool `json:"metrics_server_enable"`
Morph204Time uint64 `json:"upgrade_time"`
}

func DefaultConfig() *Config {
Expand Down Expand Up @@ -91,6 +92,10 @@ func (c *Config) SetCliContext(ctx *cli.Context) error {
c.BaseHeight = ctx.GlobalUint64(flags.DerivationBaseHeight.Name)
}

if ctx.GlobalIsSet(flags.Morph204Time.Name) {
c.Morph204Time = ctx.GlobalUint64(flags.Morph204Time.Name)
}

if ctx.GlobalIsSet(flags.DerivationPollInterval.Name) {
c.PollInterval = ctx.GlobalDuration(flags.DerivationPollInterval.Name)
if c.PollInterval == 0 {
Expand Down
Loading
Loading