Remove the sorting requirement from BlueWindow (#1266)

* Remove the requirement for sorting in BlueWindow

* Sort the BlueWindow in window_test
This commit is contained in:
Elichai Turkel 2020-12-23 10:00:14 +02:00 committed by GitHub
parent 90d4dbcba1
commit 43c00f5e7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 33 additions and 14 deletions

View File

@ -1,13 +1,11 @@
package dagtraversalmanager
import (
"sort"
"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.
// blues in the past of startindNode, the sorting is unspecified.
// 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 int) ([]*externalapi.DomainHash, error) {
@ -63,11 +61,6 @@ func (dtm *dagTraversalManager) BlueWindow(startingBlock *externalapi.DomainHash
}
}
// a heap is not a sorted list, and the interface promises to be sorted so we now need to sort this
sort.Slice(windowHeap.impl.slice, func(i, j int) bool {
return windowHeap.impl.slice[j].less(windowHeap.impl.slice[i], dtm.ghostdagManager)
})
window := make([]*externalapi.DomainHash, 0, windowSize)
for _, b := range windowHeap.impl.slice {
window = append(window, b.hash)

View File

@ -1,7 +1,9 @@
package dagtraversalmanager_test
import (
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"reflect"
"sort"
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
@ -343,6 +345,7 @@ func TestBlueBlockWindow(t *testing.T) {
if err != nil {
t.Fatalf("BlueWindow: %s", err)
}
sortWindow(t, tc, window)
if err := checkWindowIDs(window, blockData.expectedWindowWithGenesisPadding, idByBlockMap); err != nil {
t.Errorf("Unexpected values for window for block %s: %s", blockData.id, err)
}
@ -350,6 +353,20 @@ func TestBlueBlockWindow(t *testing.T) {
})
}
func sortWindow(t *testing.T, tc testapi.TestConsensus, window []*externalapi.DomainHash) {
sort.Slice(window, func(i, j int) bool {
ghostdagDataI, err := tc.GHOSTDAGDataStore().Get(tc.DatabaseContext(), window[i])
if err != nil {
t.Fatalf("Failed getting ghostdag data for %s", err)
}
ghostdagDataJ, err := tc.GHOSTDAGDataStore().Get(tc.DatabaseContext(), window[j])
if err != nil {
t.Fatalf("Failed getting ghostdag data for %s", err)
}
return !tc.GHOSTDAGManager().Less(window[i], ghostdagDataI, window[j], ghostdagDataJ)
})
}
func checkWindowIDs(window []*externalapi.DomainHash, expectedIDs []string, idByBlockMap map[externalapi.DomainHash]string) error {
ids := make([]string, len(window))
for i, node := range window {

View File

@ -29,7 +29,7 @@ func (dm *difficultyManager) getDifficultyBlock(blockHash *externalapi.DomainHas
}
// blueBlockWindow returns a blockWindow of the given size that contains the
// blues in the past of startindNode, sorted by GHOSTDAG order.
// blues in the past of startindNode, the sorting is unspecified.
// 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 (dm *difficultyManager) blueBlockWindow(startingNode *externalapi.DomainHash, windowSize int) (blockWindow, error) {
@ -49,20 +49,29 @@ func (dm *difficultyManager) blueBlockWindow(startingNode *externalapi.DomainHas
return window, nil
}
func (window blockWindow) minMaxTimestamps() (min, max int64) {
func (window blockWindow) minMaxTimestamps() (min, max int64, minIndex, maxIndex int) {
min = math.MaxInt64
minIndex = math.MaxInt64
max = 0
for _, block := range window {
maxIndex = 0
for i, block := range window {
if block.timeInMilliseconds < min {
min = block.timeInMilliseconds
minIndex = i
}
if block.timeInMilliseconds > max {
max = block.timeInMilliseconds
maxIndex = i
}
}
return
}
func (window *blockWindow) remove(n int) {
(*window)[n] = (*window)[len(*window)-1]
*window = (*window)[:len(*window)-1]
}
func (window blockWindow) averageTarget(averageTarget *big.Int) {
averageTarget.SetInt64(0)

View File

@ -100,14 +100,14 @@ func (dm *difficultyManager) RequiredDifficulty(blockHash *externalapi.DomainHas
}
// Fetch window of dag.difficultyAdjustmentWindowSize + 1 so we can have dag.difficultyAdjustmentWindowSize block intervals
timestampsWindow, err := dm.blueBlockWindow(bluestParent, dm.difficultyAdjustmentWindowSize+1)
targetsWindow, err := dm.blueBlockWindow(bluestParent, dm.difficultyAdjustmentWindowSize+1)
if err != nil {
return 0, err
}
windowMinTimestamp, windowMaxTimeStamp := timestampsWindow.minMaxTimestamps()
windowMinTimestamp, windowMaxTimeStamp, windowsMinIndex, _ := targetsWindow.minMaxTimestamps()
// Remove the last block from the window so to calculate the average target of dag.difficultyAdjustmentWindowSize blocks
targetsWindow := timestampsWindow[:dm.difficultyAdjustmentWindowSize]
targetsWindow.remove(windowsMinIndex)
// Calculate new target difficulty as:
// averageWindowTarget * (windowMinTimestamp / (targetTimePerBlock * windowSize))