mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
[NOD-1469] Implement past median time (#968)
* [NOD-1469] Implement past median time * [NOD-1469] Move BlueWindow to DAGTraversalManager
This commit is contained in:
parent
97b5b0b875
commit
03790ad8a2
@ -67,8 +67,9 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, databaseContext *dba
|
||||
ghostdagDataStore,
|
||||
model.KType(dagParams.K))
|
||||
dagTraversalManager := dagtraversalmanager.New(
|
||||
domainDBContext,
|
||||
dagTopologyManager,
|
||||
ghostdagManager)
|
||||
ghostdagDataStore)
|
||||
pruningManager := pruningmanager.New(
|
||||
dagTraversalManager,
|
||||
dagTopologyManager,
|
||||
@ -92,7 +93,10 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, databaseContext *dba
|
||||
difficultyManager := difficultymanager.New(
|
||||
ghostdagManager)
|
||||
pastMedianTimeManager := pastmediantimemanager.New(
|
||||
ghostdagManager)
|
||||
dagParams.TimestampDeviationTolerance,
|
||||
domainDBContext,
|
||||
dagTraversalManager,
|
||||
blockStore)
|
||||
transactionValidator := transactionvalidator.New(dagParams.BlockCoinbaseMaturity,
|
||||
domainDBContext,
|
||||
pastMedianTimeManager,
|
||||
|
@ -7,4 +7,5 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
type DAGTraversalManager interface {
|
||||
HighestChainBlockBelowBlueScore(highHash *externalapi.DomainHash, blueScore uint64) (*externalapi.DomainHash, error)
|
||||
SelectedParentIterator(highHash *externalapi.DomainHash) (SelectedParentIterator, error)
|
||||
BlueWindow(highHash *externalapi.DomainHash, windowSize uint64) ([]*externalapi.DomainHash, error)
|
||||
}
|
||||
|
@ -8,17 +8,21 @@ import (
|
||||
// dagTraversalManager exposes methods for travering blocks
|
||||
// in the DAG
|
||||
type dagTraversalManager struct {
|
||||
databaseContext model.DBContextProxy
|
||||
|
||||
dagTopologyManager model.DAGTopologyManager
|
||||
ghostdagManager model.GHOSTDAGManager
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
}
|
||||
|
||||
// New instantiates a new DAGTraversalManager
|
||||
func New(
|
||||
databaseContext model.DBContextProxy,
|
||||
dagTopologyManager model.DAGTopologyManager,
|
||||
ghostdagManager model.GHOSTDAGManager) model.DAGTraversalManager {
|
||||
ghostdagDataStore model.GHOSTDAGDataStore) model.DAGTraversalManager {
|
||||
return &dagTraversalManager{
|
||||
databaseContext: databaseContext,
|
||||
dagTopologyManager: dagTopologyManager,
|
||||
ghostdagManager: ghostdagManager,
|
||||
ghostdagDataStore: ghostdagDataStore,
|
||||
}
|
||||
}
|
||||
|
||||
|
41
domain/consensus/processes/dagtraversalmanager/window.go
Normal file
41
domain/consensus/processes/dagtraversalmanager/window.go
Normal file
@ -0,0 +1,41 @@
|
||||
package dagtraversalmanager
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
// blueBlockWindow returns a blockWindow of the given size that contains the
|
||||
// blues in the past of startindNode, sorted by GHOSTDAG order.
|
||||
// If the number of blues in the past of startingNode is less then windowSize,
|
||||
// the window will be padded by genesis blocks to achieve a size of windowSize.
|
||||
func (dtm *dagTraversalManager) BlueWindow(startingBlock *externalapi.DomainHash, windowSize uint64) ([]*externalapi.DomainHash, error) {
|
||||
window := make([]*externalapi.DomainHash, 0, windowSize)
|
||||
|
||||
currentHash := startingBlock
|
||||
currentGHOSTDAGData, err := dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
for uint64(len(window)) < windowSize && currentGHOSTDAGData.SelectedParent != nil {
|
||||
for _, blue := range currentGHOSTDAGData.MergeSetBlues {
|
||||
window = append(window, blue)
|
||||
if uint64(len(window)) == windowSize {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
currentHash = currentGHOSTDAGData.SelectedParent
|
||||
currentGHOSTDAGData, err = dtm.ghostdagDataStore.Get(dtm.databaseContext, currentHash)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if uint64(len(window)) < windowSize {
|
||||
genesis := currentHash
|
||||
for uint64(len(window)) < windowSize {
|
||||
window = append(window, genesis)
|
||||
}
|
||||
}
|
||||
|
||||
return window, nil
|
||||
}
|
@ -3,22 +3,64 @@ package pastmediantimemanager
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/pkg/errors"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// pastMedianTimeManager provides a method to resolve the
|
||||
// past median time of a block
|
||||
type pastMedianTimeManager struct {
|
||||
ghostdagManager model.GHOSTDAGManager
|
||||
timestampDeviationTolerance uint64
|
||||
|
||||
databaseContext model.DBContextProxy
|
||||
|
||||
dagTraversalManager model.DAGTraversalManager
|
||||
|
||||
blockStore model.BlockStore
|
||||
}
|
||||
|
||||
// New instantiates a new PastMedianTimeManager
|
||||
func New(ghostdagManager model.GHOSTDAGManager) model.PastMedianTimeManager {
|
||||
func New(timestampDeviationTolerance uint64,
|
||||
databaseContext model.DBContextProxy,
|
||||
dagTraversalManager model.DAGTraversalManager,
|
||||
blockStore model.BlockStore) model.PastMedianTimeManager {
|
||||
return &pastMedianTimeManager{
|
||||
ghostdagManager: ghostdagManager,
|
||||
timestampDeviationTolerance: timestampDeviationTolerance,
|
||||
databaseContext: databaseContext,
|
||||
dagTraversalManager: dagTraversalManager,
|
||||
blockStore: blockStore,
|
||||
}
|
||||
}
|
||||
|
||||
// PastMedianTime returns the past median time for some block
|
||||
func (pmtm *pastMedianTimeManager) PastMedianTime(blockHash *externalapi.DomainHash) (int64, error) {
|
||||
return 0, nil
|
||||
window, err := pmtm.dagTraversalManager.BlueWindow(blockHash, 2*pmtm.timestampDeviationTolerance-1)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return pmtm.windowMedianTimestamp(window)
|
||||
}
|
||||
|
||||
func (pmtm *pastMedianTimeManager) windowMedianTimestamp(window []*externalapi.DomainHash) (int64, error) {
|
||||
if len(window) == 0 {
|
||||
return 0, errors.New("Cannot calculate median timestamp for an empty block window")
|
||||
}
|
||||
|
||||
timestamps := make([]int64, len(window))
|
||||
for i, blockHash := range window {
|
||||
block, err := pmtm.blockStore.Block(pmtm.databaseContext, blockHash)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// TODO: Use headers store
|
||||
timestamps[i] = block.Header.TimeInMilliseconds
|
||||
}
|
||||
|
||||
sort.Slice(timestamps, func(i, j int) bool {
|
||||
return timestamps[i] < timestamps[j]
|
||||
})
|
||||
|
||||
return timestamps[len(timestamps)/2], nil
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user