mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-08-20 10:52:25 +00:00
refactor calcPastMedianTime
This commit is contained in:
parent
bd4b1ebf96
commit
9aa4a39940
3 changed files with 36 additions and 32 deletions
|
|
@ -18,6 +18,8 @@
|
||||||
package consensus
|
package consensus
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/big"
|
||||||
|
|
||||||
"github.com/ubiq/go-ubiq/common"
|
"github.com/ubiq/go-ubiq/common"
|
||||||
"github.com/ubiq/go-ubiq/core/state"
|
"github.com/ubiq/go-ubiq/core/state"
|
||||||
"github.com/ubiq/go-ubiq/core/types"
|
"github.com/ubiq/go-ubiq/core/types"
|
||||||
|
|
@ -45,6 +47,10 @@ type ChainReader interface {
|
||||||
|
|
||||||
// GetBlock retrieves a block from the database by hash and number.
|
// GetBlock retrieves a block from the database by hash and number.
|
||||||
GetBlock(hash common.Hash, number uint64) *types.Block
|
GetBlock(hash common.Hash, number uint64) *types.Block
|
||||||
|
|
||||||
|
// CalcPastMedianTime calculates the median time of the previous few blocks
|
||||||
|
// prior to, and including, the passed block node.
|
||||||
|
CalcPastMedianTime(number uint64, parent *types.Header) *big.Int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Engine is an algorithm agnostic consensus engine.
|
// Engine is an algorithm agnostic consensus engine.
|
||||||
|
|
|
||||||
|
|
@ -536,31 +536,8 @@ func (bc *BlockChain) HasBlockAndState(hash common.Hash) bool {
|
||||||
// prior to, and including, the passed block node.
|
// prior to, and including, the passed block node.
|
||||||
//
|
//
|
||||||
// Modified from btcsuite
|
// Modified from btcsuite
|
||||||
func (bc *BlockChain) CalcPastMedianTime(number uint64) *big.Int {
|
func (bc *BlockChain) CalcPastMedianTime(number uint64, parent *types.Header) *big.Int {
|
||||||
// Genesis block.
|
return bc.hc.CalcPastMedianTime(number, parent)
|
||||||
if number == 0 {
|
|
||||||
return bc.Genesis().Time()
|
|
||||||
}
|
|
||||||
|
|
||||||
timestamps := make([]*big.Int, medianTimeBlocks)
|
|
||||||
numNodes := 0
|
|
||||||
iterNode := bc.GetHeaderByNumber(number)
|
|
||||||
|
|
||||||
ancestors := make(map[common.Hash]*types.Header)
|
|
||||||
for i, ancestor := range bc.GetBlockHeadersFromHash(iterNode.Hash(), medianTimeBlocks) {
|
|
||||||
ancestors[ancestor.Hash()] = ancestor
|
|
||||||
timestamps[i] = ancestor.Time
|
|
||||||
numNodes++
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prune the slice to the actual number of available timestamps which
|
|
||||||
// will be fewer than desired near the beginning of the block chain
|
|
||||||
// and sort them.
|
|
||||||
timestamps = timestamps[:numNodes]
|
|
||||||
sort.Sort(BigIntSlice(timestamps))
|
|
||||||
|
|
||||||
medianTimestamp := timestamps[numNodes/2]
|
|
||||||
return medianTimestamp
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetBlock retrieves a block from the database by hash and number,
|
// GetBlock retrieves a block from the database by hash and number,
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,8 @@ const (
|
||||||
headerCacheLimit = 512
|
headerCacheLimit = 512
|
||||||
tdCacheLimit = 1024
|
tdCacheLimit = 1024
|
||||||
numberCacheLimit = 2048
|
numberCacheLimit = 2048
|
||||||
|
hashCacheLimit = 64
|
||||||
|
medianTimeBlocks = 11
|
||||||
)
|
)
|
||||||
|
|
||||||
// HeaderChain implements the basic block header chain logic that is shared by
|
// HeaderChain implements the basic block header chain logic that is shared by
|
||||||
|
|
@ -57,6 +59,7 @@ type HeaderChain struct {
|
||||||
headerCache *lru.Cache // Cache for the most recent block headers
|
headerCache *lru.Cache // Cache for the most recent block headers
|
||||||
tdCache *lru.Cache // Cache for the most recent block total difficulties
|
tdCache *lru.Cache // Cache for the most recent block total difficulties
|
||||||
numberCache *lru.Cache // Cache for the most recent block numbers
|
numberCache *lru.Cache // Cache for the most recent block numbers
|
||||||
|
hashCache *lru.Cache
|
||||||
|
|
||||||
procInterrupt func() bool
|
procInterrupt func() bool
|
||||||
|
|
||||||
|
|
@ -72,6 +75,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
|
||||||
headerCache, _ := lru.New(headerCacheLimit)
|
headerCache, _ := lru.New(headerCacheLimit)
|
||||||
tdCache, _ := lru.New(tdCacheLimit)
|
tdCache, _ := lru.New(tdCacheLimit)
|
||||||
numberCache, _ := lru.New(numberCacheLimit)
|
numberCache, _ := lru.New(numberCacheLimit)
|
||||||
|
hashCache, _ := lru.New(hashCacheLimit)
|
||||||
|
|
||||||
// Seed a fast but crypto originating random generator
|
// Seed a fast but crypto originating random generator
|
||||||
seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
|
seed, err := crand.Int(crand.Reader, big.NewInt(math.MaxInt64))
|
||||||
|
|
@ -85,6 +89,7 @@ func NewHeaderChain(chainDb ethdb.Database, config *params.ChainConfig, engine c
|
||||||
headerCache: headerCache,
|
headerCache: headerCache,
|
||||||
tdCache: tdCache,
|
tdCache: tdCache,
|
||||||
numberCache: numberCache,
|
numberCache: numberCache,
|
||||||
|
hashCache: hashCache,
|
||||||
procInterrupt: procInterrupt,
|
procInterrupt: procInterrupt,
|
||||||
rand: mrand.New(mrand.NewSource(seed.Int64())),
|
rand: mrand.New(mrand.NewSource(seed.Int64())),
|
||||||
engine: engine,
|
engine: engine,
|
||||||
|
|
@ -115,6 +120,7 @@ func (hc *HeaderChain) GetBlockNumber(hash common.Hash) uint64 {
|
||||||
number := GetBlockNumber(hc.chainDb, hash)
|
number := GetBlockNumber(hc.chainDb, hash)
|
||||||
if number != missingNumber {
|
if number != missingNumber {
|
||||||
hc.numberCache.Add(hash, number)
|
hc.numberCache.Add(hash, number)
|
||||||
|
hc.hashCache.Add(number, hash)
|
||||||
}
|
}
|
||||||
return number
|
return number
|
||||||
}
|
}
|
||||||
|
|
@ -190,6 +196,7 @@ func (hc *HeaderChain) WriteHeader(header *types.Header) (status WriteStatus, er
|
||||||
|
|
||||||
hc.headerCache.Add(hash, header)
|
hc.headerCache.Add(hash, header)
|
||||||
hc.numberCache.Add(hash, number)
|
hc.numberCache.Add(hash, number)
|
||||||
|
hc.hashCache.Add(number, hash)
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -354,8 +361,7 @@ func (hc *HeaderChain) GetTdByHash(hash common.Hash) *big.Int {
|
||||||
// prior to, and including, the passed block node.
|
// prior to, and including, the passed block node.
|
||||||
//
|
//
|
||||||
// Modified from btcsuite
|
// Modified from btcsuite
|
||||||
func (hc *HeaderChain) CalcPastMedianTime(number uint64) *big.Int {
|
func (hc *HeaderChain) CalcPastMedianTime(number uint64, parent *types.Header) *big.Int {
|
||||||
medianTimeBlocks := uint64(11)
|
|
||||||
|
|
||||||
// Genesis block.
|
// Genesis block.
|
||||||
if number == 0 {
|
if number == 0 {
|
||||||
|
|
@ -364,13 +370,22 @@ func (hc *HeaderChain) CalcPastMedianTime(number uint64) *big.Int {
|
||||||
|
|
||||||
timestamps := make([]*big.Int, medianTimeBlocks)
|
timestamps := make([]*big.Int, medianTimeBlocks)
|
||||||
numNodes := 0
|
numNodes := 0
|
||||||
iterNode := hc.GetHeaderByNumber(number)
|
limit := uint64(0)
|
||||||
|
if number >= medianTimeBlocks {
|
||||||
|
limit = number - medianTimeBlocks + 1
|
||||||
|
}
|
||||||
|
|
||||||
ancestors := make(map[common.Hash]*types.Header)
|
for i := number; i >= limit; i-- {
|
||||||
for i, ancestor := range hc.GetBlockHeadersFromHash(iterNode.Hash(), medianTimeBlocks) {
|
if parent != nil && i == number {
|
||||||
ancestors[ancestor.Hash()] = ancestor
|
timestamps[numNodes] = parent.Time
|
||||||
timestamps[i] = ancestor.Time
|
} else {
|
||||||
|
header := hc.GetHeaderByNumber(i)
|
||||||
|
timestamps[numNodes] = header.Time
|
||||||
|
}
|
||||||
numNodes++
|
numNodes++
|
||||||
|
if i == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prune the slice to the actual number of available timestamps which
|
// Prune the slice to the actual number of available timestamps which
|
||||||
|
|
@ -424,6 +439,11 @@ func (hc *HeaderChain) HasHeader(hash common.Hash) bool {
|
||||||
// GetHeaderByNumber retrieves a block header from the database by number,
|
// GetHeaderByNumber retrieves a block header from the database by number,
|
||||||
// caching it (associated with its hash) if found.
|
// caching it (associated with its hash) if found.
|
||||||
func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
|
func (hc *HeaderChain) GetHeaderByNumber(number uint64) *types.Header {
|
||||||
|
// check cache
|
||||||
|
if cache, ok := hc.hashCache.Get(number); ok {
|
||||||
|
return hc.GetHeader(cache.(common.Hash), number)
|
||||||
|
}
|
||||||
|
|
||||||
hash := GetCanonicalHash(hc.chainDb, number)
|
hash := GetCanonicalHash(hc.chainDb, number)
|
||||||
if hash == (common.Hash{}) {
|
if hash == (common.Hash{}) {
|
||||||
return nil
|
return nil
|
||||||
|
|
@ -476,6 +496,7 @@ func (hc *HeaderChain) SetHead(head uint64, delFn DeleteCallback) {
|
||||||
hc.headerCache.Purge()
|
hc.headerCache.Purge()
|
||||||
hc.tdCache.Purge()
|
hc.tdCache.Purge()
|
||||||
hc.numberCache.Purge()
|
hc.numberCache.Purge()
|
||||||
|
hc.hashCache.Purge()
|
||||||
|
|
||||||
if hc.currentHeader == nil {
|
if hc.currentHeader == nil {
|
||||||
hc.currentHeader = hc.genesisHeader
|
hc.currentHeader = hc.genesisHeader
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue