diff --git a/encoding/codecv4.go b/encoding/codecv4.go index 4d51fe5..fb0cc64 100644 --- a/encoding/codecv4.go +++ b/encoding/codecv4.go @@ -20,10 +20,14 @@ import ( type DACodecV4 struct { DACodecV3 + forcedVersion *CodecVersion } // Version returns the codec version. func (d *DACodecV4) Version() CodecVersion { + if d.forcedVersion != nil { + return *d.forcedVersion + } return CodecV4 } @@ -90,7 +94,7 @@ func (d *DACodecV4) NewDABatch(batch *Batch) (DABatch, error) { l1MessagePopped := totalL1MessagePoppedAfter - batch.TotalL1MessagePoppedBefore return newDABatchV3( - CodecV4, // version + d.Version(), // version batch.Index, // batchIndex l1MessagePopped, // l1MessagePopped totalL1MessagePoppedAfter, // totalL1MessagePopped @@ -112,8 +116,8 @@ func (d *DACodecV4) NewDABatchFromBytes(data []byte) (DABatch, error) { return nil, fmt.Errorf("invalid data length for DABatch, expected %d bytes but got %d", daBatchV3EncodedLength, len(data)) } - if CodecVersion(data[daBatchOffsetVersion]) != CodecV4 { - return nil, fmt.Errorf("codec version mismatch: expected %d but found %d", CodecV4, data[daBatchOffsetVersion]) + if CodecVersion(data[daBatchOffsetVersion]) != d.Version() { + return nil, fmt.Errorf("codec version mismatch: expected %d but found %d", d.Version(), data[daBatchOffsetVersion]) } return newDABatchV3WithProof( diff --git a/encoding/codecv5.go b/encoding/codecv5.go new file mode 100644 index 0000000..91e2a59 --- /dev/null +++ b/encoding/codecv5.go @@ -0,0 +1,19 @@ +package encoding + +type DACodecV5 struct { + DACodecV4 +} + +func NewDACodecV5() *DACodecV5 { + v := CodecV5 + return &DACodecV5{ + DACodecV4: DACodecV4{ + forcedVersion: &v, + }, + } +} + +// MaxNumChunksPerBatch returns the maximum number of chunks per batch. +func (d *DACodecV5) MaxNumChunksPerBatch() int { + return 1 +} diff --git a/encoding/codecv6.go b/encoding/codecv6.go new file mode 100644 index 0000000..819752c --- /dev/null +++ b/encoding/codecv6.go @@ -0,0 +1,14 @@ +package encoding + +type DACodecV6 struct { + DACodecV4 +} + +func NewDACodecV6() *DACodecV6 { + v := CodecV6 + return &DACodecV6{ + DACodecV4: DACodecV4{ + forcedVersion: &v, + }, + } +} diff --git a/encoding/da.go b/encoding/da.go index 480679d..8221a23 100644 --- a/encoding/da.go +++ b/encoding/da.go @@ -5,6 +5,7 @@ import ( "encoding/binary" "fmt" "math/big" + "slices" "github.com/klauspost/compress/zstd" @@ -226,6 +227,15 @@ func (c *Chunk) CrcMax() (uint64, error) { // Map sub-circuit name to row count crc := make(map[string]uint64) + // if no blocks have row consumption, this is an euclid chunk + isEuclidChunk := slices.IndexFunc(c.Blocks, func(block *Block) bool { + return block.RowConsumption != nil + }) == -1 + + if isEuclidChunk { + return 0, nil + } + // Iterate over blocks, accumulate row consumption for _, block := range c.Blocks { if block.RowConsumption == nil { @@ -633,8 +643,10 @@ func GetHardforkName(config *params.ChainConfig, blockHeight, blockTimestamp uin return "curie" } else if !config.IsDarwinV2(blockTimestamp) { return "darwin" - } else { + } else if !config.IsEuclid(blockTimestamp) { return "darwinV2" + } else { + return "euclid" } } @@ -649,8 +661,11 @@ func GetCodecVersion(config *params.ChainConfig, blockHeight, blockTimestamp uin return CodecV2 } else if !config.IsDarwinV2(blockTimestamp) { return CodecV3 - } else { + } else if !config.IsEuclid(blockTimestamp) { return CodecV4 + } else { + // V5 is skipped, because it is only used for the special Euclid transition batch that we handle explicitly + return CodecV6 } } @@ -679,7 +694,7 @@ func GetChunkEnableCompression(codecVersion CodecVersion, chunk *Chunk) (bool, e return false, nil case CodecV2, CodecV3: return true, nil - case CodecV4: + case CodecV4, CodecV5, CodecV6: return CheckChunkCompressedDataCompatibility(chunk, codecVersion) default: return false, fmt.Errorf("unsupported codec version: %v", codecVersion) @@ -693,7 +708,7 @@ func GetBatchEnableCompression(codecVersion CodecVersion, batch *Batch) (bool, e return false, nil case CodecV2, CodecV3: return true, nil - case CodecV4: + case CodecV4, CodecV5, CodecV6: return CheckBatchCompressedDataCompatibility(batch, codecVersion) default: return false, fmt.Errorf("unsupported codec version: %v", codecVersion) diff --git a/encoding/da_test.go b/encoding/da_test.go index dbfbaf1..f301ed0 100644 --- a/encoding/da_test.go +++ b/encoding/da_test.go @@ -78,6 +78,13 @@ func TestUtilFunctions(t *testing.T) { assert.Equal(t, uint64(5), chunk3.NumTransactions()) assert.Equal(t, uint64(240000), chunk3.TotalGasUsed()) + // euclid chunk + chunk3.Blocks[0].RowConsumption = nil + chunk3.Blocks[1].RowConsumption = nil + crc3Max, err = chunk3.CrcMax() + assert.NoError(t, err) + assert.Equal(t, uint64(0), crc3Max) + // Test Batch methods assert.Equal(t, block6.Header.Root, batch.StateRoot()) assert.Equal(t, block6.WithdrawRoot, batch.WithdrawRoot()) diff --git a/encoding/interfaces.go b/encoding/interfaces.go index 6461a30..605040a 100644 --- a/encoding/interfaces.go +++ b/encoding/interfaces.go @@ -76,6 +76,8 @@ const ( CodecV2 CodecV3 CodecV4 + CodecV5 + CodecV6 ) // CodecFromVersion returns the appropriate codec for the given version. @@ -91,6 +93,10 @@ func CodecFromVersion(version CodecVersion) (Codec, error) { return &DACodecV3{}, nil case CodecV4: return &DACodecV4{}, nil + case CodecV5: + return NewDACodecV5(), nil + case CodecV6: + return NewDACodecV6(), nil default: return nil, fmt.Errorf("unsupported codec version: %v", version) } @@ -98,7 +104,10 @@ func CodecFromVersion(version CodecVersion) (Codec, error) { // CodecFromConfig determines and returns the appropriate codec based on chain configuration, block number, and timestamp. func CodecFromConfig(chainCfg *params.ChainConfig, startBlockNumber *big.Int, startBlockTimestamp uint64) Codec { - if chainCfg.IsDarwinV2(startBlockTimestamp) { + if chainCfg.IsEuclid(startBlockTimestamp) { + // V5 is skipped, because it is only used for the special Euclid transition batch that we handle explicitly + return NewDACodecV6() + } else if chainCfg.IsDarwinV2(startBlockTimestamp) { return &DACodecV4{} } else if chainCfg.IsDarwin(startBlockTimestamp) { return &DACodecV3{} diff --git a/go.mod b/go.mod index 80d5fc7..6e96704 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.21 require ( github.com/agiledragon/gomonkey/v2 v2.12.0 - github.com/scroll-tech/go-ethereum v1.10.14-0.20241210104312-bdf64cfb39dc + github.com/scroll-tech/go-ethereum v1.10.14-0.20250205135740-4bdf6d096c38 github.com/stretchr/testify v1.9.0 ) @@ -31,7 +31,7 @@ require ( github.com/tklauser/go-sysconf v0.3.12 // indirect github.com/tklauser/numcpus v0.6.1 // indirect github.com/yusufpapurcu/wmi v1.2.3 // indirect - golang.org/x/crypto v0.17.0 // indirect + golang.org/x/crypto v0.21.0 // indirect golang.org/x/sync v0.6.0 // indirect golang.org/x/sys v0.21.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index ba37004..1c6e0fe 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/VictoriaMetrics/fastcache v1.12.1 h1:i0mICQuojGDL3KblA7wUNlY5lOK6a4bwt3uRKnkZU40= -github.com/VictoriaMetrics/fastcache v1.12.1/go.mod h1:tX04vaqcNoQeGLD+ra5pU5sWkuxnzWhEzLwhP9w653o= +github.com/VictoriaMetrics/fastcache v1.12.2 h1:N0y9ASrJ0F6h0QaC3o6uJb3NIZ9VKLjCM7NQbSmF7WI= +github.com/VictoriaMetrics/fastcache v1.12.2/go.mod h1:AmC+Nzz1+3G2eCPapF6UcsnkThDcMsQicp4xDukwJYI= github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII= github.com/agiledragon/gomonkey/v2 v2.12.0 h1:ek0dYu9K1rSV+TgkW5LvNNPRWyDZVIxGMCFI6Pz9o38= github.com/agiledragon/gomonkey/v2 v2.12.0/go.mod h1:ap1AmDzcVOAz1YpeJ3TCzIgstoaWLA6jbbgxfB4w2iY= @@ -78,8 +78,8 @@ github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ= github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog= -github.com/scroll-tech/go-ethereum v1.10.14-0.20241210104312-bdf64cfb39dc h1:ofQxDFg5aW0ANJcEXt5RJy5lDWz8jdKwKcZhEqvDjx8= -github.com/scroll-tech/go-ethereum v1.10.14-0.20241210104312-bdf64cfb39dc/go.mod h1:xRDJvaNUe7lCU2fB+AqyS7gahar+dfJPrUJplfXF4dw= +github.com/scroll-tech/go-ethereum v1.10.14-0.20250205135740-4bdf6d096c38 h1:IKkevP42IQx8DQvtVq9WOmZDQrto59CGdEheXPf20HA= +github.com/scroll-tech/go-ethereum v1.10.14-0.20250205135740-4bdf6d096c38/go.mod h1:Ik3OBLl7cJxPC+CFyCBYNXBPek4wpdzkWehn/y5qLM8= github.com/scroll-tech/zktrie v0.8.4 h1:UagmnZ4Z3ITCk+aUq9NQZJNAwnWl4gSxsLb2Nl7IgRE= github.com/scroll-tech/zktrie v0.8.4/go.mod h1:XvNo7vAk8yxNyTjBDj5WIiFzYW4bx/gJ78+NK6Zn6Uk= github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI= @@ -100,8 +100,8 @@ github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFi github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20170930174604-9419663f5a44/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=