mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +00:00
Refactor ValidateHeader and CalcDifficulty to accept a *BlockChain
parameter
This commit is contained in:
parent
7e15bf9013
commit
399ce66e5b
6 changed files with 136 additions and 14 deletions
|
|
@ -82,7 +82,7 @@ func (v *BlockValidator) ValidateBlock(block *types.Block) error {
|
|||
|
||||
header := block.Header()
|
||||
// validate the block header
|
||||
if err := ValidateHeader(v.config, v.Pow, header, parent.Header(), false, false); err != nil {
|
||||
if err := ValidateHeader(v.config, v.Pow, header, parent.Header(), false, false, v.bc); err != nil {
|
||||
return err
|
||||
}
|
||||
// verify the uncles are correctly rewarded
|
||||
|
|
@ -177,7 +177,7 @@ func (v *BlockValidator) VerifyUncles(block, parent *types.Block) error {
|
|||
return UncleError("uncle[%d](%x)'s parent is not ancestor (%x)", i, hash[:4], uncle.ParentHash[0:4])
|
||||
}
|
||||
|
||||
if err := ValidateHeader(v.config, v.Pow, uncle, ancestors[uncle.ParentHash].Header(), true, true); err != nil {
|
||||
if err := ValidateHeader(v.config, v.Pow, uncle, ancestors[uncle.ParentHash].Header(), true, true, v.bc); err != nil {
|
||||
return ValidationError(fmt.Sprintf("uncle[%d](%x) header invalid: %v", i, hash[:4], err))
|
||||
}
|
||||
}
|
||||
|
|
@ -197,13 +197,13 @@ func (v *BlockValidator) ValidateHeader(header, parent *types.Header, checkPow b
|
|||
if v.bc.HasHeader(header.Hash()) {
|
||||
return nil
|
||||
}
|
||||
return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false)
|
||||
return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false, v.bc)
|
||||
}
|
||||
|
||||
// Validates a header. Returns an error if the header is invalid.
|
||||
//
|
||||
// See YP section 4.3.4. "Block Header Validity"
|
||||
func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool) error {
|
||||
func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool, bc *BlockChain) error {
|
||||
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
|
||||
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
|
||||
}
|
||||
|
|
@ -221,7 +221,59 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade
|
|||
return BlockEqualTSErr
|
||||
}
|
||||
|
||||
expd := CalcDifficulty(config, header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty)
|
||||
expd := CalcDifficulty(config, header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty, bc)
|
||||
if expd.Cmp(header.Difficulty) != 0 {
|
||||
return fmt.Errorf("Difficulty check failed for header (remote: %v local: %v)", header.Difficulty, expd)
|
||||
}
|
||||
|
||||
a := new(big.Int).Set(parent.GasLimit)
|
||||
a = a.Sub(a, header.GasLimit)
|
||||
a.Abs(a)
|
||||
b := new(big.Int).Set(parent.GasLimit)
|
||||
b = b.Div(b, params.GasLimitBoundDivisor)
|
||||
if !(a.Cmp(b) < 0) || (header.GasLimit.Cmp(params.MinGasLimit) == -1) {
|
||||
return fmt.Errorf("GasLimit check failed for header (remote: %v local_max: %v)", header.GasLimit, b)
|
||||
}
|
||||
|
||||
num := new(big.Int).Set(parent.Number)
|
||||
num.Sub(header.Number, num)
|
||||
if num.Cmp(big.NewInt(1)) != 0 {
|
||||
return BlockNumberErr
|
||||
}
|
||||
|
||||
if checkPow {
|
||||
// Verify the nonce of the header. Return an error if it's not valid
|
||||
if !pow.Verify(types.NewBlockWithHeader(header)) {
|
||||
return &BlockNonceErr{header.Number, header.Hash(), header.Nonce.Uint64()}
|
||||
}
|
||||
}
|
||||
if !uncle && config.EIP150Block != nil && config.EIP150Block.Cmp(header.Number) == 0 {
|
||||
if config.EIP150Hash != (common.Hash{}) && config.EIP150Hash != header.Hash() {
|
||||
return ValidationError("Homestead gas reprice fork hash mismatch: have 0x%x, want 0x%x", header.Hash(), config.EIP150Hash)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func ValidateHeaderHeaderChain(config *params.ChainConfig, pow pow.PoW, header *types.Header, parent *types.Header, checkPow, uncle bool, hc *HeaderChain) error {
|
||||
if big.NewInt(int64(len(header.Extra))).Cmp(params.MaximumExtraDataSize) == 1 {
|
||||
return fmt.Errorf("Header extra data too long (%d)", len(header.Extra))
|
||||
}
|
||||
|
||||
if uncle {
|
||||
if header.Time.Cmp(common.MaxBig) == 1 {
|
||||
return BlockTSTooBigErr
|
||||
}
|
||||
} else {
|
||||
if header.Time.Cmp(big.NewInt(time.Now().Unix())) == 1 {
|
||||
return BlockFutureErr
|
||||
}
|
||||
}
|
||||
if header.Time.Cmp(parent.Time) != 1 {
|
||||
return BlockEqualTSErr
|
||||
}
|
||||
|
||||
expd := CalcDifficultyHeaderChain(config, header.Time.Uint64(), parent.Time.Uint64(), parent.Number, parent.Difficulty, hc)
|
||||
if expd.Cmp(header.Difficulty) != 0 {
|
||||
return fmt.Errorf("Difficulty check failed for header (remote: %v local: %v)", header.Difficulty, expd)
|
||||
}
|
||||
|
|
@ -258,7 +310,7 @@ func ValidateHeader(config *params.ChainConfig, pow pow.PoW, header *types.Heade
|
|||
// CalcDifficulty is the difficulty adjustment algorithm. It returns
|
||||
// the difficulty that a new block should have when created at time
|
||||
// given the parent block's time and difficulty.
|
||||
func CalcDifficulty(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
func CalcDifficulty(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int, bc *BlockChain) *big.Int {
|
||||
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-2.mediawiki
|
||||
// algorithm:
|
||||
// diff = (parent_diff +
|
||||
|
|
@ -307,6 +359,76 @@ func CalcDifficulty(config *params.ChainConfig, time, parentTime uint64, parentN
|
|||
return x
|
||||
}
|
||||
|
||||
func CalcDifficultyHeaderChain(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int, hc *HeaderChain) *big.Int {
|
||||
bigTime := new(big.Int).SetUint64(time)
|
||||
bigParentTime := new(big.Int).SetUint64(parentTime)
|
||||
|
||||
x := new(big.Int)
|
||||
y := new(big.Int)
|
||||
|
||||
x.Sub(bigTime, bigParentTime)
|
||||
x.Div(x, big10)
|
||||
x.Sub(common.Big1, x)
|
||||
|
||||
if x.Cmp(bigMinus99) < 0 {
|
||||
x.Set(bigMinus99)
|
||||
}
|
||||
|
||||
y.Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
x.Mul(y, x)
|
||||
x.Add(parentDiff, x)
|
||||
|
||||
if x.Cmp(params.MinimumDifficulty) < 0 {
|
||||
x.Set(params.MinimumDifficulty)
|
||||
}
|
||||
|
||||
periodCount := new(big.Int).Add(parentNumber, common.Big1)
|
||||
periodCount.Div(periodCount, ExpDiffPeriod)
|
||||
|
||||
if periodCount.Cmp(common.Big1) > 0 {
|
||||
y.Sub(periodCount, common.Big2)
|
||||
y.Exp(common.Big2, y, nil)
|
||||
x.Add(x, y)
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
func CalcDifficultyLegacy(config *params.ChainConfig, time, parentTime uint64, parentNumber, parentDiff *big.Int) *big.Int {
|
||||
bigTime := new(big.Int).SetUint64(time)
|
||||
bigParentTime := new(big.Int).SetUint64(parentTime)
|
||||
|
||||
x := new(big.Int)
|
||||
y := new(big.Int)
|
||||
|
||||
x.Sub(bigTime, bigParentTime)
|
||||
x.Div(x, big10)
|
||||
x.Sub(common.Big1, x)
|
||||
|
||||
if x.Cmp(bigMinus99) < 0 {
|
||||
x.Set(bigMinus99)
|
||||
}
|
||||
|
||||
y.Div(parentDiff, params.DifficultyBoundDivisor)
|
||||
x.Mul(y, x)
|
||||
x.Add(parentDiff, x)
|
||||
|
||||
if x.Cmp(params.MinimumDifficulty) < 0 {
|
||||
x.Set(params.MinimumDifficulty)
|
||||
}
|
||||
|
||||
periodCount := new(big.Int).Add(parentNumber, common.Big1)
|
||||
periodCount.Div(periodCount, ExpDiffPeriod)
|
||||
|
||||
if periodCount.Cmp(common.Big1) > 0 {
|
||||
y.Sub(periodCount, common.Big2)
|
||||
y.Exp(common.Big2, y, nil)
|
||||
x.Add(x, y)
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// CalcGasLimit computes the gas limit of the next block after parent.
|
||||
// The result may be modified by the caller.
|
||||
// This is miner strategy, not consensus protocol.
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ func (b *BlockGen) OffsetTime(seconds int64) {
|
|||
if b.header.Time.Cmp(b.parent.Header().Time) <= 0 {
|
||||
panic("block time out of range")
|
||||
}
|
||||
b.header.Difficulty = CalcDifficulty(MakeChainConfig(), b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
|
||||
b.header.Difficulty = CalcDifficultyLegacy(MakeChainConfig(), b.header.Time.Uint64(), b.parent.Time().Uint64(), b.parent.Number(), b.parent.Difficulty())
|
||||
}
|
||||
|
||||
// GenerateChain creates a chain of n blocks. The first block's
|
||||
|
|
@ -224,7 +224,7 @@ func makeHeader(config *params.ChainConfig, parent *types.Block, state *state.St
|
|||
Root: state.IntermediateRoot(config.IsEIP158(parent.Number())),
|
||||
ParentHash: parent.Hash(),
|
||||
Coinbase: parent.Coinbase(),
|
||||
Difficulty: CalcDifficulty(MakeChainConfig(), time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
||||
Difficulty: CalcDifficultyLegacy(MakeChainConfig(), time.Uint64(), new(big.Int).Sub(time, big.NewInt(10)).Uint64(), parent.Number(), parent.Difficulty()),
|
||||
GasLimit: CalcGasLimit(parent),
|
||||
GasUsed: new(big.Int),
|
||||
Number: new(big.Int).Add(parent.Number(), common.Big1),
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/hashicorp/golang-lru"
|
||||
"github.com/ubiq/go-ubiq/common"
|
||||
"github.com/ubiq/go-ubiq/core/types"
|
||||
"github.com/ubiq/go-ubiq/ethdb"
|
||||
|
|
@ -34,7 +35,6 @@ import (
|
|||
"github.com/ubiq/go-ubiq/logger/glog"
|
||||
"github.com/ubiq/go-ubiq/params"
|
||||
"github.com/ubiq/go-ubiq/pow"
|
||||
"github.com/hashicorp/golang-lru"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -517,5 +517,5 @@ func (v *headerValidator) ValidateHeader(header, parent *types.Header, checkPow
|
|||
if v.hc.HasHeader(header.Hash()) {
|
||||
return nil
|
||||
}
|
||||
return ValidateHeader(v.config, v.Pow, header, parent, checkPow, false)
|
||||
return ValidateHeaderHeaderChain(v.config, v.Pow, header, parent, checkPow, false, v.hc)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -404,7 +404,7 @@ func (api *PrivateDebugAPI) traceBlock(block *types.Block, logConfig *vm.LogConf
|
|||
Tracer: structLogger,
|
||||
}
|
||||
|
||||
if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash(), block.NumberU64()-1), true, false); err != nil {
|
||||
if err := core.ValidateHeader(api.config, blockchain.AuxValidator(), block.Header(), blockchain.GetHeader(block.ParentHash(), block.NumberU64()-1), true, false, blockchain); err != nil {
|
||||
return false, structLogger.StructLogs(), err
|
||||
}
|
||||
statedb, err := blockchain.StateAt(blockchain.GetBlock(block.ParentHash(), block.NumberU64()-1).Root())
|
||||
|
|
|
|||
|
|
@ -161,7 +161,7 @@ func NewProtocolManager(config *params.ChainConfig, fastSync bool, networkId int
|
|||
manager.removePeer)
|
||||
|
||||
validator := func(block *types.Block, parent *types.Block) error {
|
||||
return core.ValidateHeader(config, pow, block.Header(), parent.Header(), true, false)
|
||||
return core.ValidateHeader(config, pow, block.Header(), parent.Header(), true, false, blockchain)
|
||||
}
|
||||
heighter := func() uint64 {
|
||||
return blockchain.CurrentBlock().NumberU64()
|
||||
|
|
|
|||
|
|
@ -301,7 +301,7 @@ func (self *worker) wait() {
|
|||
}
|
||||
|
||||
auxValidator := self.eth.BlockChain().AuxValidator()
|
||||
if err := core.ValidateHeader(self.config, auxValidator, block.Header(), parent.Header(), true, false); err != nil && err != core.BlockFutureErr {
|
||||
if err := core.ValidateHeader(self.config, auxValidator, block.Header(), parent.Header(), true, false, self.eth.BlockChain()); err != nil && err != core.BlockFutureErr {
|
||||
glog.V(logger.Error).Infoln("Invalid header on mined block:", err)
|
||||
continue
|
||||
}
|
||||
|
|
@ -486,7 +486,7 @@ func (self *worker) commitNewWork() {
|
|||
header := &types.Header{
|
||||
ParentHash: parent.Hash(),
|
||||
Number: num.Add(num, common.Big1),
|
||||
Difficulty: core.CalcDifficulty(self.config, uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty()),
|
||||
Difficulty: core.CalcDifficulty(self.config, uint64(tstamp), parent.Time().Uint64(), parent.Number(), parent.Difficulty(), self.chain),
|
||||
GasLimit: core.CalcGasLimit(parent),
|
||||
GasUsed: new(big.Int),
|
||||
Coinbase: self.coinbase,
|
||||
|
|
|
|||
Loading…
Reference in a new issue