consensus, core: drop all the legacy custom core error types

This commit is contained in:
Péter Szilágyi
2017-04-06 14:58:03 +03:00
parent 702bef8493
commit 158d603528
15 changed files with 115 additions and 261 deletions

View File

@ -54,15 +54,15 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// Check whether the block's known, and if not, that it's linkable
if v.bc.HasBlock(block.Hash()) {
if _, err := state.New(block.Root(), v.bc.chainDb); err == nil {
return &KnownBlockError{block.Number(), block.Hash()}
return ErrKnownBlock
}
}
parent := v.bc.GetBlock(block.ParentHash(), block.NumberU64()-1)
if parent == nil {
return ParentError(block.ParentHash())
return consensus.ErrUnknownAncestor
}
if _, err := state.New(parent.Root(), v.bc.chainDb); err != nil {
return ParentError(block.ParentHash())
return consensus.ErrUnknownAncestor
}
// Header validity is known at this point, check the uncles and transactions
header := block.Header()
@ -82,10 +82,10 @@ func (v *BlockValidator) ValidateBody(block *types.Block) error {
// transition, such as amount of used gas, the receipt roots and the state root
// itself. ValidateState returns a database batch if the validation was a success
// otherwise nil and an error is returned.
func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas *big.Int) (err error) {
func (v *BlockValidator) ValidateState(block, parent *types.Block, statedb *state.StateDB, receipts types.Receipts, usedGas *big.Int) error {
header := block.Header()
if block.GasUsed().Cmp(usedGas) != 0 {
return ValidationError(fmt.Sprintf("invalid gas used (remote: %v local: %v)", block.GasUsed(), usedGas))
return fmt.Errorf("invalid gas used (remote: %v local: %v)", block.GasUsed(), usedGas)
}
// Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true.

View File

@ -831,7 +831,7 @@ func (self *BlockChain) WriteBlock(block *types.Block) (status WriteStatus, err
// Calculate the total difficulty of the block
ptd := self.GetTd(block.ParentHash(), block.NumberU64()-1)
if ptd == nil {
return NonStatTy, ParentError(block.ParentHash())
return NonStatTy, consensus.ErrUnknownAncestor
}
// Make sure no inconsistent state is leaked during insertion
self.mu.Lock()
@ -918,9 +918,8 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
}
// If the header is a banned one, straight out abort
if BadHashes[block.Hash()] {
err := BadHashError(block.Hash())
self.reportBlock(block, nil, err)
return i, err
self.reportBlock(block, nil, ErrBlacklistedHash)
return i, ErrBlacklistedHash
}
// Wait for the block's verification to complete
bstart := time.Now()
@ -930,25 +929,25 @@ func (self *BlockChain) InsertChain(chain types.Blocks) (int, error) {
err = self.Validator().ValidateBody(block)
}
if err != nil {
if IsKnownBlockErr(err) {
if err == ErrKnownBlock {
stats.ignored++
continue
}
if err == BlockFutureErr {
if err == consensus.ErrFutureBlock {
// Allow up to MaxFuture second in the future blocks. If this limit
// is exceeded the chain is discarded and processed at a later time
// if given.
max := big.NewInt(time.Now().Unix() + maxTimeFutureBlocks)
if block.Time().Cmp(max) == 1 {
return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
if block.Time().Cmp(max) > 0 {
return i, fmt.Errorf("future block: %v > %v", block.Time(), max)
}
self.futureBlocks.Add(block.Hash(), block)
stats.queued++
continue
}
if IsParentErr(err) && self.futureBlocks.Contains(block.ParentHash()) {
if err == consensus.ErrUnknownAncestor && self.futureBlocks.Contains(block.ParentHash()) {
self.futureBlocks.Add(block.Hash(), block)
stats.queued++
continue

View File

@ -126,7 +126,7 @@ func testBlockChainImport(chain types.Blocks, blockchain *BlockChain) error {
err = blockchain.validator.ValidateBody(block)
}
if err != nil {
if IsKnownBlockErr(err) {
if err == ErrKnownBlock {
continue
}
return err
@ -441,8 +441,8 @@ func testBadHashes(t *testing.T, full bool) {
BadHashes[headers[2].Hash()] = true
_, err = bc.InsertHeaderChain(headers, 1)
}
if !IsBadHashError(err) {
t.Errorf("error mismatch: want: BadHashError, have: %v", err)
if err != ErrBlacklistedHash {
t.Errorf("error mismatch: have: %v, want: %v", err, ErrBlacklistedHash)
}
}

View File

@ -18,6 +18,7 @@ package core
import (
"bytes"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/core/state"
@ -46,11 +47,11 @@ func ValidateDAOHeaderExtraData(config *params.ChainConfig, header *types.Header
// Depending whether we support or oppose the fork, validate the extra-data contents
if config.DAOForkSupport {
if !bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
return ValidationError("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
return fmt.Errorf("DAO pro-fork bad block extra-data: 0x%x", header.Extra)
}
} else {
if bytes.Equal(header.Extra, params.DAOForkBlockExtra) {
return ValidationError("DAO no-fork bad block extra-data: 0x%x", header.Extra)
return fmt.Errorf("DAO no-fork bad block extra-data: 0x%x", header.Extra)
}
}
// All ok, header has the same extra-data we expect

View File

@ -16,188 +16,16 @@
package core
import (
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
)
import "errors"
var (
BlockNumberErr = errors.New("block number invalid")
BlockFutureErr = errors.New("block time is in the future")
BlockTSTooBigErr = errors.New("block time too big")
BlockEqualTSErr = errors.New("block time stamp equal to previous")
// ErrKnownBlock is returned when a block to import is already known locally.
ErrKnownBlock = errors.New("block already known")
// ErrGasLimitReached is returned by the gas pool if the amount of gas required
// by a transaction is higher than what's left in the block.
ErrGasLimitReached = errors.New("gas limit reached")
// ErrBlacklistedHash is returned if a block to import is on the blacklist.
ErrBlacklistedHash = errors.New("blacklisted hash")
)
// Parent error. In case a parent is unknown this error will be thrown
// by the block manager
type ParentErr struct {
Message string
}
func (err *ParentErr) Error() string {
return err.Message
}
func ParentError(hash common.Hash) error {
return &ParentErr{Message: fmt.Sprintf("Block's parent unknown %x", hash)}
}
func IsParentErr(err error) bool {
_, ok := err.(*ParentErr)
return ok
}
type UncleErr struct {
Message string
}
func (err *UncleErr) Error() string {
return err.Message
}
func UncleError(format string, v ...interface{}) error {
return &UncleErr{Message: fmt.Sprintf(format, v...)}
}
func IsUncleErr(err error) bool {
_, ok := err.(*UncleErr)
return ok
}
// Block validation error. If any validation fails, this error will be thrown
type ValidationErr struct {
Message string
}
func (err *ValidationErr) Error() string {
return err.Message
}
func ValidationError(format string, v ...interface{}) *ValidationErr {
return &ValidationErr{Message: fmt.Sprintf(format, v...)}
}
func IsValidationErr(err error) bool {
_, ok := err.(*ValidationErr)
return ok
}
type NonceErr struct {
Message string
Is, Exp uint64
}
func (err *NonceErr) Error() string {
return err.Message
}
func NonceError(is, exp uint64) *NonceErr {
return &NonceErr{Message: fmt.Sprintf("Transaction w/ invalid nonce. tx=%d state=%d)", is, exp), Is: is, Exp: exp}
}
func IsNonceErr(err error) bool {
_, ok := err.(*NonceErr)
return ok
}
// BlockNonceErr indicates that a block's nonce is invalid.
type BlockNonceErr struct {
Number *big.Int
Hash common.Hash
Nonce uint64
}
func (err *BlockNonceErr) Error() string {
return fmt.Sprintf("nonce for #%d [%x…] is invalid (got %d)", err.Number, err.Hash, err.Nonce)
}
// IsBlockNonceErr returns true for invalid block nonce errors.
func IsBlockNonceErr(err error) bool {
_, ok := err.(*BlockNonceErr)
return ok
}
type InvalidTxErr struct {
Message string
}
func (err *InvalidTxErr) Error() string {
return err.Message
}
func InvalidTxError(err error) *InvalidTxErr {
return &InvalidTxErr{fmt.Sprintf("%v", err)}
}
func IsInvalidTxErr(err error) bool {
_, ok := err.(*InvalidTxErr)
return ok
}
type TDError struct {
a, b *big.Int
}
func (self *TDError) Error() string {
return fmt.Sprintf("incoming chain has a lower or equal TD (%v <= %v)", self.a, self.b)
}
func IsTDError(e error) bool {
_, ok := e.(*TDError)
return ok
}
type KnownBlockError struct {
number *big.Int
hash common.Hash
}
func (self *KnownBlockError) Error() string {
return fmt.Sprintf("block %v already known (%x)", self.number, self.hash[0:4])
}
func IsKnownBlockErr(e error) bool {
_, ok := e.(*KnownBlockError)
return ok
}
type ValueTransferError struct {
message string
}
func ValueTransferErr(str string, v ...interface{}) *ValueTransferError {
return &ValueTransferError{fmt.Sprintf(str, v...)}
}
func (self *ValueTransferError) Error() string {
return self.message
}
func IsValueTransferErr(e error) bool {
_, ok := e.(*ValueTransferError)
return ok
}
type BadHashError common.Hash
func (h BadHashError) Error() string {
return fmt.Sprintf("Found known bad hash in chain %x", h[:])
}
func IsBadHashError(err error) bool {
_, ok := err.(BadHashError)
return ok
}
type GasLimitErr struct {
Have, Want *big.Int
}
func IsGasLimitErr(err error) bool {
_, ok := err.(*GasLimitErr)
return ok
}
func (err *GasLimitErr) Error() string {
return fmt.Sprintf("GasLimit reached. Have %d gas, transaction requires %d", err.Have, err.Want)
}

View File

@ -35,7 +35,7 @@ func (gp *GasPool) AddGas(amount *big.Int) *GasPool {
func (gp *GasPool) SubGas(amount *big.Int) error {
i := (*big.Int)(gp)
if i.Cmp(amount) < 0 {
return &GasLimitErr{Have: new(big.Int).Set(i), Want: amount}
return ErrGasLimitReached
}
i.Sub(i, amount)
return nil

View File

@ -137,7 +137,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
// Calculate the total difficulty of the header
ptd := hc.GetTd(header.ParentHash, number-1)
if ptd == nil {
return NonStatTy, ParentError(header.ParentHash)
return NonStatTy, consensus.ErrUnknownAncestor
}
localTd := hc.GetTd(hc.currentHeaderHash, hc.currentHeader.Number.Uint64())
externTd := new(big.Int).Add(header.Difficulty, ptd)
@ -246,7 +246,7 @@ func (hc *HeaderChain) ValidateHeaderChain(chain []*types.Header, checkFreq int)
}
// If the header is a banned one, straight out abort
if BadHashes[header.Hash()] {
return i, BadHashError(header.Hash())
return i, ErrBlacklistedHash
}
// Otherwise wait for headers checks and ensure they pass
if err := <-results; err != nil {

View File

@ -18,6 +18,7 @@ package core
import (
"errors"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@ -195,26 +196,17 @@ func (self *StateTransition) buyGas() error {
return nil
}
func (self *StateTransition) preCheck() (err error) {
func (self *StateTransition) preCheck() error {
msg := self.msg
sender := self.from()
// Make sure this transaction's nonce is correct
if msg.CheckNonce() {
if n := self.state.GetNonce(sender.Address()); n != msg.Nonce() {
return NonceError(msg.Nonce(), n)
return fmt.Errorf("invalid nonce: have %d, expected %d", msg.Nonce(), n)
}
}
// Pre-pay gas
if err = self.buyGas(); err != nil {
if IsGasLimitErr(err) {
return err
}
return InvalidTxError(err)
}
return nil
return self.buyGas()
}
// TransitionDb will transition the state by applying the current message and returning the result
@ -233,11 +225,10 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
// TODO convert to uint64
intrinsicGas := IntrinsicGas(self.data, contractCreation, homestead)
if intrinsicGas.BitLen() > 64 {
return nil, nil, nil, InvalidTxError(vm.ErrOutOfGas)
return nil, nil, nil, vm.ErrOutOfGas
}
if err = self.useGas(intrinsicGas.Uint64()); err != nil {
return nil, nil, nil, InvalidTxError(err)
return nil, nil, nil, err
}
var (
@ -260,10 +251,9 @@ func (self *StateTransition) TransitionDb() (ret []byte, requiredGas, usedGas *b
// sufficient balance to make the transfer happen. The first
// balance transfer may never fail.
if vmerr == vm.ErrInsufficientBalance {
return nil, nil, nil, InvalidTxError(vmerr)
return nil, nil, nil, vmerr
}
}
requiredGas = new(big.Int).Set(self.gasUsed())
self.refundGas()