Implement CalcPastMedianTime to HeaderChain

This commit is contained in:
Julian Yap 2016-12-04 00:11:39 -10:00
parent 7dac149d70
commit c6820a988e

View file

@ -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 {