Files
scroll/rollup/internal/utils/utils.go
colin 0578aab3ae feat: openvm euclid v2 (#1613)
Signed-off-by: noelwei <fan@scroll.io>
Co-authored-by: jonastheis <4181434+jonastheis@users.noreply.github.com>
Co-authored-by: Ömer Faruk Irmak <omerfirmak@gmail.com>
Co-authored-by: noelwei <fan@scroll.io>
Co-authored-by: Rohit Narurkar <rohit.narurkar@proton.me>
Co-authored-by: Péter Garamvölgyi <peter@scroll.io>
Co-authored-by: Morty <70688412+yiweichi@users.noreply.github.com>
Co-authored-by: omerfirmak <omerfirmak@users.noreply.github.com>
Co-authored-by: jonastheis <jonastheis@users.noreply.github.com>
Co-authored-by: georgehao <georgehao@users.noreply.github.com>
Co-authored-by: kunxian xia <xiakunxian130@gmail.com>
Co-authored-by: Morty <yiweichi1@gmail.com>
Co-authored-by: Velaciela <git.rover@outlook.com>
Co-authored-by: colinlyguo <colinlyguo@users.noreply.github.com>
2025-04-04 16:44:09 +08:00

232 lines
7.4 KiB
Go

package utils
import (
"fmt"
"time"
"github.com/scroll-tech/da-codec/encoding"
"github.com/scroll-tech/go-ethereum/common"
)
// ChunkMetrics indicates the metrics for proposing a chunk.
type ChunkMetrics struct {
NumBlocks uint64
TxNum uint64
L2Gas uint64
CrcMax uint64
FirstBlockTimestamp uint64
L1CommitCalldataSize uint64
L1CommitGas uint64
L1CommitBlobSize uint64
L1CommitUncompressedBatchBytesSize uint64
// timing metrics
EstimateGasTime time.Duration
EstimateCalldataSizeTime time.Duration
EstimateBlobSizeTime time.Duration
}
// CalculateChunkMetrics calculates chunk metrics.
func CalculateChunkMetrics(chunk *encoding.Chunk, codecVersion encoding.CodecVersion) (*ChunkMetrics, error) {
metrics := &ChunkMetrics{
TxNum: chunk.NumTransactions(),
NumBlocks: uint64(len(chunk.Blocks)),
FirstBlockTimestamp: chunk.Blocks[0].Header.Time,
}
// Get total L2 gas for chunk
for _, block := range chunk.Blocks {
metrics.L2Gas += block.Header.GasUsed
}
var err error
metrics.CrcMax, err = chunk.CrcMax()
if err != nil {
return nil, fmt.Errorf("failed to get crc max, version: %v, err: %w", codecVersion, err)
}
codec, err := encoding.CodecFromVersion(codecVersion)
if err != nil {
return nil, fmt.Errorf("failed to get codec from version: %v, err: %w", codecVersion, err)
}
metrics.EstimateGasTime, err = measureTime(func() error {
metrics.L1CommitGas, err = codec.EstimateChunkL1CommitGas(chunk)
return err
})
if err != nil {
return nil, fmt.Errorf("failed to estimate chunk L1 commit gas, version: %v, err: %w", codecVersion, err)
}
metrics.EstimateCalldataSizeTime, err = measureTime(func() error {
metrics.L1CommitCalldataSize, err = codec.EstimateChunkL1CommitCalldataSize(chunk)
return err
})
if err != nil {
return nil, fmt.Errorf("failed to estimate chunk L1 commit calldata size, version: %v, err: %w", codecVersion, err)
}
metrics.EstimateBlobSizeTime, err = measureTime(func() error {
metrics.L1CommitUncompressedBatchBytesSize, metrics.L1CommitBlobSize, err = codec.EstimateChunkL1CommitBatchSizeAndBlobSize(chunk)
return err
})
if err != nil {
return nil, fmt.Errorf("failed to estimate chunk L1 commit batch size and blob size, version: %v, err: %w", codecVersion, err)
}
return metrics, nil
}
// BatchMetrics indicates the metrics for proposing a batch.
type BatchMetrics struct {
NumChunks uint64
FirstBlockTimestamp uint64
L1CommitCalldataSize uint64
L1CommitGas uint64
L1CommitBlobSize uint64
L1CommitUncompressedBatchBytesSize uint64
// timing metrics
EstimateGasTime time.Duration
EstimateCalldataSizeTime time.Duration
EstimateBlobSizeTime time.Duration
}
// CalculateBatchMetrics calculates batch metrics.
func CalculateBatchMetrics(batch *encoding.Batch, codecVersion encoding.CodecVersion) (*BatchMetrics, error) {
metrics := &BatchMetrics{
NumChunks: uint64(len(batch.Chunks)),
FirstBlockTimestamp: batch.Chunks[0].Blocks[0].Header.Time,
}
codec, err := encoding.CodecFromVersion(codecVersion)
if err != nil {
return nil, fmt.Errorf("failed to get codec from version: %v, err: %w", codecVersion, err)
}
metrics.EstimateGasTime, err = measureTime(func() error {
metrics.L1CommitGas, err = codec.EstimateBatchL1CommitGas(batch)
return err
})
if err != nil {
return nil, fmt.Errorf("failed to estimate batch L1 commit gas, version: %v, err: %w", codecVersion, err)
}
metrics.EstimateCalldataSizeTime, err = measureTime(func() error {
metrics.L1CommitCalldataSize, err = codec.EstimateBatchL1CommitCalldataSize(batch)
return err
})
if err != nil {
return nil, fmt.Errorf("failed to estimate batch L1 commit calldata size, version: %v, err: %w", codecVersion, err)
}
metrics.EstimateBlobSizeTime, err = measureTime(func() error {
metrics.L1CommitUncompressedBatchBytesSize, metrics.L1CommitBlobSize, err = codec.EstimateBatchL1CommitBatchSizeAndBlobSize(batch)
return err
})
if err != nil {
return nil, fmt.Errorf("failed to estimate batch L1 commit batch size and blob size, version: %v, err: %w", codecVersion, err)
}
return metrics, nil
}
// GetChunkHash retrieves the hash of a chunk.
func GetChunkHash(chunk *encoding.Chunk, totalL1MessagePoppedBefore uint64, codecVersion encoding.CodecVersion) (common.Hash, error) {
codec, err := encoding.CodecFromVersion(codecVersion)
if err != nil {
return common.Hash{}, fmt.Errorf("failed to get codec from version: %v, err: %w", codecVersion, err)
}
daChunk, err := codec.NewDAChunk(chunk, totalL1MessagePoppedBefore)
if err != nil {
return common.Hash{}, fmt.Errorf("failed to create DA chunk, version: %v, err: %w", codecVersion, err)
}
chunkHash, err := daChunk.Hash()
if err != nil {
return common.Hash{}, fmt.Errorf("failed to get DA chunk hash, version: %v, err: %w", codecVersion, err)
}
return chunkHash, nil
}
// BatchMetadata represents the metadata of a batch.
type BatchMetadata struct {
BatchHash common.Hash
BatchDataHash common.Hash
BatchBlobDataProof []byte
BatchBytes []byte
StartChunkHash common.Hash
EndChunkHash common.Hash
BlobBytes []byte
ChallengeDigest common.Hash
}
// GetBatchMetadata retrieves the metadata of a batch.
func GetBatchMetadata(batch *encoding.Batch, codecVersion encoding.CodecVersion) (*BatchMetadata, error) {
codec, err := encoding.CodecFromVersion(codecVersion)
if err != nil {
return nil, fmt.Errorf("failed to get codec from version: %v, err: %w", codecVersion, err)
}
daBatch, err := codec.NewDABatch(batch)
if err != nil {
return nil, fmt.Errorf("failed to create DA batch, version: %v, err: %w", codecVersion, err)
}
batchMeta := &BatchMetadata{
BatchHash: daBatch.Hash(),
BatchDataHash: daBatch.DataHash(),
BatchBytes: daBatch.Encode(),
BlobBytes: daBatch.BlobBytes(),
ChallengeDigest: daBatch.ChallengeDigest(),
}
batchMeta.BatchBlobDataProof, err = daBatch.BlobDataProofForPointEvaluation()
if err != nil {
return nil, fmt.Errorf("failed to get blob data proof, version: %v, err: %w", codecVersion, err)
}
numChunks := len(batch.Chunks)
if numChunks == 0 {
return nil, fmt.Errorf("batch contains no chunks, version: %v, index: %v", codecVersion, batch.Index)
}
startDAChunk, err := codec.NewDAChunk(batch.Chunks[0], batch.TotalL1MessagePoppedBefore)
if err != nil {
return nil, fmt.Errorf("failed to create start DA chunk, version: %v, err: %w", codecVersion, err)
}
batchMeta.StartChunkHash, err = startDAChunk.Hash()
if err != nil {
return nil, fmt.Errorf("failed to get start DA chunk hash, version: %v, err: %w", codecVersion, err)
}
totalL1MessagePoppedBeforeEndDAChunk := batch.TotalL1MessagePoppedBefore
for i := 0; i < len(batch.Chunks)-1; i++ {
totalL1MessagePoppedBeforeEndDAChunk += batch.Chunks[i].NumL1Messages(totalL1MessagePoppedBeforeEndDAChunk)
}
endDAChunk, err := codec.NewDAChunk(batch.Chunks[numChunks-1], totalL1MessagePoppedBeforeEndDAChunk)
if err != nil {
return nil, fmt.Errorf("failed to create end DA chunk, version: %v, err: %w", codecVersion, err)
}
batchMeta.EndChunkHash, err = endDAChunk.Hash()
if err != nil {
return nil, fmt.Errorf("failed to get end DA chunk hash, version: %v, err: %w", codecVersion, err)
}
return batchMeta, nil
}
func measureTime(operation func() error) (time.Duration, error) {
start := time.Now()
err := operation()
return time.Since(start), err
}