mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-28 07:36:44 +00:00
* feat(rollup): sync finalized batches from L1 * tweak * address comments * address comments * tweak * address comments * Update rollup/eventwatcher/eventwatcher.go Co-authored-by: Péter Garamvölgyi <peter@scroll.io> * address comments * address comments * address comments * add s.rollupSyncService.Stop() * add block chunk batch tests * fix goimports-lint * address comments * address comments * remove * add TestUnpackLog test * add decodeChunkRanges tests * add commit batch version check * fix goimport & golint * tweak * fixes * add TestRollupSyncServiceStartAndStop * add TestGetChunkRanges * address comments * add TestValidateBatch * add TestCalculateFinalizedBatchMeta * address comments * address comments * fix * address comments * address comments * fix * tweak log * fix * tweak logs * increase wait time * add --rollup.verify flag * add flag check in s.rollupSyncService.Stop() * bump version * refactor * tweak configs * tweak * refactor getLocalInfoForBatch * use syscall.Kill(os.Getpid(), syscall.SIGTERM) to shutdown * refactor decodeChunkBlockRanges * nit * address comments * address comments * add WithdrawRoot and StateRoot in FinalizedBatchMeta * address comments * address comments * add ctx.Err() check in retry * add configs in gen_config.go * bump version * fix goimport & golint * try to fix goimport * revert change * fix goimport & golint * tweak * bump version * add l2 block -> batch index mapping * bump version * add mainnet config * bump version * address comments * rename some vars * feat: add more detailed logs in crash case (#547) add more detailed logs in crash case * trigger ci * re-add batch finalization progress log * remove block number -> batch index mapping --------- Co-authored-by: Péter Garamvölgyi <peter@scroll.io> Co-authored-by: HAOYUatHZ <37070449+HAOYUatHZ@users.noreply.github.com>
123 lines
3.8 KiB
Go
123 lines
3.8 KiB
Go
package rollup_sync_service
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"fmt"
|
|
"math/big"
|
|
|
|
"github.com/scroll-tech/go-ethereum/common"
|
|
"github.com/scroll-tech/go-ethereum/core/types"
|
|
"github.com/scroll-tech/go-ethereum/crypto"
|
|
)
|
|
|
|
const batchHeaderVersion = 0
|
|
|
|
// BatchHeader contains batch header info to be committed.
|
|
type BatchHeader struct {
|
|
// Encoded in BatchHeaderV0Codec
|
|
version uint8
|
|
batchIndex uint64
|
|
l1MessagePopped uint64
|
|
totalL1MessagePopped uint64
|
|
dataHash common.Hash
|
|
parentBatchHash common.Hash
|
|
skippedL1MessageBitmap []byte
|
|
}
|
|
|
|
// NewBatchHeader creates a new BatchHeader
|
|
func NewBatchHeader(version uint8, batchIndex, totalL1MessagePoppedBefore uint64, parentBatchHash common.Hash, chunks []*Chunk) (*BatchHeader, error) {
|
|
// buffer for storing chunk hashes in order to compute the batch data hash
|
|
var dataBytes []byte
|
|
|
|
// skipped L1 message bitmap, an array of 256-bit bitmaps
|
|
var skippedBitmap []*big.Int
|
|
|
|
// the first queue index that belongs to this batch
|
|
baseIndex := totalL1MessagePoppedBefore
|
|
|
|
// the next queue index that we need to process
|
|
nextIndex := totalL1MessagePoppedBefore
|
|
|
|
for chunkID, chunk := range chunks {
|
|
// build data hash
|
|
totalL1MessagePoppedBeforeChunk := nextIndex
|
|
chunkHash, err := chunk.Hash(totalL1MessagePoppedBeforeChunk)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
dataBytes = append(dataBytes, chunkHash.Bytes()...)
|
|
|
|
// build skip bitmap
|
|
for blockID, block := range chunk.Blocks {
|
|
for _, tx := range block.Transactions {
|
|
if tx.Type != types.L1MessageTxType {
|
|
continue
|
|
}
|
|
currentIndex := tx.Nonce
|
|
|
|
if currentIndex < nextIndex {
|
|
return nil, fmt.Errorf("unexpected batch payload, expected queue index: %d, got: %d. Batch index: %d, chunk index in batch: %d, block index in chunk: %d, block hash: %v, transaction hash: %v", nextIndex, currentIndex, batchIndex, chunkID, blockID, block.Header.Hash(), tx.TxHash)
|
|
}
|
|
|
|
// mark skipped messages
|
|
for skippedIndex := nextIndex; skippedIndex < currentIndex; skippedIndex++ {
|
|
quo := int((skippedIndex - baseIndex) / 256)
|
|
rem := int((skippedIndex - baseIndex) % 256)
|
|
for len(skippedBitmap) <= quo {
|
|
bitmap := big.NewInt(0)
|
|
skippedBitmap = append(skippedBitmap, bitmap)
|
|
}
|
|
skippedBitmap[quo].SetBit(skippedBitmap[quo], rem, 1)
|
|
}
|
|
|
|
// process included message
|
|
quo := int((currentIndex - baseIndex) / 256)
|
|
for len(skippedBitmap) <= quo {
|
|
bitmap := big.NewInt(0)
|
|
skippedBitmap = append(skippedBitmap, bitmap)
|
|
}
|
|
|
|
nextIndex = currentIndex + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
// compute data hash
|
|
dataHash := crypto.Keccak256Hash(dataBytes)
|
|
|
|
// compute skipped bitmap
|
|
bitmapBytes := make([]byte, len(skippedBitmap)*32)
|
|
for ii, num := range skippedBitmap {
|
|
bytes := num.Bytes()
|
|
padding := 32 - len(bytes)
|
|
copy(bitmapBytes[32*ii+padding:], bytes)
|
|
}
|
|
|
|
return &BatchHeader{
|
|
version: version,
|
|
batchIndex: batchIndex,
|
|
l1MessagePopped: nextIndex - totalL1MessagePoppedBefore,
|
|
totalL1MessagePopped: nextIndex,
|
|
dataHash: dataHash,
|
|
parentBatchHash: parentBatchHash,
|
|
skippedL1MessageBitmap: bitmapBytes,
|
|
}, nil
|
|
}
|
|
|
|
// Encode encodes the BatchHeader into RollupV2 BatchHeaderV0Codec Encoding.
|
|
func (b *BatchHeader) Encode() []byte {
|
|
batchBytes := make([]byte, 89+len(b.skippedL1MessageBitmap))
|
|
batchBytes[0] = b.version
|
|
binary.BigEndian.PutUint64(batchBytes[1:], b.batchIndex)
|
|
binary.BigEndian.PutUint64(batchBytes[9:], b.l1MessagePopped)
|
|
binary.BigEndian.PutUint64(batchBytes[17:], b.totalL1MessagePopped)
|
|
copy(batchBytes[25:], b.dataHash[:])
|
|
copy(batchBytes[57:], b.parentBatchHash[:])
|
|
copy(batchBytes[89:], b.skippedL1MessageBitmap[:])
|
|
return batchBytes
|
|
}
|
|
|
|
// Hash calculates the hash of the batch header.
|
|
func (b *BatchHeader) Hash() common.Hash {
|
|
return crypto.Keccak256Hash(b.Encode())
|
|
}
|