package codecv1

import (
	"encoding/hex"
	"encoding/json"
	"os"
	"strings"
	"testing"

	"scroll-tech/common/types/encoding"
	"scroll-tech/common/types/encoding/codecv0"

	"github.com/scroll-tech/go-ethereum/common"
	"github.com/scroll-tech/go-ethereum/core/types"
	"github.com/scroll-tech/go-ethereum/crypto/kzg4844"
	"github.com/stretchr/testify/assert"
)

func TestCodecV1BlockEncode(t *testing.T) {
	block := &DABlock{}
	encoded := hex.EncodeToString(block.Encode())
	assert.Equal(t, "000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", encoded)

	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	block, err := NewDABlock(trace2, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(block.Encode())
	assert.Equal(t, "00000000000000020000000063807b2a0000000000000000000000000000000000000000000000000000000000001de9000355418d1e818400020000", encoded)

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	block, err = NewDABlock(trace3, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(block.Encode())
	assert.Equal(t, "00000000000000030000000063807b2d0000000000000000000000000000000000000000000000000000000000001a2c0003546c3cbb39e500010000", encoded)

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	block, err = NewDABlock(trace4, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(block.Encode())
	assert.Equal(t, "000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a1200000c000b", encoded)

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	block, err = NewDABlock(trace5, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(block.Encode())
	assert.Equal(t, "000000000000001100000000646b6ed0000000000000000000000000000000000000000000000000000000000000000000000000007a1200002a002a", encoded)

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	block, err = NewDABlock(trace6, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(block.Encode())
	assert.Equal(t, "000000000000001100000000646b6ed0000000000000000000000000000000000000000000000000000000000000000000000000007a1200000a000a", encoded)

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	block, err = NewDABlock(trace7, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(block.Encode())
	assert.Equal(t, "000000000000001100000000646b6ed0000000000000000000000000000000000000000000000000000000000000000000000000007a120001010101", encoded)

	// sanity check: v0 and v1 block encodings are identical
	for _, trace := range []*encoding.Block{trace2, trace3, trace4, trace5, trace6, trace7} {
		blockv0, err := codecv0.NewDABlock(trace, 0)
		assert.NoError(t, err)
		encodedv0 := hex.EncodeToString(blockv0.Encode())

		blockv1, err := NewDABlock(trace, 0)
		assert.NoError(t, err)
		encodedv1 := hex.EncodeToString(blockv1.Encode())

		assert.Equal(t, encodedv0, encodedv1)
	}
}

func TestCodecV1ChunkEncode(t *testing.T) {
	// chunk with a single empty block
	block := DABlock{}
	chunk := &DAChunk{Blocks: []*DABlock{&block}, Transactions: [][]*types.TransactionData{nil}}
	encoded := hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", encoded)

	// transactions are not part of the encoding
	chunk.Transactions[0] = append(chunk.Transactions[0], &types.TransactionData{Type: types.L1MessageTxType}, &types.TransactionData{Type: types.DynamicFeeTxType})
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", encoded)

	trace := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	originalChunk := &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err := NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "0100000000000000020000000063807b2a0000000000000000000000000000000000000000000000000000000000001de9000355418d1e818400020000", encoded)

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "0100000000000000030000000063807b2d0000000000000000000000000000000000000000000000000000000000001a2c0003546c3cbb39e500010000", encoded)

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "01000000000000000d00000000646b6e13000000000000000000000000000000000000000000000000000000000000000000000000007a1200000c000b", encoded)

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "01000000000000001100000000646b6ed0000000000000000000000000000000000000000000000000000000000000000000000000007a1200002a002a", encoded)

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "01000000000000001100000000646b6ed0000000000000000000000000000000000000000000000000000000000000000000000000007a1200000a000a", encoded)

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(chunk.Encode())
	assert.Equal(t, "01000000000000001100000000646b6ed0000000000000000000000000000000000000000000000000000000000000000000000000007a120001010101", encoded)
}

func TestCodecV1ChunkHash(t *testing.T) {
	// chunk with a single empty block
	block := DABlock{}
	chunk := &DAChunk{Blocks: []*DABlock{&block}, Transactions: [][]*types.TransactionData{nil}}
	hash, err := chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0x7cdb9d7f02ea58dfeb797ed6b4f7ea68846e4f2b0e30ed1535fc98b60c4ec809", hash.Hex())

	// L1 transactions are part of the hash
	chunk.Transactions[0] = append(chunk.Transactions[0], &types.TransactionData{Type: types.L1MessageTxType, TxHash: "0x0000000000000000000000000000000000000000000000000000000000000000"})
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0xdcb42a70c54293e75a19dd1303d167822182d78b361dd7504758c35e516871b2", hash.Hex())

	// L2 transactions are not part of the hash
	chunk.Transactions[0] = append(chunk.Transactions[0], &types.TransactionData{Type: types.DynamicFeeTxType, TxHash: "0x0000000000000000000000000000000000000000000000000000000000000000"})
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0xdcb42a70c54293e75a19dd1303d167822182d78b361dd7504758c35e516871b2", hash.Hex())

	// numL1Messages are not part of the hash
	chunk.Blocks[0].NumL1Messages = 1
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0xdcb42a70c54293e75a19dd1303d167822182d78b361dd7504758c35e516871b2", hash.Hex())

	// invalid hash
	chunk.Transactions[0] = append(chunk.Transactions[0], &types.TransactionData{Type: types.L1MessageTxType, TxHash: "0xg"})
	_, err = chunk.Hash()
	assert.Error(t, err)

	trace := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	originalChunk := &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0x820f25d806ddea0ccdbfa463ee480da5b6ea3906e8a658417fb5417d0f837f5c", hash.Hex())

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0x4620b3900e8454133448b677cbb2054c5dd61d467d7ebf752bfb12cffff90f40", hash.Hex())

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0x059c6451e83012b405c7e1a38818369012a4a1c87d7d699366eac946d0410d73", hash.Hex())

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0x854fc3136f47ce482ec85ee3325adfa16a1a1d60126e1c119eaaf0c3a9e90f8e", hash.Hex())

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0x2aa220ca7bd1368e59e8053eb3831e30854aa2ec8bd3af65cee350c1c0718ba6", hash.Hex())

	trace = readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	originalChunk = &encoding.Chunk{Blocks: []*encoding.Block{trace}}
	chunk, err = NewDAChunk(originalChunk, 0)
	assert.NoError(t, err)
	hash, err = chunk.Hash()
	assert.NoError(t, err)
	assert.Equal(t, "0xb65521bea7daff75838de07951c3c055966750fb5a270fead5e0e727c32455c3", hash.Hex())
}

func TestCodecV1BatchEncode(t *testing.T) {
	// empty batch
	batch := &DABatch{Version: CodecV1Version}
	encoded := hex.EncodeToString(batch.Encode())
	assert.Equal(t, "01000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", encoded)

	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "010000000000000000000000000000000000000000000000009f81f6879f121da5b7a37535cdb21b3d53099266de57b1fdf603ce32100ed54101af944924715b48be6ce3c35aef7500a50e909265599bd2b3e544ac59fc75530000000000000000000000000000000000000000000000000000000000000000", encoded)

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "01000000000000000000000000000000000000000000000000d46d19f6d48083dc7905a68e6a20ea6a8fbcd445d56b549b324a8485b5b574a6010c54fa675ed1b78f269827177019b0814a4ac4d269c68037e2c41cf08f94110000000000000000000000000000000000000000000000000000000000000000", encoded)

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "010000000000000000000000000000000b000000000000000bcaece1705bf2ce5e94154469d910ffe8d102419c5eb3152c0c6d237cf35c885f01ea66c4de196d36e2c3a5d7c0045100b9e46ef65be8f7a921ef20e6f2e99ebd000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003ff", encoded)

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "010000000000000000000000000000002a000000000000002a93255aa24dd468c5645f1e6901b8131a7a78a0eeb2a17cbb09ba64688a8de6b401a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001fffffffff", encoded)

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "010000000000000000000000000000000a000000000000000ac7bcc8da943dd83404e84d9ce7e894ab97ce4829df4eb51ebbbe13c90b5a3f4d01a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a6000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001dd", encoded)

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "01000000000000000000000000000001010000000000000101899a411a3309c6491701b7b955c7b1115ac015414bbb71b59a0ca561668d520801a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a60000000000000000000000000000000000000000000000000000000000000000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0000000000000000000000000000000000000000000000000000000000000000", encoded)

	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk2, chunk3, chunk4, chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "010000000000000000000000000000002a000000000000002ae7740182b0948139505b6b296d0c6c6f7717708323e6e687917acad823b559d8014ae5927a983081a8bcdbcce19e926c9e4c56e2dc89c91c32c034b875b8a1ca00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffbff", encoded)

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}}
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = hex.EncodeToString(batch.Encode())
	assert.Equal(t, "010000000000000000000000000000002a000000000000002a9b0f37c563d27d9717ab16d47075df996c54fe110130df6b11bfd7230e13476701b63f87bdd2caa8d43500d47ee59204f61af95339483c62ff436c6beabf47bf00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001ffffffbff", encoded)
}

func TestCodecV1BatchHash(t *testing.T) {
	// empty batch
	batch := &DABatch{Version: CodecV1Version}
	assert.Equal(t, "0x4b6fe410f63051f6e93532087b42ece79fb7b966e2ba5845e6cd1c091f27e564", batch.Hash().Hex())

	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xd557b02638c0385d5124f7fc188a025b33f8819b7f78c000751404997148ab8b", batch.Hash().Hex())

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xf13c7e249d00941c59fe4cd970241bbd6753eede8e043c438165674031792b3b", batch.Hash().Hex())

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xb64208f07fab641f7ebf831686d05ad667da0c7bfabcbd9c878cc22cbc8032fd", batch.Hash().Hex())

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0x4f7426d164e885574a661838406083f5292b0a1bc6dc20c51129eed0723b8a27", batch.Hash().Hex())

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xfce89ec2aed85cebeb20eea722e3ae4ec622bff49218dbe249a2d358e2e85451", batch.Hash().Hex())

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0x8fc063179b709bab338674278bb7b70dce2879a4e11ea857b3a202fb3313559f", batch.Hash().Hex())

	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk2, chunk3, chunk4, chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xf1c94cdf45967bc60bfccd599edd8cb07fd0201f41ab068637834f86140f62bf", batch.Hash().Hex())

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}}
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xfef0b56bd889529e3a1d884c88dd1c867e084fdc1369496907be8f865f43f0e0", batch.Hash().Hex())
}

func TestCodecV1BatchDataHash(t *testing.T) {
	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0x9f81f6879f121da5b7a37535cdb21b3d53099266de57b1fdf603ce32100ed541", batch.DataHash.Hex())

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xd46d19f6d48083dc7905a68e6a20ea6a8fbcd445d56b549b324a8485b5b574a6", batch.DataHash.Hex())

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xcaece1705bf2ce5e94154469d910ffe8d102419c5eb3152c0c6d237cf35c885f", batch.DataHash.Hex())

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0x93255aa24dd468c5645f1e6901b8131a7a78a0eeb2a17cbb09ba64688a8de6b4", batch.DataHash.Hex())

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xc7bcc8da943dd83404e84d9ce7e894ab97ce4829df4eb51ebbbe13c90b5a3f4d", batch.DataHash.Hex())

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0x899a411a3309c6491701b7b955c7b1115ac015414bbb71b59a0ca561668d5208", batch.DataHash.Hex())

	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk2, chunk3, chunk4, chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0xe7740182b0948139505b6b296d0c6c6f7717708323e6e687917acad823b559d8", batch.DataHash.Hex())

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}}
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0x9b0f37c563d27d9717ab16d47075df996c54fe110130df6b11bfd7230e134767", batch.DataHash.Hex())
}

func TestCodecV1BatchBlob(t *testing.T) {
	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded := strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t,
		// metadata
		"00"+"0001"+"000000e6"+"00000000"+"00000000"+"00000000"+"00000000"+"00000000"+"00000000"+"00"+"00"+"000000"+"00000000"+"00000000"+"00000000"+"00000000"+"00000000"+"00000000"+"00000000"+
			// tx payload
			"00f87180843b9aec2e8307a12094c0c4c8baea3f6acb49b6e1fb9e2adeceeacb000ca28a152d02c7e14af60000008083019ecea0ab07ae99c67aa78e7ba5cf670081e90cc32b219b1de102513d56548a41e86df514a034cbd19feacd73e8ce6400d00c4d1996b9b5243c578fd7f51bfaec288bbaf42a8bf87101843b9aec2e830007a1209401bae6bf68e9a03fb2bc0615b1bf0d69ce9411ed8a152d02c7e14a00f60000008083019ecea0f039985866d8256f10c1be4f7b2cace28d8f20bde2007e2604393eb095b7f77316a05a3e6e81065f2b4604bcec5bd4aba68483599600fc3f879380aac1c09c6eed32f1", encoded)
	assert.Equal(t, "0x01af944924715b48be6ce3c35aef7500a50e909265599bd2b3e544ac59fc7553", batch.BlobVersionedHash.Hex())

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t, " ", encoded)
	assert.Equal(t, "0x010c54fa675ed1b78f269827177019b0814a4ac4d269c68037e2c41cf08f9411", batch.BlobVersionedHash.Hex())

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t, "0000010000002000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000df0b80825dc0941a258d17bf244c4df02d40343a7626a9d321e10580808080008", encoded)
	assert.Equal(t, "0x01ea66c4de196d36e2c3a5d7c0045100b9e46ef65be8f7a921ef20e6f2e99ebd", batch.BlobVersionedHash.Hex())

	// this batch only contains L1 txs
	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t, "000001", encoded)
	assert.Equal(t, "0x01a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a6", batch.BlobVersionedHash.Hex())

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t, "000001", encoded)
	assert.Equal(t, "0x01a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a6", batch.BlobVersionedHash.Hex())

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t, "000001", encoded)
	assert.Equal(t, "0x01a327088bb2b13151449d8313c281d0006d12e8453e863637b746898b6ad5a6", batch.BlobVersionedHash.Hex())

	// 15 chunks
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t,
		// metadata
		"00"+"000f"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"00"+"00"+"0000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+"000000e6"+
			// tx payload
			" ", encoded)
	assert.Equal(t, "0x01521b20f341588dea5978efb00d7b077a986598a6001fc2e5859d77f3ffc284", batch.BlobVersionedHash.Hex())

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}}
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	encoded = strings.TrimRight(hex.EncodeToString(batch.blob[:]), "0")
	assert.Equal(t, " ", encoded)
	assert.Equal(t, "0x01b63f87bdd2caa8d43500d47ee59204f61af95339483c62ff436c6beabf47bf", batch.BlobVersionedHash.Hex())
}

func TestCodecV1BatchChallenge(t *testing.T) {
	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0d8e67f882c61159aa99b04ec4f6f3d90cb95cbfba6efd56cefc55ca15b290ef", hex.EncodeToString(batch.z[:]))

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "32da228f4945de828954675f9396debb169bbf336ba93f849a8fc7fee1bc9e58", hex.EncodeToString(batch.z[:]))

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "09a37ab43d41bcae3000c090a341e4661a8dc705b3c93d01b9eda3a0b3f8d4a8", hex.EncodeToString(batch.z[:]))

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925", hex.EncodeToString(batch.z[:]))

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925", hex.EncodeToString(batch.z[:]))

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925", hex.EncodeToString(batch.z[:]))

	// 15 chunks
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "55dac3baa818133cfdce0f97ddbb950e341399756d7b49bc34107dd65ecd3a4b", hex.EncodeToString(batch.z[:]))

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}}
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0b14dce4abfdeb3a69a341f7db6b1e16162c20826e6d964a829e20f671030cab", hex.EncodeToString(batch.z[:]))
}

func repeat(element byte, count int) string {
	result := make([]byte, 0, count)
	for i := 0; i < count; i++ {
		result = append(result, element)
	}
	return "0x" + common.Bytes2Hex(result)
}

func TestCodecV1BatchChallengeWithStandardTestCases(t *testing.T) {
	nRowsData := 126914

	for _, tc := range []struct {
		chunks    [][]string
		expectedz string
		expectedy string
	}{
		// single empty chunk
		{chunks: [][]string{{}}, expectedz: "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925", expectedy: "304817c2a9ec97b4cfdfc7a646f4bd5ac309e967465bb49059d397094e57cd08"},
		// single non-empty chunk
		{chunks: [][]string{{"0x010203"}}, expectedz: "1c1d4bd5153f877d799853080aba243f2c186dd6d6064eaefacfe715c92b6354", expectedy: "24e80ed99526b0d15ba46f7ec682f517576ddae68d5131e5d351f8bae06ea7d3"},
		// multiple empty chunks
		{chunks: [][]string{{}, {}}, expectedz: "152c9ccfcc2884f9891f7adce2de110cf9f85bfd0e21f0933ae0636390a84d41", expectedy: "5f6f532676e25b49e2eae77513fbeca173a300b434c0a5e24fa554b68e27d582"},
		// multiple non-empty chunks
		{chunks: [][]string{{"0x010203"}, {"0x070809"}}, expectedz: "62100f5381179ea7db7aa8fdedb0f7fc7b82730b75432d50ab41f80aeebe45a3", expectedy: "5b1f6e7a54907ddc06871853cf1f5d53bf2de0df7b61d0df84bc2c3fb80320cd"},
		// empty chunk followed by non-empty chunk
		{chunks: [][]string{{}, {"0x010203"}}, expectedz: "2d94d241c4a2a8d8f02845ca40cfba344f3b42384af2045a75c82e725a184232", expectedy: "302416c177e9e7fe40c3bc4315066c117e27d246b0a33ef68cdda6dd333c485c"},
		// non-empty chunk followed by empty chunk
		{chunks: [][]string{{"0x070809"}, {}}, expectedz: "7227567e3b1dbacb48a32bb85e4e99f73e4bd5620ea8cd4f5ac00a364c86af9c", expectedy: "2eb3dfd28362f35f562f779e749a555d2f1f87ddc716e95f04133d25189a391c"},
		// max number of chunks all empty
		{chunks: [][]string{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}}, expectedz: "1128ac3e22ced6af85be4335e0d03a266946a7cade8047e7fc59d6c8be642321", expectedy: "2d9b16422ce17f328fd00c99349768f0cb0c8648115eb3bd9b7864617ba88059"},
		// max number of chunks all non-empty
		{chunks: [][]string{{"0x0a"}, {"0x0a0b"}, {"0x0a0b0c"}, {"0x0a0b0c0d"}, {"0x0a0b0c0d0e"}, {"0x0a0b0c0d0e0f"}, {"0x0a0b0c0d0e0f10"}, {"0x0a0b0c0d0e0f1011"}, {"0x0a0b0c0d0e0f101112"}, {"0x0a0b0c0d0e0f10111213"}, {"0x0a0b0c0d0e0f1011121314"}, {"0x0a0b0c0d0e0f101112131415"}, {"0x0a0b0c0d0e0f10111213141516"}, {"0x0a0b0c0d0e0f1011121314151617"}, {"0x0a0b0c0d0e0f101112131415161718"}}, expectedz: "1a4025a3d74e70b511007dd55a2e252478c48054c6383285e8a176f33d99853b", expectedy: "12071ac2571c11220432a27b8be549392892e9baf4c654748ca206def3843940"},
		// single chunk blob full
		{chunks: [][]string{{repeat(123, nRowsData)}}, expectedz: "72714cc4a0ca75cee2d543b1f958e3d3dd59ac7df0d9d5617d8117b65295a5f2", expectedy: "4ebb690362bcbc42321309c210c99f2ebdb53b3fcf7cf3b17b78f6cfd1203ed3"},
		// multiple chunks blob full
		{chunks: [][]string{{repeat(123, 1111)}, {repeat(231, nRowsData-1111)}}, expectedz: "70eb5b4db503e59413238eef451871c5d12f2bb96c8b96ceca012f4ca0114727", expectedy: "568d0aaf280ec83f9c81ed2d80ecbdf199bd72dafb8a350007d37ea82997e455"},
		// max number of chunks only last one non-empty not full blob
		{chunks: [][]string{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {repeat(132, nRowsData-1111)}}, expectedz: "03db68ae16ee88489d52db19e6111b25630c5f23ad7cd14530aacf0cd231d476", expectedy: "24527d0b0e93b3dec0060c7b128975a8088b3104d3a297dc807ab43862a77a1a"},
		// max number of chunks only last one non-empty full blob
		{chunks: [][]string{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {}, {repeat(132, nRowsData)}}, expectedz: "677670193f73db499cede572bcb55677f0d2f13d690f9a820bd00bf584c3c241", expectedy: "1d85677f172dbdf4ad3094a17deeb1df4d7d2b7f35ecea44aebffa757811a268"},
		// max number of chunks but last is empty
		{chunks: [][]string{{repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {repeat(111, 100)}, {}}, expectedz: "22935042dfe7df771b02c1f5cababfe508869e8f6339dabe25a8a32e37728bb0", expectedy: "48ca66fb5a094401728c3a6a517ffbd72c4d4d9a8c907e2d2f1320812f4d856f"},
	} {
		chunks := []*encoding.Chunk{}

		for _, c := range tc.chunks {
			block := &encoding.Block{Transactions: []*types.TransactionData{}}

			for _, data := range c {
				tx := &types.TransactionData{Type: 0xff, Data: data}
				block.Transactions = append(block.Transactions, tx)
			}

			chunk := &encoding.Chunk{Blocks: []*encoding.Block{block}}
			chunks = append(chunks, chunk)
		}

		b, _, z, err := constructBlobPayload(chunks)
		assert.NoError(t, err)
		actualZ := hex.EncodeToString(z[:])
		assert.Equal(t, tc.expectedz, actualZ)

		_, y, err := kzg4844.ComputeProof(*b, *z)
		assert.NoError(t, err)
		actualY := hex.EncodeToString(y[:])
		assert.Equal(t, tc.expectedy, actualY)

	}
}

func TestCodecV1BatchBlobDataProof(t *testing.T) {
	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err := batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "0d8e67f882c61159aa99b04ec4f6f3d90cb95cbfba6efd56cefc55ca15b290ef423dc493f1dd7c9fbecdffa021ca4649b13e8d72231487034ec6b27e155ecfd7b44a38af1f9a6c70cd3ccfbf71968f447aa566bbafb0bbc566fc9eeb42973484802635a1bbd8305d34a46693331bf607b38542ec811c92d86ff6f3319de06ee60c42655278ccf874f3615f450de730895276828b73db03c553b0bc7e5474a5e0", hex.EncodeToString(verifyData))

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "32da228f4945de828954675f9396debb169bbf336ba93f849a8fc7fee1bc9e5821975f318babe50be728f9b52754d5ce2caa2ba82ba35b5888af1c5f28d23206b8aab265dc352e352807a298f7bb99d432c7cd543e63158cbdb8fbf99f3182a71af35ccbed2693c5e0bc5be38d565e868e0c6fe7bd39baa5ee6339cd334a18af7c680d24e825262499e83b31633b13a9ee89813fae8441630c82bc9dce3f1e07", hex.EncodeToString(verifyData))

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "09a37ab43d41bcae3000c090a341e4661a8dc705b3c93d01b9eda3a0b3f8d4a8088a01e54e3565d2e91ce6afbadf479330847d9106737875303ce17f17c48722afd4e1c55a17dbdf8390b5736158afe238d82f8b696669ba47015fcdfd4d1becd0ff7a47f8f379a4ac8d1741e2d67624aee03a0f7cdb7807bc7e0b9fb20bc299af2a35e38cda816708b40f2f18db491e14a0f5d9cfe2f4c12e4ca1a219484f17", hex.EncodeToString(verifyData))

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925304817c2a9ec97b4cfdfc7a646f4bd5ac309e967465bb49059d397094e57cd088f26f349339c68b33ce856aa2c05b8f89e7c23db0c00817550679998efcbd8f2464f9e1ea6c3172b0b750603d1e4ea38979341a25ec6b613f9f32b23fc0e1a11342bc84d4af0705c666e7813de790d0e63b0a9bc56dc484590728aaaafa6b7a4", hex.EncodeToString(verifyData))

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925304817c2a9ec97b4cfdfc7a646f4bd5ac309e967465bb49059d397094e57cd088f26f349339c68b33ce856aa2c05b8f89e7c23db0c00817550679998efcbd8f2464f9e1ea6c3172b0b750603d1e4ea38979341a25ec6b613f9f32b23fc0e1a11342bc84d4af0705c666e7813de790d0e63b0a9bc56dc484590728aaaafa6b7a4", hex.EncodeToString(verifyData))

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "17c71700d949f82963d3bd6af3994ecc383a3d58007f2f27702758fefa34a925304817c2a9ec97b4cfdfc7a646f4bd5ac309e967465bb49059d397094e57cd088f26f349339c68b33ce856aa2c05b8f89e7c23db0c00817550679998efcbd8f2464f9e1ea6c3172b0b750603d1e4ea38979341a25ec6b613f9f32b23fc0e1a11342bc84d4af0705c666e7813de790d0e63b0a9bc56dc484590728aaaafa6b7a4", hex.EncodeToString(verifyData))

	// 15 chunks
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2, chunk2}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "55dac3baa818133cfdce0f97ddbb950e341399756d7b49bc34107dd65ecd3a4b54d28f1479467d8b97fb99f5257d3e5d63a81cb2d60e3564fe6ec6066a311c119743324c70e20042de6480f115b215fbba3472a8b994303a99576c1244aa4aec22fdfe6c74ec728aa28a9eb3812bc932a0b603cc94be2007d4b3b17af06b4fb30caf0e574d5abcfc5654079e65154679afad75844396082a7200a4e82462aeed", hex.EncodeToString(verifyData))

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}}
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	verifyData, err = batch.BlobDataProof()
	assert.NoError(t, err)
	assert.Equal(t, "0b14dce4abfdeb3a69a341f7db6b1e16162c20826e6d964a829e20f671030cab35b73ddb4a78fc4a8540f1d8259512c46e606a701e7ef7742e38cc4562ef53b983bee97f95fbf2d789a8e0fb365c26e141d6a31e43403b4a469d1723128f6d5de5c54e913e143feede32d0af9b6fd6fda28e5610ca6b185d6ac30b53bd83d6366fccb1956daafa90ff6b504a966b119ebb45cb3f7085b7c1d622ee1ad27fcff9", hex.EncodeToString(verifyData))
}

func TestCodecV1BatchSkipBitmap(t *testing.T) {
	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	originalBatch := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch, err := NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 0, int(batch.L1MessagePopped))
	assert.Equal(t, 0, int(batch.TotalL1MessagePopped))

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 0, int(batch.L1MessagePopped))
	assert.Equal(t, 0, int(batch.TotalL1MessagePopped))

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "00000000000000000000000000000000000000000000000000000000000003ff", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 11, int(batch.L1MessagePopped)) // skip 10, include 1
	assert.Equal(t, 11, int(batch.TotalL1MessagePopped))

	trace5 := readBlockFromJSON(t, "../../../testdata/blockTrace_05.json")
	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk5}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0000000000000000000000000000000000000000000000000000001fffffffff", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 42, int(batch.L1MessagePopped)) // skip 37, include 5
	assert.Equal(t, 42, int(batch.TotalL1MessagePopped))

	originalBatch.TotalL1MessagePoppedBefore = 37
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 5, int(batch.L1MessagePopped)) // skip 37, include 5
	assert.Equal(t, 42, int(batch.TotalL1MessagePopped))

	trace6 := readBlockFromJSON(t, "../../../testdata/blockTrace_06.json")
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace6}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk6}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "00000000000000000000000000000000000000000000000000000000000001dd", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 10, int(batch.L1MessagePopped)) // skip 7, include 3
	assert.Equal(t, 10, int(batch.TotalL1MessagePopped))

	trace7 := readBlockFromJSON(t, "../../../testdata/blockTrace_07.json")
	chunk7 := &encoding.Chunk{Blocks: []*encoding.Block{trace7}}
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk7}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd0000000000000000000000000000000000000000000000000000000000000000", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 257, int(batch.L1MessagePopped)) // skip 255, include 2
	assert.Equal(t, 257, int(batch.TotalL1MessagePopped))

	originalBatch.TotalL1MessagePoppedBefore = 1
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 256, int(batch.L1MessagePopped)) // skip 254, include 2
	assert.Equal(t, 257, int(batch.TotalL1MessagePopped))

	chunk8 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3, trace4}} // queue index 10
	chunk9 := &encoding.Chunk{Blocks: []*encoding.Block{trace5}}                 // queue index 37-41
	originalBatch = &encoding.Batch{Chunks: []*encoding.Chunk{chunk8, chunk9}}
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0000000000000000000000000000000000000000000000000000001ffffffbff", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 42, int(batch.L1MessagePopped))
	assert.Equal(t, 42, int(batch.TotalL1MessagePopped))

	originalBatch.TotalL1MessagePoppedBefore = 10
	batch, err = NewDABatch(originalBatch)
	assert.NoError(t, err)
	assert.Equal(t, "0000000000000000000000000000000000000000000000000000000007fffffe", hex.EncodeToString(batch.SkippedL1MessageBitmap))
	assert.Equal(t, 32, int(batch.L1MessagePopped))
	assert.Equal(t, 42, int(batch.TotalL1MessagePopped))
}

func TestCodecV1ChunkAndBatchBlobSizeEstimation(t *testing.T) {
	trace2 := readBlockFromJSON(t, "../../../testdata/blockTrace_02.json")
	chunk2 := &encoding.Chunk{Blocks: []*encoding.Block{trace2}}
	chunk2BlobSize, err := EstimateChunkL1CommitBlobSize(chunk2)
	assert.NoError(t, err)
	assert.Equal(t, uint64(320), chunk2BlobSize)
	batch2 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk2}}
	batch2BlobSize, err := EstimateBatchL1CommitBlobSize(batch2)
	assert.NoError(t, err)
	assert.Equal(t, uint64(320), batch2BlobSize)

	trace3 := readBlockFromJSON(t, "../../../testdata/blockTrace_03.json")
	chunk3 := &encoding.Chunk{Blocks: []*encoding.Block{trace3}}
	chunk3BlobSize, err := EstimateChunkL1CommitBlobSize(chunk3)
	assert.NoError(t, err)
	assert.Equal(t, uint64(5952), chunk3BlobSize)
	batch3 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk3}}
	batch3BlobSize, err := EstimateBatchL1CommitBlobSize(batch3)
	assert.NoError(t, err)
	assert.Equal(t, uint64(5952), batch3BlobSize)

	trace4 := readBlockFromJSON(t, "../../../testdata/blockTrace_04.json")
	chunk4 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	chunk4BlobSize, err := EstimateChunkL1CommitBlobSize(chunk4)
	assert.NoError(t, err)
	assert.Equal(t, uint64(128), chunk4BlobSize)
	batch4 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk4}}
	batch4BlobSize, err := EstimateBatchL1CommitBlobSize(batch4)
	assert.NoError(t, err)
	assert.Equal(t, uint64(128), batch4BlobSize)

	chunk5 := &encoding.Chunk{Blocks: []*encoding.Block{trace2, trace3}}
	chunk5BlobSize, err := EstimateChunkL1CommitBlobSize(chunk5)
	assert.NoError(t, err)
	assert.Equal(t, uint64(6176), chunk5BlobSize)
	chunk6 := &encoding.Chunk{Blocks: []*encoding.Block{trace4}}
	chunk6BlobSize, err := EstimateChunkL1CommitBlobSize(chunk6)
	assert.NoError(t, err)
	assert.Equal(t, uint64(128), chunk6BlobSize)
	batch5 := &encoding.Batch{Chunks: []*encoding.Chunk{chunk5, chunk6}}
	batch5BlobSize, err := EstimateBatchL1CommitBlobSize(batch5)
	assert.NoError(t, err)
	assert.Equal(t, uint64(6208), batch5BlobSize)
}

func readBlockFromJSON(t *testing.T, filename string) *encoding.Block {
	data, err := os.ReadFile(filename)
	assert.NoError(t, err)

	block := &encoding.Block{}
	assert.NoError(t, json.Unmarshal(data, block))
	return block
}
