mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-26 14:46:42 +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"
|
"math/big"
|
||||||
mrand "math/rand"
|
mrand "math/rand"
|
||||||
"runtime"
|
"runtime"
|
||||||
|
"sort"
|
||||||
"sync"
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
@ -356,6 +357,27 @@ func (hc *HeaderChain) GetBlockHashesFromHash(hash common.Hash, max uint64) []co
|
||||||
return chain
|
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
|
// GetTd retrieves a block's total difficulty in the canonical chain from the
|
||||||
// database by hash and number, caching it if found.
|
// database by hash and number, caching it if found.
|
||||||
func (hc *HeaderChain) GetTd(hash common.Hash, number uint64) *big.Int {
|
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))
|
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
|
// WriteTd stores a block's total difficulty into the database, also caching it
|
||||||
// along the way.
|
// along the way.
|
||||||
func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) error {
|
func (hc *HeaderChain) WriteTd(hash common.Hash, number uint64, td *big.Int) error {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue