mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 06:36:43 +00:00
Implement CalcPastMedianTime to HeaderChain
This commit is contained in:
parent
7dac149d70
commit
c6820a988e
1 changed files with 55 additions and 0 deletions
|
|
@ -23,6 +23,7 @@ import (
|
|||
"math/big"
|
||||
mrand "math/rand"
|
||||
"runtime"
|
||||
"sort"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
|
@ -356,6 +357,27 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co
|
|||
return chain
|
||||
}
|
||||
|
||||
func (hc *HeaderChain) GetBlockHeadersFromHash(hash common.Hash, max uint64) []*types.Header {
|
||||
// Get the origin header from which to fetch
|
||||
header := hc.GetHeader(hash)
|
||||
if header == nil {
|
||||
return nil
|
||||
}
|
||||
// Iterate the headers until enough is collected or the genesis reached
|
||||
chain := make([]*types.Header, 0, max)
|
||||
for i := uint64(0); i < max; i++ {
|
||||
next := header.ParentHash
|
||||
if header = hc.GetHeader(next); header == nil {
|
||||
break
|
||||
}
|
||||
chain = append(chain, hc.GetHeader(next))
|
||||
if header.Number.Cmp(common.Big0) == 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return chain
|
||||
}
|
||||
|
||||
// GetTd retrieves a block's total difficulty in the canonical chain from the
|
||||
// database by hash and number, caching it if found.
|
||||
func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {
|
||||
|
|
@ -378,6 +400,39 @@ func (hc *HeaderChain) GetTdByHash(hash common.Hash) *big.Int {
|
|||
return hc.GetTd(hash, hc.GetBlockNumber(hash))
|
||||
}
|
||||
|
||||
// calcPastMedianTime calculates the median time of the previous few blocks
|
||||
// prior to, and including, the passed block node.
|
||||
//
|
||||
// Modified from btcsuite
|
||||
func (hc *HeaderChain) CalcPastMedianTime(number uint64) *big.Int {
|
||||
medianTimeBlocks := uint64(11)
|
||||
|
||||
// Genesis block.
|
||||
if number == 0 {
|
||||
return hc.GetHeaderByNumber(0).Time
|
||||
}
|
||||
|
||||
timestamps := make([]*big.Int, medianTimeBlocks)
|
||||
numNodes := 0
|
||||
iterNode := hc.GetHeaderByNumber(number)
|
||||
|
||||
ancestors := make(map[common.Hash]*types.Header)
|
||||
for i, ancestor := range hc.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
|
||||
}
|
||||
|
||||
// WriteTd stores a block's total difficulty into the database, also caching it
|
||||
// along the way.
|
||||
func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) error {
|
||||
|
|
|
|||
Loading…
Reference in a new issue