stasatdaglabs 1f56a68a28
Add an RPC command: EstimateNetworkHashesPerSecond (#1686)
* Implement EstimateNetworkHashesPerSecond.

* Fix failing tests.

* Add request/response messages to the .proto files.

* Add the EstimateNetworkHashesPerSecond RPC command.

* Add the EstimateNetworkHashesPerSecond RPC client function.

* Add the EstimateNetworkHashesPerSecond RPC command to kaspactl.

* Disallow windowSize lesser than 2.

* Fix wrong scale (milliseconds instead of seconds).

* Handle windowHashes being 0.
2021-04-22 15:18:21 +03:00

65 lines
2.1 KiB
Go

package difficultymanager
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/pkg/errors"
"math/big"
)
func (dm *difficultyManager) EstimateNetworkHashesPerSecond(windowSize int) (uint64, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "EstimateNetworkHashesPerSecond")
defer onEnd()
stagingArea := model.NewStagingArea()
return dm.estimateNetworkHashesPerSecond(stagingArea, windowSize)
}
func (dm *difficultyManager) estimateNetworkHashesPerSecond(stagingArea *model.StagingArea, windowSize int) (uint64, error) {
if windowSize < 2 {
return 0, errors.Errorf("windowSize must be equal to or greater than 2")
}
blockWindow, windowHashes, err := dm.blockWindow(stagingArea, model.VirtualBlockHash, windowSize)
if err != nil {
return 0, err
}
// return 0 if no blocks had been mined yet
if len(windowHashes) == 0 {
return 0, nil
}
minWindowTimestamp, maxWindowTimestamp, _, _ := blockWindow.minMaxTimestamps()
if minWindowTimestamp == maxWindowTimestamp {
return 0, errors.Errorf("min window timestamp is equal to the max window timestamp")
}
firstHash := windowHashes[0]
firstBlockGHOSTDAGData, err := dm.ghostdagStore.Get(dm.databaseContext, stagingArea, firstHash)
if err != nil {
return 0, err
}
firstBlockBlueWork := firstBlockGHOSTDAGData.BlueWork()
minWindowBlueWork := firstBlockBlueWork
maxWindowBlueWork := firstBlockBlueWork
for _, hash := range windowHashes[1:] {
blockGHOSTDAGData, err := dm.ghostdagStore.Get(dm.databaseContext, stagingArea, hash)
if err != nil {
return 0, err
}
blockBlueWork := blockGHOSTDAGData.BlueWork()
if blockBlueWork.Cmp(minWindowBlueWork) < 0 {
minWindowBlueWork = blockBlueWork
}
if blockBlueWork.Cmp(maxWindowBlueWork) > 0 {
maxWindowBlueWork = blockBlueWork
}
}
nominator := new(big.Int).Sub(maxWindowBlueWork, minWindowBlueWork)
denominator := big.NewInt((maxWindowTimestamp - minWindowTimestamp) / 1000) // Divided by 1000 to convert milliseconds to seconds
networkHashesPerSecondBigInt := new(big.Int).Div(nominator, denominator)
return networkHashesPerSecondBigInt.Uint64(), nil
}