span_batch_test.go 17.9 KB
Newer Older
1 2 3 4
package derive

import (
	"bytes"
5
	"math"
6 7 8 9
	"math/big"
	"math/rand"
	"testing"

10 11 12
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"

13 14 15
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/rlp"
16 17 18

	"github.com/ethereum-optimism/optimism/op-node/rollup"
	"github.com/ethereum-optimism/optimism/op-service/testutils"
19 20
)

21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
// initializedSpanBatch creates a new SpanBatch with given SingularBatches.
// It is used *only* in tests to create a SpanBatch with given SingularBatches as a convenience.
// It will also ignore any errors that occur during AppendSingularBatch.
// Tests should manually set the first bit of the originBits if needed using SetFirstOriginChangedBit
func initializedSpanBatch(singularBatches []*SingularBatch, genesisTimestamp uint64, chainID *big.Int) *SpanBatch {
	spanBatch := NewSpanBatch(genesisTimestamp, chainID)
	if len(singularBatches) == 0 {
		return spanBatch
	}
	for i := 0; i < len(singularBatches); i++ {
		if err := spanBatch.AppendSingularBatch(singularBatches[i], uint64(i)); err != nil {
			continue
		}
	}
	return spanBatch
}

// setFirstOriginChangedBit sets the first bit of the originBits to the given value
// used for testing when a Span Batch is made with InitializedSpanBatch, which doesn't have a sequence number
func (b *SpanBatch) setFirstOriginChangedBit(bit uint) {
	b.originBits.SetBit(b.originBits, 0, bit)
}

44 45 46 47 48 49 50 51 52
func TestSpanBatchForBatchInterface(t *testing.T) {
	rng := rand.New(rand.NewSource(0x5432177))
	chainID := big.NewInt(rng.Int63n(1000))

	singularBatches := RandomValidConsecutiveSingularBatches(rng, chainID)
	blockCount := len(singularBatches)
	safeL2Head := testutils.RandomL2BlockRef(rng)
	safeL2Head.Hash = common.BytesToHash(singularBatches[0].ParentHash[:])

53
	spanBatch := initializedSpanBatch(singularBatches, uint64(0), chainID)
54 55

	// check interface method implementations except logging
56 57 58 59 60
	require.Equal(t, SpanBatchType, spanBatch.GetBatchType())
	require.Equal(t, singularBatches[0].Timestamp, spanBatch.GetTimestamp())
	require.Equal(t, singularBatches[0].EpochNum, spanBatch.GetStartEpochNum())
	require.True(t, spanBatch.CheckOriginHash(singularBatches[blockCount-1].EpochHash))
	require.True(t, spanBatch.CheckParentHash(singularBatches[0].ParentHash))
61 62
}

63 64 65 66 67 68 69 70 71 72
func TestEmptySpanBatch(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556691))
	chainID := big.NewInt(rng.Int63n(1000))
	spanTxs, err := newSpanBatchTxs(nil, chainID)
	require.NoError(t, err)

	rawSpanBatch := RawSpanBatch{
		spanBatchPrefix: spanBatchPrefix{
			relTimestamp:  uint64(rng.Uint32()),
			l1OriginNum:   rng.Uint64(),
73 74
			parentCheck:   *(*[20]byte)(testutils.RandomData(rng, 20)),
			l1OriginCheck: *(*[20]byte)(testutils.RandomData(rng, 20)),
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
		},
		spanBatchPayload: spanBatchPayload{
			blockCount:    0,
			originBits:    big.NewInt(0),
			blockTxCounts: []uint64{},
			txs:           spanTxs,
		},
	}

	var buf bytes.Buffer
	err = rawSpanBatch.encodeBlockCount(&buf)
	assert.NoError(t, err)

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch

	err = sb.decodeBlockCount(r)
	require.ErrorIs(t, err, ErrEmptySpanBatch)
}

96 97 98 99 100 101 102 103 104 105
func TestSpanBatchOriginBits(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77665544))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	blockCount := rawSpanBatch.blockCount

	var buf bytes.Buffer
	err := rawSpanBatch.encodeOriginBits(&buf)
106
	require.NoError(t, err)
107 108 109 110 111 112

	// originBit field is fixed length: single bit
	originBitBufferLen := blockCount / 8
	if blockCount%8 != 0 {
		originBitBufferLen++
	}
113
	require.Equal(t, buf.Len(), int(originBitBufferLen))
114 115 116 117 118 119

	result := buf.Bytes()
	var sb RawSpanBatch
	sb.blockCount = blockCount
	r := bytes.NewReader(result)
	err = sb.decodeOriginBits(r)
120
	require.NoError(t, err)
121

122
	require.Equal(t, rawSpanBatch.originBits, sb.originBits)
123 124 125 126 127 128 129 130 131 132 133 134
}

func TestSpanBatchPrefix(t *testing.T) {
	rng := rand.New(rand.NewSource(0x44775566))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)
	// only compare prefix
	rawSpanBatch.spanBatchPayload = spanBatchPayload{}

	var buf bytes.Buffer
	err := rawSpanBatch.encodePrefix(&buf)
135
	require.NoError(t, err)
136 137 138 139 140

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	err = sb.decodePrefix(r)
141
	require.NoError(t, err)
142

143
	require.Equal(t, rawSpanBatch, &sb)
144 145 146 147 148 149 150 151 152 153
}

func TestSpanBatchRelTimestamp(t *testing.T) {
	rng := rand.New(rand.NewSource(0x44775566))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeRelTimestamp(&buf)
154
	require.NoError(t, err)
155 156 157 158 159

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	err = sb.decodeRelTimestamp(r)
160
	require.NoError(t, err)
161

162
	require.Equal(t, rawSpanBatch.relTimestamp, sb.relTimestamp)
163 164 165 166 167 168 169 170 171 172
}

func TestSpanBatchL1OriginNum(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556688))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeL1OriginNum(&buf)
173
	require.NoError(t, err)
174 175 176 177 178

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	err = sb.decodeL1OriginNum(r)
179
	require.NoError(t, err)
180

181
	require.Equal(t, rawSpanBatch.l1OriginNum, sb.l1OriginNum)
182 183 184 185 186 187 188 189 190 191
}

func TestSpanBatchParentCheck(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556689))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeParentCheck(&buf)
192
	require.NoError(t, err)
193 194

	// parent check field is fixed length: 20 bytes
195
	require.Equal(t, buf.Len(), 20)
196 197 198 199 200

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	err = sb.decodeParentCheck(r)
201
	require.NoError(t, err)
202

203
	require.Equal(t, rawSpanBatch.parentCheck, sb.parentCheck)
204 205 206 207 208 209 210 211 212 213
}

func TestSpanBatchL1OriginCheck(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556690))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeL1OriginCheck(&buf)
214
	require.NoError(t, err)
215 216

	// l1 origin check field is fixed length: 20 bytes
217
	require.Equal(t, buf.Len(), 20)
218 219 220 221 222

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	err = sb.decodeL1OriginCheck(r)
223
	require.NoError(t, err)
224

225
	require.Equal(t, rawSpanBatch.l1OriginCheck, sb.l1OriginCheck)
226 227 228 229 230 231 232 233 234 235
}

func TestSpanBatchPayload(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556691))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodePayload(&buf)
236
	require.NoError(t, err)
237 238 239 240 241 242

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch

	err = sb.decodePayload(r)
243
	require.NoError(t, err)
244

245 246
	err = sb.txs.recoverV(chainID)
	require.NoError(t, err)
247

248
	require.Equal(t, rawSpanBatch.spanBatchPayload, sb.spanBatchPayload)
249 250 251 252 253 254 255 256 257 258
}

func TestSpanBatchBlockCount(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556691))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeBlockCount(&buf)
259
	require.NoError(t, err)
260 261 262 263 264 265

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch

	err = sb.decodeBlockCount(r)
266
	require.NoError(t, err)
267

268
	require.Equal(t, rawSpanBatch.blockCount, sb.blockCount)
269 270 271 272 273 274 275 276 277 278
}

func TestSpanBatchBlockTxCounts(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556692))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeBlockTxCounts(&buf)
279
	require.NoError(t, err)
280 281 282 283 284 285 286

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch

	sb.blockCount = rawSpanBatch.blockCount
	err = sb.decodeBlockTxCounts(r)
287
	require.NoError(t, err)
288

289
	require.Equal(t, rawSpanBatch.blockTxCounts, sb.blockTxCounts)
290 291 292 293 294 295 296 297 298 299
}

func TestSpanBatchTxs(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556693))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

	var buf bytes.Buffer
	err := rawSpanBatch.encodeTxs(&buf)
300
	require.NoError(t, err)
301 302 303 304 305 306 307

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch

	sb.blockTxCounts = rawSpanBatch.blockTxCounts
	err = sb.decodeTxs(r)
308
	require.NoError(t, err)
309

310 311
	err = sb.txs.recoverV(chainID)
	require.NoError(t, err)
312

313
	require.Equal(t, rawSpanBatch.txs, sb.txs)
314 315 316 317 318 319 320 321
}

func TestSpanBatchRoundTrip(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556694))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)

322 323
	var result bytes.Buffer
	err := rawSpanBatch.encode(&result)
324
	require.NoError(t, err)
325 326

	var sb RawSpanBatch
327
	err = sb.decode(bytes.NewReader(result.Bytes()))
328
	require.NoError(t, err)
329

330 331
	err = sb.txs.recoverV(chainID)
	require.NoError(t, err)
332

333
	require.Equal(t, rawSpanBatch, &sb)
334 335 336 337 338 339 340 341 342 343 344 345 346 347
}

func TestSpanBatchDerive(t *testing.T) {
	rng := rand.New(rand.NewSource(0xbab0bab0))

	chainID := new(big.Int).SetUint64(rng.Uint64())
	l2BlockTime := uint64(2)

	for originChangedBit := 0; originChangedBit < 2; originChangedBit++ {
		singularBatches := RandomValidConsecutiveSingularBatches(rng, chainID)
		safeL2Head := testutils.RandomL2BlockRef(rng)
		safeL2Head.Hash = common.BytesToHash(singularBatches[0].ParentHash[:])
		genesisTimeStamp := 1 + singularBatches[0].Timestamp - 128

348 349 350 351
		spanBatch := initializedSpanBatch(singularBatches, genesisTimeStamp, chainID)
		// set originChangedBit to match the original test implementation
		spanBatch.setFirstOriginChangedBit(uint(originChangedBit))
		rawSpanBatch, err := spanBatch.ToRawSpanBatch()
352
		require.NoError(t, err)
353 354

		spanBatchDerived, err := rawSpanBatch.derive(l2BlockTime, genesisTimeStamp, chainID)
355
		require.NoError(t, err)
356 357

		blockCount := len(singularBatches)
358 359
		require.Equal(t, safeL2Head.Hash.Bytes()[:20], spanBatchDerived.ParentCheck[:])
		require.Equal(t, singularBatches[blockCount-1].Epoch().Hash.Bytes()[:20], spanBatchDerived.L1OriginCheck[:])
360
		require.Equal(t, len(singularBatches), int(rawSpanBatch.blockCount))
361 362

		for i := 1; i < len(singularBatches); i++ {
363
			require.Equal(t, spanBatchDerived.Batches[i].Timestamp, spanBatchDerived.Batches[i-1].Timestamp+l2BlockTime)
364 365 366
		}

		for i := 0; i < len(singularBatches); i++ {
367 368 369
			require.Equal(t, singularBatches[i].EpochNum, spanBatchDerived.Batches[i].EpochNum)
			require.Equal(t, singularBatches[i].Timestamp, spanBatchDerived.Batches[i].Timestamp)
			require.Equal(t, singularBatches[i].Transactions, spanBatchDerived.Batches[i].Transactions)
370 371 372 373 374 375 376 377 378 379 380
		}
	}
}

func TestSpanBatchAppend(t *testing.T) {
	rng := rand.New(rand.NewSource(0x44337711))

	chainID := new(big.Int).SetUint64(rng.Uint64())

	singularBatches := RandomValidConsecutiveSingularBatches(rng, chainID)
	// initialize empty span batch
381
	spanBatch := initializedSpanBatch([]*SingularBatch{}, uint64(0), chainID)
382 383 384

	L := 2
	for i := 0; i < L; i++ {
385 386
		err := spanBatch.AppendSingularBatch(singularBatches[i], uint64(i))
		require.NoError(t, err)
387 388
	}
	// initialize with two singular batches
389
	spanBatch2 := initializedSpanBatch(singularBatches[:L], uint64(0), chainID)
390

391
	require.Equal(t, spanBatch, spanBatch2)
392 393 394 395 396 397 398 399 400 401 402 403
}

func TestSpanBatchMerge(t *testing.T) {
	rng := rand.New(rand.NewSource(0x73314433))

	genesisTimeStamp := rng.Uint64()
	chainID := new(big.Int).SetUint64(rng.Uint64())

	for originChangedBit := 0; originChangedBit < 2; originChangedBit++ {
		singularBatches := RandomValidConsecutiveSingularBatches(rng, chainID)
		blockCount := len(singularBatches)

404 405 406 407
		spanBatch := initializedSpanBatch(singularBatches, genesisTimeStamp, chainID)
		// set originChangedBit to match the original test implementation
		spanBatch.setFirstOriginChangedBit(uint(originChangedBit))
		rawSpanBatch, err := spanBatch.ToRawSpanBatch()
408
		require.NoError(t, err)
409 410

		// check span batch prefix
411 412 413 414
		require.Equal(t, rawSpanBatch.relTimestamp, singularBatches[0].Timestamp-genesisTimeStamp, "invalid relative timestamp")
		require.Equal(t, rollup.Epoch(rawSpanBatch.l1OriginNum), singularBatches[blockCount-1].EpochNum)
		require.Equal(t, rawSpanBatch.parentCheck[:], singularBatches[0].ParentHash.Bytes()[:20], "invalid parent check")
		require.Equal(t, rawSpanBatch.l1OriginCheck[:], singularBatches[blockCount-1].EpochHash.Bytes()[:20], "invalid l1 origin check")
415 416

		// check span batch payload
417
		require.Equal(t, int(rawSpanBatch.blockCount), len(singularBatches))
418
		require.Equal(t, rawSpanBatch.originBits.Bit(0), uint(originChangedBit))
419 420
		for i := 1; i < blockCount; i++ {
			if rawSpanBatch.originBits.Bit(i) == 1 {
421
				require.Equal(t, singularBatches[i].EpochNum, singularBatches[i-1].EpochNum+1)
422
			} else {
423
				require.Equal(t, singularBatches[i].EpochNum, singularBatches[i-1].EpochNum)
424 425 426 427
			}
		}
		for i := 0; i < len(singularBatches); i++ {
			txCount := len(singularBatches[i].Transactions)
428
			require.Equal(t, txCount, int(rawSpanBatch.blockTxCounts[i]))
429 430 431 432
		}

		// check invariants
		endEpochNum := rawSpanBatch.l1OriginNum
433
		require.Equal(t, endEpochNum, uint64(singularBatches[blockCount-1].EpochNum))
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449

		// we do not check txs field because it has to be derived to be compared
	}
}

func TestSpanBatchToSingularBatch(t *testing.T) {
	rng := rand.New(rand.NewSource(0xbab0bab1))
	chainID := new(big.Int).SetUint64(rng.Uint64())

	for originChangedBit := 0; originChangedBit < 2; originChangedBit++ {
		singularBatches := RandomValidConsecutiveSingularBatches(rng, chainID)
		safeL2Head := testutils.RandomL2BlockRef(rng)
		safeL2Head.Hash = common.BytesToHash(singularBatches[0].ParentHash[:])
		safeL2Head.Time = singularBatches[0].Timestamp - 2
		genesisTimeStamp := 1 + singularBatches[0].Timestamp - 128

450 451 452 453
		spanBatch := initializedSpanBatch(singularBatches, genesisTimeStamp, chainID)
		// set originChangedBit to match the original test implementation
		spanBatch.setFirstOriginChangedBit(uint(originChangedBit))
		rawSpanBatch, err := spanBatch.ToRawSpanBatch()
454
		require.NoError(t, err)
455 456 457 458

		l1Origins := mockL1Origin(rng, rawSpanBatch, singularBatches)

		singularBatches2, err := spanBatch.GetSingularBatches(l1Origins, safeL2Head)
459
		require.NoError(t, err)
460 461 462 463 464 465 466 467

		// GetSingularBatches does not fill in parent hash of singular batches
		// empty out parent hash for comparison
		for i := 0; i < len(singularBatches); i++ {
			singularBatches[i].ParentHash = common.Hash{}
		}
		// check parent hash is empty
		for i := 0; i < len(singularBatches2); i++ {
468
			require.Equal(t, singularBatches2[i].ParentHash, common.Hash{})
469 470
		}

471
		require.Equal(t, singularBatches, singularBatches2)
472 473 474 475
	}
}

func TestSpanBatchReadTxData(t *testing.T) {
476
	cases := []spanBatchTxTest{
477 478 479 480
		{"unprotected legacy tx", 32, testutils.RandomLegacyTx, false},
		{"legacy tx", 32, testutils.RandomLegacyTx, true},
		{"access list tx", 32, testutils.RandomAccessListTx, true},
		{"dynamic fee tx", 32, testutils.RandomDynamicFeeTx, true},
481 482
	}

483 484 485 486 487
	for i, testCase := range cases {
		t.Run(testCase.name, func(t *testing.T) {
			rng := rand.New(rand.NewSource(int64(0x109550 + i)))
			chainID := new(big.Int).SetUint64(rng.Uint64())
			signer := types.NewLondonSigner(chainID)
488 489 490
			if !testCase.protected {
				signer = types.HomesteadSigner{}
			}
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508

			var rawTxs [][]byte
			var txs []*types.Transaction
			for txIdx := 0; txIdx < testCase.trials; txIdx++ {
				tx := testCase.mkTx(rng, signer)
				rawTx, err := tx.MarshalBinary()
				require.NoError(t, err)
				rawTxs = append(rawTxs, rawTx)
				txs = append(txs, tx)
			}

			for txIdx := 0; txIdx < testCase.trials; txIdx++ {
				r := bytes.NewReader(rawTxs[i])
				_, txType, err := ReadTxData(r)
				require.NoError(t, err)
				assert.Equal(t, int(txs[i].Type()), txType)
			}
		})
509 510 511 512 513
	}
}

func TestSpanBatchReadTxDataInvalid(t *testing.T) {
	dummy, err := rlp.EncodeToBytes("dummy")
514
	require.NoError(t, err)
515 516 517 518

	// test non list rlp decoding
	r := bytes.NewReader(dummy)
	_, _, err = ReadTxData(r)
519
	require.ErrorContains(t, err, "tx RLP prefix type must be list")
520 521 522 523 524 525
}

func TestSpanBatchMaxTxData(t *testing.T) {
	rng := rand.New(rand.NewSource(0x177288))

	invalidTx := types.NewTx(&types.DynamicFeeTx{
526
		Data: testutils.RandomData(rng, MaxSpanBatchElementCount+1),
527 528 529
	})

	txEncoded, err := invalidTx.MarshalBinary()
530
	require.NoError(t, err)
531 532 533 534

	r := bytes.NewReader(txEncoded)
	_, _, err = ReadTxData(r)

535
	require.ErrorIs(t, err, ErrTooBigSpanBatchSize)
536 537 538 539
}

func TestSpanBatchMaxOriginBitsLength(t *testing.T) {
	var sb RawSpanBatch
540
	sb.blockCount = math.MaxUint64
541 542 543

	r := bytes.NewReader([]byte{})
	err := sb.decodeOriginBits(r)
544
	require.ErrorIs(t, err, ErrTooBigSpanBatchSize)
545
}
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561

func TestSpanBatchMaxBlockCount(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556691))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)
	rawSpanBatch.blockCount = math.MaxUint64

	var buf bytes.Buffer
	err := rawSpanBatch.encodeBlockCount(&buf)
	require.NoError(t, err)

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	err = sb.decodeBlockCount(r)
562
	require.ErrorIs(t, err, ErrTooBigSpanBatchSize)
563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580
}

func TestSpanBatchMaxBlockTxCount(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556692))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)
	rawSpanBatch.blockTxCounts[0] = math.MaxUint64

	var buf bytes.Buffer
	err := rawSpanBatch.encodeBlockTxCounts(&buf)
	require.NoError(t, err)

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	sb.blockCount = rawSpanBatch.blockCount
	err = sb.decodeBlockTxCounts(r)
581
	require.ErrorIs(t, err, ErrTooBigSpanBatchSize)
582 583 584 585 586 587 588
}

func TestSpanBatchTotalBlockTxCountNotOverflow(t *testing.T) {
	rng := rand.New(rand.NewSource(0x77556693))
	chainID := big.NewInt(rng.Int63n(1000))

	rawSpanBatch := RandomRawSpanBatch(rng, chainID)
589 590
	rawSpanBatch.blockTxCounts[0] = MaxSpanBatchElementCount - 1
	rawSpanBatch.blockTxCounts[1] = MaxSpanBatchElementCount - 1
591 592 593 594 595 596 597 598 599 600 601 602
	// we are sure that totalBlockTxCount will overflow on uint64

	var buf bytes.Buffer
	err := rawSpanBatch.encodeBlockTxCounts(&buf)
	require.NoError(t, err)

	result := buf.Bytes()
	r := bytes.NewReader(result)
	var sb RawSpanBatch
	sb.blockTxCounts = rawSpanBatch.blockTxCounts
	err = sb.decodeTxs(r)

603
	require.ErrorIs(t, err, ErrTooBigSpanBatchSize)
604
}