Skip to content

Commit 7842864

Browse files
authored
Merge pull request #18 from vulcanize/block_verification
Block verification
2 parents 0c8dcc0 + 783f706 commit 7842864

File tree

2 files changed

+112
-32
lines changed

2 files changed

+112
-32
lines changed

consensus/ethash/consensus.go

Lines changed: 64 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ var (
7171
errInvalidDifficulty = errors.New("non-positive difficulty")
7272
errInvalidMixDigest = errors.New("invalid mix digest")
7373
errInvalidPoW = errors.New("invalid proof-of-work")
74+
errGasLimitSet = errors.New("GasLimit should not be set after EIP1559 has finalized")
7475
)
7576

7677
// Author implements consensus.Engine, returning the header's coinbase as the
@@ -258,26 +259,34 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
258259
if expected.Cmp(header.Difficulty) != 0 {
259260
return fmt.Errorf("invalid difficulty: have %v, want %v", header.Difficulty, expected)
260261
}
261-
// Verify that the gas limit is <= 2^63-1
262-
cap := uint64(0x7fffffffffffffff)
263-
if header.GasLimit > cap {
264-
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
265-
}
266-
// Verify that the gasUsed is <= gasLimit
267-
if header.GasUsed > header.GasLimit {
268-
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
269-
}
270262

271-
// Verify that the gas limit remains within allowed bounds
272-
diff := int64(parent.GasLimit) - int64(header.GasLimit)
273-
if diff < 0 {
274-
diff *= -1
275-
}
276-
limit := parent.GasLimit / params.GasLimitBoundDivisor
263+
// If we have not reached the EIP1559 finalization block we need to verify that the GasLimit field is valid
264+
if !chain.Config().IsEIP1559Finalized(header.Number) {
265+
// Verify that the gas limit is <= 2^63-1
266+
cap := uint64(0x7fffffffffffffff)
267+
if header.GasLimit > cap {
268+
return fmt.Errorf("invalid gasLimit: have %v, max %v", header.GasLimit, cap)
269+
}
270+
// Verify that the gasUsed is <= gasLimit
271+
if header.GasUsed > header.GasLimit {
272+
return fmt.Errorf("invalid gasUsed: have %d, gasLimit %d", header.GasUsed, header.GasLimit)
273+
}
274+
275+
// Verify that the gas limit remains within allowed bounds
276+
diff := int64(parent.GasLimit) - int64(header.GasLimit)
277+
if diff < 0 {
278+
diff *= -1
279+
}
280+
limit := parent.GasLimit / params.GasLimitBoundDivisor
277281

278-
if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
279-
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
282+
if uint64(diff) >= limit || header.GasLimit < params.MinGasLimit {
283+
return fmt.Errorf("invalid gas limit: have %d, want %d += %d", header.GasLimit, parent.GasLimit, limit)
284+
}
285+
} else if header.GasLimit != 0 {
286+
// If EIP1559 is finalized, GasLimit should be 0
287+
return errGasLimitSet
280288
}
289+
281290
// Verify that the block number is parent's +1
282291
if diff := new(big.Int).Sub(header.Number, parent.Number); diff.Cmp(big.NewInt(1)) != 0 {
283292
return consensus.ErrInvalidNumber
@@ -289,6 +298,9 @@ func (ethash *Ethash) verifyHeader(chain consensus.ChainReader, header, parent *
289298
}
290299
}
291300
// If all checks passed, validate any special fields for hard forks
301+
if err := misc.VerifyEIP1559BaseFee(chain.Config(), header, parent); err != nil {
302+
return err
303+
}
292304
if err := misc.VerifyDAOHeaderExtraData(chain.Config(), header); err != nil {
293305
return err
294306
}
@@ -583,21 +595,41 @@ func (ethash *Ethash) FinalizeAndAssemble(chain consensus.ChainReader, header *t
583595
func (ethash *Ethash) SealHash(header *types.Header) (hash common.Hash) {
584596
hasher := sha3.NewLegacyKeccak256()
585597

586-
rlp.Encode(hasher, []interface{}{
587-
header.ParentHash,
588-
header.UncleHash,
589-
header.Coinbase,
590-
header.Root,
591-
header.TxHash,
592-
header.ReceiptHash,
593-
header.Bloom,
594-
header.Difficulty,
595-
header.Number,
596-
header.GasLimit,
597-
header.GasUsed,
598-
header.Time,
599-
header.Extra,
600-
})
598+
if header.BaseFee == nil {
599+
rlp.Encode(hasher, []interface{}{
600+
header.ParentHash,
601+
header.UncleHash,
602+
header.Coinbase,
603+
header.Root,
604+
header.TxHash,
605+
header.ReceiptHash,
606+
header.Bloom,
607+
header.Difficulty,
608+
header.Number,
609+
header.GasLimit,
610+
header.GasUsed,
611+
header.Time,
612+
header.Extra,
613+
})
614+
} else {
615+
rlp.Encode(hasher, []interface{}{
616+
header.ParentHash,
617+
header.UncleHash,
618+
header.Coinbase,
619+
header.Root,
620+
header.TxHash,
621+
header.ReceiptHash,
622+
header.Bloom,
623+
header.Difficulty,
624+
header.Number,
625+
header.GasLimit,
626+
header.GasUsed,
627+
header.Time,
628+
header.Extra,
629+
header.BaseFee,
630+
})
631+
}
632+
601633
hasher.Sum(hash[:0])
602634
return hash
603635
}

consensus/misc/forks.go

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,23 @@
1717
package misc
1818

1919
import (
20+
"errors"
2021
"fmt"
22+
"math/big"
2123

2224
"github.com/ethereum/go-ethereum/common"
2325
"github.com/ethereum/go-ethereum/core/types"
2426
"github.com/ethereum/go-ethereum/params"
2527
)
2628

29+
var (
30+
errInvalidInitialBaseFee = fmt.Errorf("initial BaseFee must equal %d", params.EIP1559InitialBaseFee)
31+
errInvalidBaseFee = errors.New("invalid BaseFee")
32+
errMissingParentBaseFee = errors.New("parent header is missing BaseFee")
33+
errMissingBaseFee = errors.New("current header is missing BaseFee")
34+
errHaveBaseFee = fmt.Errorf("BaseFee should not be set before block %d", params.EIP1559ForkBlockNumber)
35+
)
36+
2737
// VerifyForkHashes verifies that blocks conforming to network hard-forks do have
2838
// the correct hashes, to avoid clients going off on different chains. This is an
2939
// optional feature.
@@ -41,3 +51,41 @@ func VerifyForkHashes(config *params.ChainConfig, header *types.Header, uncle bo
4151
// All ok, return
4252
return nil
4353
}
54+
55+
// VerifyEIP1559BaseFee verifies that the EIP1559 BaseFee field is valid for the current block height
56+
func VerifyEIP1559BaseFee(config *params.ChainConfig, header, parent *types.Header) error {
57+
// If we are at the EIP1559 fork block the BaseFee needs to be equal to params.EIP1559InitialBaseFee
58+
if config.EIP1559Block != nil && config.EIP1559Block.Cmp(header.Number) == 0 {
59+
if header.BaseFee == nil || header.BaseFee.Cmp(new(big.Int).SetUint64(params.EIP1559InitialBaseFee)) != 0 {
60+
return errInvalidInitialBaseFee
61+
}
62+
return nil
63+
}
64+
// Verify the BaseFee is valid if we are past the EIP1559 initialization block
65+
if config.IsEIP1559(header.Number) {
66+
// A valid BASEFEE is one such that abs(BASEFEE - PARENT_BASEFEE) <= max(1, PARENT_BASEFEE // BASEFEE_MAX_CHANGE_DENOMINATOR)
67+
if parent.BaseFee == nil {
68+
return errMissingParentBaseFee
69+
}
70+
if header.BaseFee == nil {
71+
return errMissingBaseFee
72+
}
73+
diff := new(big.Int).Sub(header.BaseFee, parent.BaseFee)
74+
if diff.Sign() < 0 {
75+
diff.Neg(diff)
76+
}
77+
max := new(big.Int).Div(parent.BaseFee, new(big.Int).SetUint64(params.BaseFeeMaxChangeDenominator))
78+
if max.Cmp(common.Big1) < 0 {
79+
max = common.Big1
80+
}
81+
if diff.Cmp(max) > 0 {
82+
return errInvalidBaseFee
83+
}
84+
return nil
85+
}
86+
// If we are before the EIP1559 initialization block the current and parent BaseFees should be nil
87+
if header.BaseFee != nil || parent.BaseFee != nil {
88+
return errHaveBaseFee
89+
}
90+
return nil
91+
}

0 commit comments

Comments
 (0)