Skip to content

Commit b10f41d

Browse files
committed
fix: harden usage of sentinel error is block_gas_cost.go and corresponding tests
1 parent 5419374 commit b10f41d

File tree

2 files changed

+56
-26
lines changed

2 files changed

+56
-26
lines changed

plugin/evm/customheader/block_gas_cost.go

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,12 +19,15 @@ import (
1919
)
2020

2121
var (
22-
errBaseFeeNil = errors.New("base fee is nil")
23-
errBlockGasCostNil = errors.New("block gas cost is nil")
24-
errExtDataGasUsedNil = errors.New("extDataGasUsed is nil")
25-
errNoGasUsed = errors.New("no gas used")
26-
errNonZeroBlockGasCostGranite = errors.New("non-zero block gas cost in Granite - must be 0")
27-
ErrInsufficientBlockGas = errors.New("insufficient gas to cover the block cost")
22+
errBaseFeeNil = errors.New("base fee is nil")
23+
errBlockGasCostNil = errors.New("block gas cost is nil")
24+
errExtDataGasUsedNil = errors.New("extDataGasUsed is nil")
25+
errNoGasUsed = errors.New("no gas used")
26+
errNonZeroBlockGasCostGranite = errors.New("non-zero block gas cost in Granite - must be 0")
27+
ErrInsufficientBlockGas = errors.New("insufficient gas to cover the block cost")
28+
errInvalidExtraStateChangeContribution = errors.New("invalid extra state change contribution")
29+
errInvalidBaseFeeApricotPhase4 = errors.New("invalid base fee in apricot phase 4")
30+
errInvalidRequiredBlockGasCostApricotPhase4 = errors.New("invalid block gas cost in apricot phase 4")
2831
)
2932

3033
// BlockGasCost calculates the required block gas cost based on the parent
@@ -155,10 +158,10 @@ func VerifyBlockFee(
155158
}
156159

157160
if baseFee == nil || baseFee.Sign() <= 0 {
158-
return fmt.Errorf("invalid base fee (%d) in apricot phase 4", baseFee)
161+
return fmt.Errorf("%w: %d", errInvalidBaseFeeApricotPhase4, baseFee)
159162
}
160163
if requiredBlockGasCost == nil || !requiredBlockGasCost.IsUint64() {
161-
return fmt.Errorf("invalid block gas cost (%d) in apricot phase 4", requiredBlockGasCost)
164+
return fmt.Errorf("%w: %d", errInvalidRequiredBlockGasCostApricotPhase4, requiredBlockGasCost)
162165
}
163166

164167
var (
@@ -170,7 +173,7 @@ func VerifyBlockFee(
170173
// Add in the external contribution
171174
if extraStateChangeContribution != nil {
172175
if extraStateChangeContribution.Cmp(common.Big0) < 0 {
173-
return fmt.Errorf("invalid extra state change contribution: %d", extraStateChangeContribution)
176+
return fmt.Errorf("%w: %d", errInvalidExtraStateChangeContribution, extraStateChangeContribution)
174177
}
175178
totalBlockFee.Add(totalBlockFee, extraStateChangeContribution)
176179
}

plugin/evm/customheader/block_gas_cost_test.go

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
package customheader
55

66
import (
7+
"fmt"
78
"math/big"
89
"testing"
910

@@ -319,6 +320,7 @@ func TestVerifyBlockFee(t *testing.T) {
319320
rules extras.AvalancheRules
320321
overrideBlockGasCost *big.Int
321322
expectedErrMsg string
323+
expectedErr error
322324
}{
323325
"tx only base fee": {
324326
baseFee: big.NewInt(100),
@@ -331,7 +333,8 @@ func TestVerifyBlockFee(t *testing.T) {
331333
{GasUsed: 1000},
332334
},
333335
extraStateContribution: nil,
334-
expectedErrMsg: "insufficient gas to cover the block cost: expected 100000 but got 0",
336+
expectedErrMsg: toWrappedErrorMsg(ErrInsufficientBlockGas, "expected 100000 but got 0"),
337+
expectedErr: ErrInsufficientBlockGas,
335338
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
336339
},
337340
"tx covers exactly block fee": {
@@ -345,7 +348,6 @@ func TestVerifyBlockFee(t *testing.T) {
345348
{GasUsed: 100_000},
346349
},
347350
extraStateContribution: nil,
348-
expectedErrMsg: "",
349351
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
350352
},
351353
"txs share block fee": {
@@ -361,7 +363,6 @@ func TestVerifyBlockFee(t *testing.T) {
361363
{GasUsed: 100_000},
362364
},
363365
extraStateContribution: nil,
364-
expectedErrMsg: "",
365366
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
366367
},
367368
"txs split block fee": {
@@ -377,7 +378,6 @@ func TestVerifyBlockFee(t *testing.T) {
377378
{GasUsed: 100_000},
378379
},
379380
extraStateContribution: nil,
380-
expectedErrMsg: "",
381381
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
382382
},
383383
"split block fee with extra state contribution": {
@@ -391,7 +391,6 @@ func TestVerifyBlockFee(t *testing.T) {
391391
{GasUsed: 100_000},
392392
},
393393
extraStateContribution: big.NewInt(5_000_000),
394-
expectedErrMsg: "",
395394
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
396395
},
397396
"extra state contribution insufficient": {
@@ -401,7 +400,8 @@ func TestVerifyBlockFee(t *testing.T) {
401400
txs: nil,
402401
receipts: nil,
403402
extraStateContribution: big.NewInt(9_999_999),
404-
expectedErrMsg: "insufficient gas to cover the block cost: expected 100000 but got 99999",
403+
expectedErrMsg: toWrappedErrorMsg(ErrInsufficientBlockGas, "expected 100000 but got 99999"),
404+
expectedErr: ErrInsufficientBlockGas,
405405
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
406406
},
407407
"negative extra state contribution": {
@@ -411,7 +411,8 @@ func TestVerifyBlockFee(t *testing.T) {
411411
txs: nil,
412412
receipts: nil,
413413
extraStateContribution: big.NewInt(-1),
414-
expectedErrMsg: "invalid extra state change contribution: -1",
414+
expectedErrMsg: toWrappedErrorMsg(errInvalidExtraStateChangeContribution, "-1"),
415+
expectedErr: errInvalidExtraStateChangeContribution,
415416
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
416417
},
417418
"extra state contribution covers block fee": {
@@ -421,7 +422,6 @@ func TestVerifyBlockFee(t *testing.T) {
421422
txs: nil,
422423
receipts: nil,
423424
extraStateContribution: big.NewInt(10_000_000),
424-
expectedErrMsg: "",
425425
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
426426
},
427427
"extra state contribution covers more than block fee": {
@@ -431,7 +431,6 @@ func TestVerifyBlockFee(t *testing.T) {
431431
txs: nil,
432432
receipts: nil,
433433
extraStateContribution: big.NewInt(10_000_001),
434-
expectedErrMsg: "",
435434
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
436435
},
437436
"tx only base fee after full time window": {
@@ -445,7 +444,6 @@ func TestVerifyBlockFee(t *testing.T) {
445444
{GasUsed: 1000},
446445
},
447446
extraStateContribution: nil,
448-
expectedErrMsg: "",
449447
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
450448
},
451449
"tx only base fee after large time window": {
@@ -459,7 +457,6 @@ func TestVerifyBlockFee(t *testing.T) {
459457
{GasUsed: 1000},
460458
},
461459
extraStateContribution: nil,
462-
expectedErrMsg: "",
463460
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
464461
},
465462
"fortuna minimum base fee should fail": {
@@ -469,7 +466,8 @@ func TestVerifyBlockFee(t *testing.T) {
469466
txs: nil,
470467
receipts: nil,
471468
extraStateContribution: nil,
472-
expectedErrMsg: "insufficient gas to cover the block cost: expected 400000 but got 0",
469+
expectedErrMsg: toWrappedErrorMsg(ErrInsufficientBlockGas, "expected 400000 but got 0"),
470+
expectedErr: ErrInsufficientBlockGas,
473471
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.Fortuna),
474472
},
475473
"granite minimum base fee should not fail ": {
@@ -479,7 +477,6 @@ func TestVerifyBlockFee(t *testing.T) {
479477
txs: nil,
480478
receipts: nil,
481479
extraStateContribution: nil,
482-
expectedErrMsg: "",
483480
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.Granite),
484481
},
485482
"granite block gas cost = 0 should not fail": {
@@ -489,7 +486,6 @@ func TestVerifyBlockFee(t *testing.T) {
489486
txs: nil,
490487
receipts: nil,
491488
extraStateContribution: nil,
492-
expectedErrMsg: "",
493489
overrideBlockGasCost: big.NewInt(0),
494490
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.Granite),
495491
},
@@ -500,10 +496,31 @@ func TestVerifyBlockFee(t *testing.T) {
500496
txs: nil,
501497
receipts: nil,
502498
extraStateContribution: nil,
503-
expectedErrMsg: errNonZeroBlockGasCostGranite.Error(),
499+
expectedErr: errNonZeroBlockGasCostGranite,
504500
overrideBlockGasCost: big.NewInt(1),
505501
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.Granite),
506502
},
503+
"ap4 invalid base fee (zero)": {
504+
baseFee: big.NewInt(0),
505+
parentBlockGasCost: big.NewInt(0),
506+
timeElapsed: 0,
507+
txs: nil,
508+
receipts: nil,
509+
extraStateContribution: nil,
510+
expectedErr: errInvalidBaseFeeApricotPhase4,
511+
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
512+
},
513+
"ap4 invalid required block gas cost (not uint64)": {
514+
baseFee: big.NewInt(100),
515+
parentBlockGasCost: big.NewInt(0),
516+
timeElapsed: 0,
517+
txs: nil,
518+
receipts: nil,
519+
extraStateContribution: nil,
520+
expectedErr: errInvalidRequiredBlockGasCostApricotPhase4,
521+
overrideBlockGasCost: new(big.Int).Exp(big.NewInt(2), big.NewInt(65), nil),
522+
rules: extrastest.GetAvalancheRulesFromFork(upgradetest.ApricotPhase4),
523+
},
507524
}
508525

509526
for name, test := range tests {
@@ -526,11 +543,21 @@ func TestVerifyBlockFee(t *testing.T) {
526543
}
527544

528545
err := VerifyBlockFee(test.baseFee, blockGasCost, test.txs, test.receipts, test.extraStateContribution, test.rules)
546+
if test.expectedErr != nil {
547+
require.ErrorIs(t, err, test.expectedErr)
548+
return
549+
}
550+
529551
if test.expectedErrMsg == "" {
530552
require.NoError(t, err)
531-
} else {
532-
require.ErrorContains(t, err, test.expectedErrMsg)
553+
return
533554
}
555+
556+
require.ErrorContains(t, err, test.expectedErrMsg)
534557
})
535558
}
536559
}
560+
561+
func toWrappedErrorMsg(err error, msg string) string {
562+
return fmt.Errorf("%w: %s", err, msg).Error()
563+
}

0 commit comments

Comments
 (0)