mirror of
https://github.com/kaspanet/kaspad.git
synced 2026-02-22 03:32:55 +00:00
Compare commits
1 Commits
patch7
...
testnet-ma
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
642bdd9c9d |
@@ -92,14 +92,11 @@ type RPCBlockLevelParents struct {
|
||||
|
||||
// RPCBlockVerboseData holds verbose data about a block
|
||||
type RPCBlockVerboseData struct {
|
||||
Hash string
|
||||
Difficulty float64
|
||||
SelectedParentHash string
|
||||
TransactionIDs []string
|
||||
IsHeaderOnly bool
|
||||
BlueScore uint64
|
||||
ChildrenHashes []string
|
||||
MergeSetBluesHashes []string
|
||||
MergeSetRedsHashes []string
|
||||
IsChainBlock bool
|
||||
Hash string
|
||||
Difficulty float64
|
||||
SelectedParentHash string
|
||||
TransactionIDs []string
|
||||
IsHeaderOnly bool
|
||||
BlueScore uint64
|
||||
ChildrenHashes []string
|
||||
}
|
||||
|
||||
@@ -77,37 +77,14 @@ func (flow *handleIBDFlow) runIBDIfNotRunning(block *externalapi.DomainBlock) er
|
||||
}()
|
||||
|
||||
highHash := consensushashing.BlockHash(block)
|
||||
log.Criticalf("IBD started with peer %s and highHash %s", flow.peer, highHash)
|
||||
log.Criticalf("Syncing blocks up to %s", highHash)
|
||||
log.Criticalf("Trying to find highest shared chain block with peer %s with high hash %s", flow.peer, highHash)
|
||||
log.Debugf("IBD started with peer %s and highHash %s", flow.peer, highHash)
|
||||
log.Debugf("Syncing blocks up to %s", highHash)
|
||||
log.Debugf("Trying to find highest shared chain block with peer %s with high hash %s", flow.peer, highHash)
|
||||
highestSharedBlockHash, highestSharedBlockFound, err := flow.findHighestSharedBlockHash(highHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Criticalf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
|
||||
if highestSharedBlockFound {
|
||||
checkpoint, err := externalapi.NewDomainHashFromString("f4a415f28990806a899a208b77930fa5a58f3a94876c3cbe814e60a7ed22824f")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
info, err := flow.Domain().Consensus().GetBlockInfo(checkpoint)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if info.Exists {
|
||||
isInSelectedParentChainOf, err := flow.Domain().Consensus().IsInSelectedParentChainOf(checkpoint, highestSharedBlockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !isInSelectedParentChainOf {
|
||||
log.Criticalf("Stopped IBD because the checkpoint %s is not in the selected chain of %s", checkpoint, highestSharedBlockHash)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
log.Debugf("Found highest shared chain block %s with peer %s", highestSharedBlockHash, flow.peer)
|
||||
|
||||
shouldDownloadHeadersProof, shouldSync, err := flow.shouldSyncAndShouldDownloadHeadersProof(block, highestSharedBlockFound)
|
||||
if err != nil {
|
||||
@@ -347,7 +324,7 @@ func (flow *handleIBDFlow) syncPruningPointFutureHeaders(consensus externalapi.C
|
||||
return nil
|
||||
}
|
||||
for _, header := range ibdBlocksMessage.BlockHeaders {
|
||||
_, err := flow.processHeader(consensus, header)
|
||||
err = flow.processHeader(consensus, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -388,7 +365,7 @@ func (flow *handleIBDFlow) receiveHeaders() (msgIBDBlock *appmessage.BlockHeader
|
||||
}
|
||||
}
|
||||
|
||||
func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlockHeader *appmessage.MsgBlockHeader) (bool, error) {
|
||||
func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlockHeader *appmessage.MsgBlockHeader) error {
|
||||
header := appmessage.BlockHeaderToDomainBlockHeader(msgBlockHeader)
|
||||
block := &externalapi.DomainBlock{
|
||||
Header: header,
|
||||
@@ -398,26 +375,27 @@ func (flow *handleIBDFlow) processHeader(consensus externalapi.Consensus, msgBlo
|
||||
blockHash := consensushashing.BlockHash(block)
|
||||
blockInfo, err := consensus.GetBlockInfo(blockHash)
|
||||
if err != nil {
|
||||
return false, err
|
||||
return err
|
||||
}
|
||||
if blockInfo.Exists {
|
||||
log.Debugf("Block header %s is already in the DAG. Skipping...", blockHash)
|
||||
return false, nil
|
||||
return nil
|
||||
}
|
||||
_, err = consensus.ValidateAndInsertBlock(block, false)
|
||||
if err != nil {
|
||||
if !errors.As(err, &ruleerrors.RuleError{}) {
|
||||
return false, errors.Wrapf(err, "failed to process header %s during IBD", blockHash)
|
||||
return errors.Wrapf(err, "failed to process header %s during IBD", blockHash)
|
||||
}
|
||||
|
||||
if errors.Is(err, ruleerrors.ErrDuplicateBlock) {
|
||||
log.Debugf("Skipping block header %s as it is a duplicate", blockHash)
|
||||
} else {
|
||||
log.Infof("Rejected block header %s from %s during IBD: %s", blockHash, flow.peer, err)
|
||||
return false, protocolerrors.Wrapf(true, err, "got invalid block header %s during IBD", blockHash)
|
||||
return protocolerrors.Wrapf(true, err, "got invalid block header %s during IBD", blockHash)
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (flow *handleIBDFlow) validatePruningPointFutureHeaderTimestamps() error {
|
||||
|
||||
@@ -22,7 +22,6 @@ type TransactionsRelayContext interface {
|
||||
SharedRequestedTransactions() *flowcontext.SharedRequestedTransactions
|
||||
OnTransactionAddedToMempool()
|
||||
EnqueueTransactionIDsForPropagation(transactionIDs []*externalapi.DomainTransactionID) error
|
||||
IsIBDRunning() bool
|
||||
}
|
||||
|
||||
type handleRelayedTransactionsFlow struct {
|
||||
@@ -50,10 +49,6 @@ func (flow *handleRelayedTransactionsFlow) start() error {
|
||||
return err
|
||||
}
|
||||
|
||||
if flow.IsIBDRunning() {
|
||||
continue
|
||||
}
|
||||
|
||||
requestedIDs, err := flow.requestInvTransactions(inv)
|
||||
if err != nil {
|
||||
return err
|
||||
|
||||
@@ -47,10 +47,6 @@ func (m *mocTransactionsRelayContext) EnqueueTransactionIDsForPropagation(transa
|
||||
func (m *mocTransactionsRelayContext) OnTransactionAddedToMempool() {
|
||||
}
|
||||
|
||||
func (m *mocTransactionsRelayContext) IsIBDRunning() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// TestHandleRelayedTransactionsNotFound tests the flow of HandleRelayedTransactions when the peer doesn't
|
||||
// have the requested transactions in the mempool.
|
||||
func TestHandleRelayedTransactionsNotFound(t *testing.T) {
|
||||
|
||||
@@ -56,29 +56,21 @@ func (ctx *Context) PopulateBlockWithVerboseData(block *appmessage.RPCBlock, dom
|
||||
"invalid block")
|
||||
}
|
||||
|
||||
_, childrenHashes, err := ctx.Domain.Consensus().GetBlockRelations(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
isChainBlock, err := ctx.Domain.Consensus().IsChainBlock(blockHash)
|
||||
_, selectedParentHash, childrenHashes, err := ctx.Domain.Consensus().GetBlockRelations(blockHash)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
block.VerboseData = &appmessage.RPCBlockVerboseData{
|
||||
Hash: blockHash.String(),
|
||||
Difficulty: ctx.GetDifficultyRatio(domainBlockHeader.Bits(), ctx.Config.ActiveNetParams),
|
||||
ChildrenHashes: hashes.ToStrings(childrenHashes),
|
||||
IsHeaderOnly: blockInfo.BlockStatus == externalapi.StatusHeaderOnly,
|
||||
BlueScore: blockInfo.BlueScore,
|
||||
MergeSetBluesHashes: hashes.ToStrings(blockInfo.MergeSetBlues),
|
||||
MergeSetRedsHashes: hashes.ToStrings(blockInfo.MergeSetReds),
|
||||
IsChainBlock: isChainBlock,
|
||||
Hash: blockHash.String(),
|
||||
Difficulty: ctx.GetDifficultyRatio(domainBlockHeader.Bits(), ctx.Config.ActiveNetParams),
|
||||
ChildrenHashes: hashes.ToStrings(childrenHashes),
|
||||
IsHeaderOnly: blockInfo.BlockStatus == externalapi.StatusHeaderOnly,
|
||||
BlueScore: blockInfo.BlueScore,
|
||||
}
|
||||
// selectedParentHash will be nil in the genesis block
|
||||
if blockInfo.SelectedParent != nil {
|
||||
block.VerboseData.SelectedParentHash = blockInfo.SelectedParent.String()
|
||||
if selectedParentHash != nil {
|
||||
block.VerboseData.SelectedParentHash = selectedParentHash.String()
|
||||
}
|
||||
|
||||
if blockInfo.BlockStatus == externalapi.StatusHeaderOnly {
|
||||
|
||||
@@ -3,7 +3,6 @@ package main
|
||||
import (
|
||||
"reflect"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/proto"
|
||||
@@ -150,24 +149,12 @@ func stringToValue(parameterDesc *parameterDescription, valueStr string) (reflec
|
||||
|
||||
value = pointer.Interface()
|
||||
|
||||
case reflect.Slice:
|
||||
sliceType := parameterDesc.typeof.Elem()
|
||||
if sliceType.Kind() != reflect.String {
|
||||
return reflect.Value{},
|
||||
errors.Errorf("Unsupported slice type '%s' for parameter '%s'",
|
||||
sliceType,
|
||||
parameterDesc.name)
|
||||
}
|
||||
if valueStr == "" {
|
||||
value = []string{}
|
||||
} else {
|
||||
value = strings.Split(valueStr, ",")
|
||||
}
|
||||
// Int and uint are not supported because their size is platform-dependant
|
||||
case reflect.Int,
|
||||
reflect.Uint,
|
||||
// Other types are not supported simply because they are not used in any command right now
|
||||
// but support can be added if and when needed
|
||||
reflect.Slice,
|
||||
reflect.Func,
|
||||
reflect.Interface,
|
||||
reflect.Map,
|
||||
|
||||
@@ -15,7 +15,6 @@ const (
|
||||
createUnsignedTransactionSubCmd = "create-unsigned-transaction"
|
||||
signSubCmd = "sign"
|
||||
broadcastSubCmd = "broadcast"
|
||||
parseSubCmd = "parse"
|
||||
showAddressesSubCmd = "show-addresses"
|
||||
newAddressSubCmd = "new-address"
|
||||
dumpUnencryptedDataSubCmd = "dump-unencrypted-data"
|
||||
@@ -80,13 +79,6 @@ type broadcastConfig struct {
|
||||
config.NetworkFlags
|
||||
}
|
||||
|
||||
type parseConfig struct {
|
||||
Transaction string `long:"transaction" short:"t" description:"The transaction to parse (encoded in hex)"`
|
||||
TransactionFile string `long:"transaction-file" short:"F" description:"The file containing the transaction to parse (encoded in hex)"`
|
||||
Verbose bool `long:"verbose" short:"v" description:"Verbose: show transaction inputs"`
|
||||
config.NetworkFlags
|
||||
}
|
||||
|
||||
type showAddressesConfig struct {
|
||||
DaemonAddress string `long:"daemonaddress" short:"d" description:"Wallet daemon server to connect to (default: localhost:8082)"`
|
||||
config.NetworkFlags
|
||||
@@ -141,10 +133,6 @@ func parseCommandLine() (subCommand string, config interface{}) {
|
||||
parser.AddCommand(broadcastSubCmd, "Broadcast the given transaction",
|
||||
"Broadcast the given transaction", broadcastConf)
|
||||
|
||||
parseConf := &parseConfig{}
|
||||
parser.AddCommand(parseSubCmd, "Parse the given transaction and print its contents",
|
||||
"Parse the given transaction and print its contents", parseConf)
|
||||
|
||||
showAddressesConf := &showAddressesConfig{DaemonAddress: defaultListen}
|
||||
parser.AddCommand(showAddressesSubCmd, "Shows all generated public addresses of the current wallet",
|
||||
"Shows all generated public addresses of the current wallet", showAddressesConf)
|
||||
@@ -219,13 +207,6 @@ func parseCommandLine() (subCommand string, config interface{}) {
|
||||
printErrorAndExit(err)
|
||||
}
|
||||
config = broadcastConf
|
||||
case parseSubCmd:
|
||||
combineNetworkFlags(&parseConf.NetworkFlags, &cfg.NetworkFlags)
|
||||
err := parseConf.ResolveNetwork(parser)
|
||||
if err != nil {
|
||||
printErrorAndExit(err)
|
||||
}
|
||||
config = parseConf
|
||||
case showAddressesSubCmd:
|
||||
combineNetworkFlags(&showAddressesConf.NetworkFlags, &cfg.NetworkFlags)
|
||||
err := showAddressesConf.ResolveNetwork(parser)
|
||||
|
||||
@@ -19,8 +19,6 @@ func main() {
|
||||
err = sign(config.(*signConfig))
|
||||
case broadcastSubCmd:
|
||||
err = broadcast(config.(*broadcastConfig))
|
||||
case parseSubCmd:
|
||||
err = parse(config.(*parseConfig))
|
||||
case showAddressesSubCmd:
|
||||
err = showAddresses(config.(*showAddressesConfig))
|
||||
case newAddressSubCmd:
|
||||
|
||||
@@ -1,83 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet/serialization"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
|
||||
"github.com/pkg/errors"
|
||||
"io/ioutil"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func parse(conf *parseConfig) error {
|
||||
if conf.Transaction == "" && conf.TransactionFile == "" {
|
||||
return errors.Errorf("Either --transaction or --transaction-file is required")
|
||||
}
|
||||
if conf.Transaction != "" && conf.TransactionFile != "" {
|
||||
return errors.Errorf("Both --transaction and --transaction-file cannot be passed at the same time")
|
||||
}
|
||||
|
||||
transactionHex := conf.Transaction
|
||||
if conf.TransactionFile != "" {
|
||||
transactionHexBytes, err := ioutil.ReadFile(conf.TransactionFile)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "Could not read hex from %s", conf.TransactionFile)
|
||||
}
|
||||
transactionHex = strings.TrimSpace(string(transactionHexBytes))
|
||||
}
|
||||
|
||||
transaction, err := hex.DecodeString(transactionHex)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
partiallySignedTransaction, err := serialization.DeserializePartiallySignedTransaction(transaction)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Transaction ID: \t%s\n", consensushashing.TransactionID(partiallySignedTransaction.Tx))
|
||||
fmt.Println()
|
||||
|
||||
allInputSompi := uint64(0)
|
||||
for index, input := range partiallySignedTransaction.Tx.Inputs {
|
||||
partiallySignedInput := partiallySignedTransaction.PartiallySignedInputs[index]
|
||||
|
||||
if conf.Verbose {
|
||||
fmt.Printf("Input %d: \tOutpoint: %s:%d \tAmount: %.2f Kaspa\n", index, input.PreviousOutpoint.TransactionID,
|
||||
input.PreviousOutpoint.Index, float64(partiallySignedInput.PrevOutput.Value)/float64(constants.SompiPerKaspa))
|
||||
}
|
||||
|
||||
allInputSompi += partiallySignedInput.PrevOutput.Value
|
||||
}
|
||||
if conf.Verbose {
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
allOutputSompi := uint64(0)
|
||||
for index, output := range partiallySignedTransaction.Tx.Outputs {
|
||||
scriptPublicKeyType, scriptPublicKeyAddress, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, conf.ActiveNetParams)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addressString := scriptPublicKeyAddress.EncodeAddress()
|
||||
if scriptPublicKeyType == txscript.NonStandardTy {
|
||||
scriptPublicKeyHex := hex.EncodeToString(output.ScriptPublicKey.Script)
|
||||
addressString = fmt.Sprintf("<Non-standard transaction script public key: %s>", scriptPublicKeyHex)
|
||||
}
|
||||
|
||||
fmt.Printf("Output %d: \tRecipient: %s \tAmount: %.2f Kaspa\n",
|
||||
index, addressString, float64(output.Value)/float64(constants.SompiPerKaspa))
|
||||
|
||||
allOutputSompi += output.Value
|
||||
}
|
||||
fmt.Println()
|
||||
|
||||
fmt.Printf("Fee:\t%d Sompi\n", allInputSompi-allOutputSompi)
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -286,15 +286,13 @@ func (s *consensus) GetBlockInfo(blockHash *externalapi.DomainHash) (*externalap
|
||||
|
||||
blockInfo.BlueScore = ghostdagData.BlueScore()
|
||||
blockInfo.BlueWork = ghostdagData.BlueWork()
|
||||
blockInfo.SelectedParent = ghostdagData.SelectedParent()
|
||||
blockInfo.MergeSetBlues = ghostdagData.MergeSetBlues()
|
||||
blockInfo.MergeSetReds = ghostdagData.MergeSetReds()
|
||||
|
||||
return blockInfo, nil
|
||||
}
|
||||
|
||||
func (s *consensus) GetBlockRelations(blockHash *externalapi.DomainHash) (
|
||||
parents []*externalapi.DomainHash, children []*externalapi.DomainHash, err error) {
|
||||
parents []*externalapi.DomainHash, selectedParent *externalapi.DomainHash,
|
||||
children []*externalapi.DomainHash, err error) {
|
||||
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
@@ -303,10 +301,15 @@ func (s *consensus) GetBlockRelations(blockHash *externalapi.DomainHash) (
|
||||
|
||||
blockRelation, err := s.blockRelationStores[0].BlockRelation(s.databaseContext, stagingArea, blockHash)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return blockRelation.Parents, blockRelation.Children, nil
|
||||
blockGHOSTDAGData, err := s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, blockHash, false)
|
||||
if err != nil {
|
||||
return nil, nil, nil, err
|
||||
}
|
||||
|
||||
return blockRelation.Parents, blockGHOSTDAGData.SelectedParent(), blockRelation.Children, nil
|
||||
}
|
||||
|
||||
func (s *consensus) GetBlockAcceptanceData(blockHash *externalapi.DomainHash) (externalapi.AcceptanceData, error) {
|
||||
@@ -821,16 +824,3 @@ func (s *consensus) TrustedGHOSTDAGData(blockHash *externalapi.DomainHash) (*ext
|
||||
|
||||
return ghostdagData, nil
|
||||
}
|
||||
|
||||
func (s *consensus) IsChainBlock(blockHash *externalapi.DomainHash) (bool, error) {
|
||||
s.lock.Lock()
|
||||
defer s.lock.Unlock()
|
||||
|
||||
stagingArea := model.NewStagingArea()
|
||||
virtualGHOSTDAGData, err := s.ghostdagDataStores[0].Get(s.databaseContext, stagingArea, model.VirtualBlockHash, false)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return s.dagTopologyManagers[0].IsInSelectedParentChainOf(stagingArea, blockHash, virtualGHOSTDAGData.SelectedParent())
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
package blockwindowheapslicestore
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
type shardKey struct {
|
||||
hash externalapi.DomainHash
|
||||
windowSize int
|
||||
}
|
||||
|
||||
type blockWindowHeapSliceStagingShard struct {
|
||||
store *blockWindowHeapSliceStore
|
||||
toAdd map[shardKey][]*externalapi.BlockGHOSTDAGDataHashPair
|
||||
}
|
||||
|
||||
func (bss *blockWindowHeapSliceStore) stagingShard(stagingArea *model.StagingArea) *blockWindowHeapSliceStagingShard {
|
||||
return stagingArea.GetOrCreateShard(bss.shardID, func() model.StagingShard {
|
||||
return &blockWindowHeapSliceStagingShard{
|
||||
store: bss,
|
||||
toAdd: make(map[shardKey][]*externalapi.BlockGHOSTDAGDataHashPair),
|
||||
}
|
||||
}).(*blockWindowHeapSliceStagingShard)
|
||||
}
|
||||
|
||||
func (bsss *blockWindowHeapSliceStagingShard) Commit(_ model.DBTransaction) error {
|
||||
for key, heapSlice := range bsss.toAdd {
|
||||
bsss.store.cache.Add(&key.hash, key.windowSize, heapSlice)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (bsss *blockWindowHeapSliceStagingShard) isStaged() bool {
|
||||
return len(bsss.toAdd) != 0
|
||||
}
|
||||
|
||||
func newShardKey(hash *externalapi.DomainHash, windowSize int) shardKey {
|
||||
return shardKey{
|
||||
hash: *hash,
|
||||
windowSize: windowSize,
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package blockwindowheapslicestore
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/lrucachehashandwindowsizetoblockghostdagdatahashpairs"
|
||||
"github.com/kaspanet/kaspad/infrastructure/db/database"
|
||||
"github.com/kaspanet/kaspad/util/staging"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type blockWindowHeapSliceStore struct {
|
||||
shardID model.StagingShardID
|
||||
cache *lrucachehashandwindowsizetoblockghostdagdatahashpairs.LRUCache
|
||||
}
|
||||
|
||||
// New instantiates a new WindowHeapSliceStore
|
||||
func New(cacheSize int, preallocate bool) model.WindowHeapSliceStore {
|
||||
return &blockWindowHeapSliceStore{
|
||||
shardID: staging.GenerateShardingID(),
|
||||
cache: lrucachehashandwindowsizetoblockghostdagdatahashpairs.New(cacheSize, preallocate),
|
||||
}
|
||||
}
|
||||
|
||||
// Stage stages the given blockStatus for the given blockHash
|
||||
func (bss *blockWindowHeapSliceStore) Stage(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, windowSize int, heapSlice []*externalapi.BlockGHOSTDAGDataHashPair) {
|
||||
stagingShard := bss.stagingShard(stagingArea)
|
||||
stagingShard.toAdd[newShardKey(blockHash, windowSize)] = heapSlice
|
||||
}
|
||||
|
||||
func (bss *blockWindowHeapSliceStore) IsStaged(stagingArea *model.StagingArea) bool {
|
||||
return bss.stagingShard(stagingArea).isStaged()
|
||||
}
|
||||
|
||||
func (bss *blockWindowHeapSliceStore) Get(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, windowSize int) ([]*externalapi.BlockGHOSTDAGDataHashPair, error) {
|
||||
stagingShard := bss.stagingShard(stagingArea)
|
||||
|
||||
if heapSlice, ok := stagingShard.toAdd[newShardKey(blockHash, windowSize)]; ok {
|
||||
return heapSlice, nil
|
||||
}
|
||||
|
||||
if heapSlice, ok := bss.cache.Get(blockHash, windowSize); ok {
|
||||
return heapSlice, nil
|
||||
}
|
||||
|
||||
return nil, errors.Wrap(database.ErrNotFound, "Window heap slice not found")
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockwindowheapslicestore"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/datastructures/daawindowstore"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/processes/blockparentbuilder"
|
||||
@@ -145,10 +144,9 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
|
||||
finalityStore := finalitystore.New(prefixBucket, 200, preallocateCaches)
|
||||
headersSelectedChainStore := headersselectedchainstore.New(prefixBucket, pruningWindowSizeForCaches, preallocateCaches)
|
||||
daaBlocksStore := daablocksstore.New(prefixBucket, pruningWindowSizeForCaches, int(config.FinalityDepth()), preallocateCaches)
|
||||
windowHeapSliceStore := blockwindowheapslicestore.New(2000, preallocateCaches)
|
||||
|
||||
blockRelationStores, reachabilityDataStores, ghostdagDataStores := dagStores(config, prefixBucket, pruningWindowSizePlusFinalityDepthForCache, pruningWindowSizeForCaches, preallocateCaches)
|
||||
reachabilityManagers, dagTopologyManagers, ghostdagManagers, dagTraversalManagers := f.dagProcesses(config, dbManager, blockHeaderStore, daaWindowStore, windowHeapSliceStore, blockRelationStores, reachabilityDataStores, ghostdagDataStores)
|
||||
reachabilityManagers, dagTopologyManagers, ghostdagManagers, dagTraversalManagers := f.dagProcesses(config, dbManager, blockHeaderStore, daaWindowStore, blockRelationStores, reachabilityDataStores, ghostdagDataStores)
|
||||
|
||||
blockRelationStore := blockRelationStores[0]
|
||||
reachabilityDataStore := reachabilityDataStores[0]
|
||||
@@ -602,7 +600,6 @@ func (f *factory) dagProcesses(config *Config,
|
||||
dbManager model.DBManager,
|
||||
blockHeaderStore model.BlockHeaderStore,
|
||||
daaWindowStore model.BlocksWithTrustedDataDAAWindowStore,
|
||||
windowHeapSliceStore model.WindowHeapSliceStore,
|
||||
blockRelationStores []model.BlockRelationStore,
|
||||
reachabilityDataStores []model.ReachabilityDataStore,
|
||||
ghostdagDataStores []model.GHOSTDAGDataStore) (
|
||||
@@ -644,7 +641,6 @@ func (f *factory) dagProcesses(config *Config,
|
||||
reachabilityDataStores[i],
|
||||
ghostdagManagers[i],
|
||||
daaWindowStore,
|
||||
windowHeapSliceStore,
|
||||
config.GenesisHash,
|
||||
config.DifficultyAdjustmentWindowSize)
|
||||
}
|
||||
|
||||
@@ -4,24 +4,18 @@ import "math/big"
|
||||
|
||||
// BlockInfo contains various information about a specific block
|
||||
type BlockInfo struct {
|
||||
Exists bool
|
||||
BlockStatus BlockStatus
|
||||
BlueScore uint64
|
||||
BlueWork *big.Int
|
||||
SelectedParent *DomainHash
|
||||
MergeSetBlues []*DomainHash
|
||||
MergeSetReds []*DomainHash
|
||||
Exists bool
|
||||
BlockStatus BlockStatus
|
||||
BlueScore uint64
|
||||
BlueWork *big.Int
|
||||
}
|
||||
|
||||
// Clone returns a clone of BlockInfo
|
||||
func (bi *BlockInfo) Clone() *BlockInfo {
|
||||
return &BlockInfo{
|
||||
Exists: bi.Exists,
|
||||
BlockStatus: bi.BlockStatus.Clone(),
|
||||
BlueScore: bi.BlueScore,
|
||||
BlueWork: new(big.Int).Set(bi.BlueWork),
|
||||
SelectedParent: bi.SelectedParent,
|
||||
MergeSetBlues: CloneHashes(bi.MergeSetBlues),
|
||||
MergeSetReds: CloneHashes(bi.MergeSetReds),
|
||||
Exists: bi.Exists,
|
||||
BlockStatus: bi.BlockStatus.Clone(),
|
||||
BlueScore: bi.BlueScore,
|
||||
BlueWork: new(big.Int).Set(bi.BlueWork),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,83 +14,31 @@ func initTestBlockInfoStructsForClone() []*BlockInfo {
|
||||
BlockStatus(0x01),
|
||||
0,
|
||||
big.NewInt(0),
|
||||
nil,
|
||||
[]*DomainHash{},
|
||||
[]*DomainHash{},
|
||||
}, {
|
||||
true,
|
||||
BlockStatus(0x02),
|
||||
0,
|
||||
big.NewInt(0),
|
||||
nil,
|
||||
[]*DomainHash{},
|
||||
[]*DomainHash{},
|
||||
}, {
|
||||
true,
|
||||
1,
|
||||
1,
|
||||
big.NewInt(0),
|
||||
nil,
|
||||
[]*DomainHash{},
|
||||
[]*DomainHash{},
|
||||
}, {
|
||||
true,
|
||||
255,
|
||||
2,
|
||||
big.NewInt(0),
|
||||
nil,
|
||||
[]*DomainHash{},
|
||||
[]*DomainHash{},
|
||||
}, {
|
||||
true,
|
||||
0,
|
||||
3,
|
||||
big.NewInt(0),
|
||||
nil,
|
||||
[]*DomainHash{},
|
||||
[]*DomainHash{},
|
||||
}, {
|
||||
true,
|
||||
BlockStatus(0x01),
|
||||
0,
|
||||
big.NewInt(1),
|
||||
nil,
|
||||
[]*DomainHash{},
|
||||
[]*DomainHash{},
|
||||
}, {
|
||||
false,
|
||||
BlockStatus(0x01),
|
||||
0,
|
||||
big.NewInt(1),
|
||||
NewDomainHashFromByteArray(&[DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01}),
|
||||
[]*DomainHash{
|
||||
NewDomainHashFromByteArray(&[DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02}),
|
||||
NewDomainHashFromByteArray(&[DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03}),
|
||||
},
|
||||
[]*DomainHash{
|
||||
NewDomainHashFromByteArray(&[DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04}),
|
||||
NewDomainHashFromByteArray(&[DomainHashSize]byte{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05}),
|
||||
},
|
||||
},
|
||||
}
|
||||
return tests
|
||||
|
||||
@@ -16,7 +16,7 @@ type Consensus interface {
|
||||
GetBlockEvenIfHeaderOnly(blockHash *DomainHash) (*DomainBlock, error)
|
||||
GetBlockHeader(blockHash *DomainHash) (BlockHeader, error)
|
||||
GetBlockInfo(blockHash *DomainHash) (*BlockInfo, error)
|
||||
GetBlockRelations(blockHash *DomainHash) (parents []*DomainHash, children []*DomainHash, err error)
|
||||
GetBlockRelations(blockHash *DomainHash) (parents []*DomainHash, selectedParent *DomainHash, children []*DomainHash, err error)
|
||||
GetBlockAcceptanceData(blockHash *DomainHash) (AcceptanceData, error)
|
||||
|
||||
GetHashesBetween(lowHash, highHash *DomainHash, maxBlocks uint64) (hashes []*DomainHash, actualHighHash *DomainHash, err error)
|
||||
@@ -50,5 +50,4 @@ type Consensus interface {
|
||||
TrustedDataDataDAAHeader(trustedBlockHash, daaBlockHash *DomainHash, daaBlockWindowIndex uint64) (*TrustedDataDataDAAHeader, error)
|
||||
TrustedBlockAssociatedGHOSTDAGDataBlockHashes(blockHash *DomainHash) ([]*DomainHash, error)
|
||||
TrustedGHOSTDAGData(blockHash *DomainHash) (*BlockGHOSTDAGData, error)
|
||||
IsChainBlock(blockHash *DomainHash) (bool, error)
|
||||
}
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
package model
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
// WindowHeapSliceStore caches the slices that are needed for the heap implementation of DAGTraversalManager.BlockWindow
|
||||
type WindowHeapSliceStore interface {
|
||||
Store
|
||||
Stage(stagingArea *StagingArea, blockHash *externalapi.DomainHash, windowSize int, pairs []*externalapi.BlockGHOSTDAGDataHashPair)
|
||||
IsStaged(stagingArea *StagingArea) bool
|
||||
Get(stagingArea *StagingArea, blockHash *externalapi.DomainHash, windowSize int) ([]*externalapi.BlockGHOSTDAGDataHashPair, error)
|
||||
}
|
||||
@@ -152,18 +152,6 @@ func (dtm *dagTraversalManager) newSizedUpHeap(stagingArea *model.StagingArea, c
|
||||
return &h
|
||||
}
|
||||
|
||||
func (dtm *dagTraversalManager) newSizedUpHeapFromSlice(stagingArea *model.StagingArea, slice []*externalapi.BlockGHOSTDAGDataHashPair) *sizedUpBlockHeap {
|
||||
sliceClone := make([]*externalapi.BlockGHOSTDAGDataHashPair, len(slice), cap(slice))
|
||||
copy(sliceClone, slice)
|
||||
h := sizedUpBlockHeap{
|
||||
impl: upHeap{baseHeap{slice: sliceClone, ghostdagManager: dtm.ghostdagManager}},
|
||||
ghostdagStore: dtm.ghostdagDataStore,
|
||||
dbContext: dtm.databaseContext,
|
||||
stagingArea: stagingArea,
|
||||
}
|
||||
return &h
|
||||
}
|
||||
|
||||
// len returns the length of this heap
|
||||
func (sbh *sizedUpBlockHeap) len() int {
|
||||
return sbh.impl.Len()
|
||||
|
||||
@@ -18,7 +18,6 @@ type dagTraversalManager struct {
|
||||
daaWindowStore model.BlocksWithTrustedDataDAAWindowStore
|
||||
genesisHash *externalapi.DomainHash
|
||||
difficultyAdjustmentWindowSize int
|
||||
windowHeapSliceStore model.WindowHeapSliceStore
|
||||
}
|
||||
|
||||
// New instantiates a new DAGTraversalManager
|
||||
@@ -29,7 +28,6 @@ func New(
|
||||
reachabilityDataStore model.ReachabilityDataStore,
|
||||
ghostdagManager model.GHOSTDAGManager,
|
||||
daaWindowStore model.BlocksWithTrustedDataDAAWindowStore,
|
||||
windowHeapSliceStore model.WindowHeapSliceStore,
|
||||
genesisHash *externalapi.DomainHash,
|
||||
difficultyAdjustmentWindowSize int) model.DAGTraversalManager {
|
||||
return &dagTraversalManager{
|
||||
@@ -42,7 +40,6 @@ func New(
|
||||
|
||||
genesisHash: genesisHash,
|
||||
difficultyAdjustmentWindowSize: difficultyAdjustmentWindowSize,
|
||||
windowHeapSliceStore: windowHeapSliceStore,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ func (dtm *dagTraversalManager) DAABlockWindow(stagingArea *model.StagingArea, h
|
||||
func (dtm *dagTraversalManager) BlockWindow(stagingArea *model.StagingArea, highHash *externalapi.DomainHash,
|
||||
windowSize int) ([]*externalapi.DomainHash, error) {
|
||||
|
||||
windowHeap, err := dtm.blockWindowHeap(stagingArea, highHash, windowSize)
|
||||
windowHeap, err := dtm.calculateBlockWindowHeap(stagingArea, highHash, windowSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -28,28 +28,6 @@ func (dtm *dagTraversalManager) BlockWindow(stagingArea *model.StagingArea, high
|
||||
return window, nil
|
||||
}
|
||||
|
||||
func (dtm *dagTraversalManager) blockWindowHeap(stagingArea *model.StagingArea,
|
||||
highHash *externalapi.DomainHash, windowSize int) (*sizedUpBlockHeap, error) {
|
||||
windowHeapSlice, err := dtm.windowHeapSliceStore.Get(stagingArea, highHash, windowSize)
|
||||
sliceNotCached := database.IsNotFoundError(err)
|
||||
if !sliceNotCached && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !sliceNotCached {
|
||||
return dtm.newSizedUpHeapFromSlice(stagingArea, windowHeapSlice), nil
|
||||
}
|
||||
|
||||
heap, err := dtm.calculateBlockWindowHeap(stagingArea, highHash, windowSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !highHash.Equal(model.VirtualBlockHash) {
|
||||
dtm.windowHeapSliceStore.Stage(stagingArea, highHash, windowSize, heap.impl.slice)
|
||||
}
|
||||
return heap, nil
|
||||
}
|
||||
|
||||
func (dtm *dagTraversalManager) calculateBlockWindowHeap(stagingArea *model.StagingArea,
|
||||
highHash *externalapi.DomainHash, windowSize int) (*sizedUpBlockHeap, error) {
|
||||
|
||||
@@ -67,54 +45,18 @@ func (dtm *dagTraversalManager) calculateBlockWindowHeap(stagingArea *model.Stag
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// If the block has a trusted DAA window attached, we just take it as is and don't use cache of selected parent to
|
||||
// build the window. This is because tryPushMergeSet might not be able to find all the GHOSTDAG data that is
|
||||
// associated with the block merge set.
|
||||
_, err = dtm.daaWindowStore.DAAWindowBlock(dtm.databaseContext, stagingArea, current, 0)
|
||||
isNonTrustedBlock := database.IsNotFoundError(err)
|
||||
if !isNonTrustedBlock && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if isNonTrustedBlock && currentGHOSTDAGData.SelectedParent() != nil {
|
||||
windowHeapSlice, err := dtm.windowHeapSliceStore.Get(stagingArea, currentGHOSTDAGData.SelectedParent(), windowSize)
|
||||
selectedParentNotCached := database.IsNotFoundError(err)
|
||||
if !selectedParentNotCached && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !selectedParentNotCached {
|
||||
windowHeap := dtm.newSizedUpHeapFromSlice(stagingArea, windowHeapSlice)
|
||||
if !currentGHOSTDAGData.SelectedParent().Equal(dtm.genesisHash) {
|
||||
selectedParentGHOSTDAGData, err := dtm.ghostdagDataStore.Get(
|
||||
dtm.databaseContext, stagingArea, currentGHOSTDAGData.SelectedParent(), false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
_, err = dtm.tryPushMergeSet(windowHeap, currentGHOSTDAGData, selectedParentGHOSTDAGData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return windowHeap, nil
|
||||
}
|
||||
}
|
||||
|
||||
// Walk down the chain until you finish or find a trusted block and then take complete the rest
|
||||
// of the window with the trusted window.
|
||||
for {
|
||||
if currentGHOSTDAGData.SelectedParent().Equal(dtm.genesisHash) {
|
||||
break
|
||||
}
|
||||
|
||||
_, err := dtm.daaWindowStore.DAAWindowBlock(dtm.databaseContext, stagingArea, current, 0)
|
||||
currentIsNonTrustedBlock := database.IsNotFoundError(err)
|
||||
if !currentIsNonTrustedBlock && err != nil {
|
||||
isNotFoundError := database.IsNotFoundError(err)
|
||||
if !isNotFoundError && err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if !currentIsNonTrustedBlock {
|
||||
if !isNotFoundError {
|
||||
for i := uint64(0); ; i++ {
|
||||
daaBlock, err := dtm.daaWindowStore.DAAWindowBlock(dtm.databaseContext, stagingArea, current, i)
|
||||
if database.IsNotFoundError(err) {
|
||||
@@ -141,60 +83,47 @@ func (dtm *dagTraversalManager) calculateBlockWindowHeap(stagingArea *model.Stag
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
done, err := dtm.tryPushMergeSet(windowHeap, currentGHOSTDAGData, selectedParentGHOSTDAGData)
|
||||
added, err := windowHeap.tryPushWithGHOSTDAGData(currentGHOSTDAGData.SelectedParent(), selectedParentGHOSTDAGData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if done {
|
||||
|
||||
// If the window is full and the selected parent is less than the minimum then we break
|
||||
// because this means that there cannot be any more blocks in the past with higher blueWork
|
||||
if !added {
|
||||
break
|
||||
}
|
||||
|
||||
// Now we go over the merge set.
|
||||
// Remove the SP from the blue merge set because we already added it.
|
||||
mergeSetBlues := currentGHOSTDAGData.MergeSetBlues()[1:]
|
||||
// Go over the merge set in reverse because it's ordered in reverse by blueWork.
|
||||
for i := len(mergeSetBlues) - 1; i >= 0; i-- {
|
||||
added, err := windowHeap.tryPush(mergeSetBlues[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If it's smaller than minimum then we won't be able to add the rest because they're even smaller.
|
||||
if !added {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
mergeSetReds := currentGHOSTDAGData.MergeSetReds()
|
||||
for i := len(mergeSetReds) - 1; i >= 0; i-- {
|
||||
added, err := windowHeap.tryPush(mergeSetReds[i])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// If it's smaller than minimum then we won't be able to add the rest because they're even smaller.
|
||||
if !added {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
current = currentGHOSTDAGData.SelectedParent()
|
||||
currentGHOSTDAGData = selectedParentGHOSTDAGData
|
||||
}
|
||||
|
||||
return windowHeap, nil
|
||||
}
|
||||
|
||||
func (dtm *dagTraversalManager) tryPushMergeSet(windowHeap *sizedUpBlockHeap, currentGHOSTDAGData, selectedParentGHOSTDAGData *externalapi.BlockGHOSTDAGData) (bool, error) {
|
||||
added, err := windowHeap.tryPushWithGHOSTDAGData(currentGHOSTDAGData.SelectedParent(), selectedParentGHOSTDAGData)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
// If the window is full and the selected parent is less than the minimum then we break
|
||||
// because this means that there cannot be any more blocks in the past with higher blueWork
|
||||
if !added {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// Now we go over the merge set.
|
||||
// Remove the SP from the blue merge set because we already added it.
|
||||
mergeSetBlues := currentGHOSTDAGData.MergeSetBlues()[1:]
|
||||
// Go over the merge set in reverse because it's ordered in reverse by blueWork.
|
||||
for i := len(mergeSetBlues) - 1; i >= 0; i-- {
|
||||
added, err := windowHeap.tryPush(mergeSetBlues[i])
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// If it's smaller than minimum then we won't be able to add the rest because they're even smaller.
|
||||
if !added {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
mergeSetReds := currentGHOSTDAGData.MergeSetReds()
|
||||
for i := len(mergeSetReds) - 1; i >= 0; i-- {
|
||||
added, err := windowHeap.tryPush(mergeSetReds[i])
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
// If it's smaller than minimum then we won't be able to add the rest because they're even smaller.
|
||||
if !added {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
@@ -38,8 +38,8 @@ func TestPruning(t *testing.T) {
|
||||
"dag-for-test-pruning.json": {
|
||||
dagconfig.MainnetParams.Name: "503",
|
||||
dagconfig.TestnetParams.Name: "502",
|
||||
dagconfig.DevnetParams.Name: "502",
|
||||
dagconfig.SimnetParams.Name: "503",
|
||||
dagconfig.DevnetParams.Name: "503",
|
||||
dagconfig.SimnetParams.Name: "502",
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@@ -995,13 +995,7 @@ func (pm *pruningManager) ExpectedHeaderPruningPoint(stagingArea *model.StagingA
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Note: the pruning point from the POV of the current block is the first block in its chain that is in depth of pm.pruningDepth and
|
||||
// its finality score is greater than the previous pruning point. This is why the diff between finalityScore(selectedParent.blueScore + 1) * finalityInterval
|
||||
// and the current block blue score is less than pm.pruningDepth we can know for sure that this block didn't trigger a pruning point change.
|
||||
minRequiredBlueScoreForNextPruningPoint := (pm.finalityScore(selectedParentPruningPointHeader.BlueScore()) + 1) * pm.finalityInterval
|
||||
|
||||
if hasPruningPointInItsSelectedChain &&
|
||||
minRequiredBlueScoreForNextPruningPoint+pm.pruningDepth <= ghostdagData.BlueScore() {
|
||||
if hasPruningPointInItsSelectedChain && pm.finalityScore(ghostdagData.BlueScore()) > pm.finalityScore(selectedParentPruningPointHeader.BlueScore()+pm.pruningDepth) {
|
||||
var suggestedLowHash *externalapi.DomainHash
|
||||
hasReachabilityData, err := pm.reachabilityDataStore.HasReachabilityData(pm.databaseContext, stagingArea, selectedParentHeader.PruningPoint())
|
||||
if err != nil {
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
package lrucachehashandwindowsizetoblockghostdagdatahashpairs
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
|
||||
type lruKey struct {
|
||||
blockHash externalapi.DomainHash
|
||||
windowSize int
|
||||
}
|
||||
|
||||
func newKey(blockHash *externalapi.DomainHash, windowSize int) lruKey {
|
||||
return lruKey{
|
||||
blockHash: *blockHash,
|
||||
windowSize: windowSize,
|
||||
}
|
||||
}
|
||||
|
||||
// LRUCache is a least-recently-used cache from
|
||||
// lruKey to *externalapi.BlockGHOSTDAGDataHashPair
|
||||
type LRUCache struct {
|
||||
cache map[lruKey][]*externalapi.BlockGHOSTDAGDataHashPair
|
||||
capacity int
|
||||
}
|
||||
|
||||
// New creates a new LRUCache
|
||||
func New(capacity int, preallocate bool) *LRUCache {
|
||||
var cache map[lruKey][]*externalapi.BlockGHOSTDAGDataHashPair
|
||||
if preallocate {
|
||||
cache = make(map[lruKey][]*externalapi.BlockGHOSTDAGDataHashPair, capacity+1)
|
||||
} else {
|
||||
cache = make(map[lruKey][]*externalapi.BlockGHOSTDAGDataHashPair)
|
||||
}
|
||||
return &LRUCache{
|
||||
cache: cache,
|
||||
capacity: capacity,
|
||||
}
|
||||
}
|
||||
|
||||
// Add adds an entry to the LRUCache
|
||||
func (c *LRUCache) Add(blockHash *externalapi.DomainHash, windowSize int, value []*externalapi.BlockGHOSTDAGDataHashPair) {
|
||||
key := newKey(blockHash, windowSize)
|
||||
c.cache[key] = value
|
||||
|
||||
if len(c.cache) > c.capacity {
|
||||
c.evictRandom()
|
||||
}
|
||||
}
|
||||
|
||||
// Get returns the entry for the given key, or (nil, false) otherwise
|
||||
func (c *LRUCache) Get(blockHash *externalapi.DomainHash, windowSize int) ([]*externalapi.BlockGHOSTDAGDataHashPair, bool) {
|
||||
key := newKey(blockHash, windowSize)
|
||||
value, ok := c.cache[key]
|
||||
if !ok {
|
||||
return nil, false
|
||||
}
|
||||
return value, true
|
||||
}
|
||||
|
||||
// Has returns whether the LRUCache contains the given key
|
||||
func (c *LRUCache) Has(blockHash *externalapi.DomainHash, windowSize int) bool {
|
||||
key := newKey(blockHash, windowSize)
|
||||
_, ok := c.cache[key]
|
||||
return ok
|
||||
}
|
||||
|
||||
// Remove removes the entry for the the given key. Does nothing if
|
||||
// the entry does not exist
|
||||
func (c *LRUCache) Remove(blockHash *externalapi.DomainHash, windowSize int) {
|
||||
key := newKey(blockHash, windowSize)
|
||||
delete(c.cache, key)
|
||||
}
|
||||
|
||||
func (c *LRUCache) evictRandom() {
|
||||
var keyToEvict lruKey
|
||||
for key := range c.cache {
|
||||
keyToEvict = key
|
||||
break
|
||||
}
|
||||
c.Remove(&keyToEvict.blockHash, keyToEvict.windowSize)
|
||||
}
|
||||
@@ -291,11 +291,11 @@ var MainnetParams = Params{
|
||||
// TestnetParams defines the network parameters for the test Kaspa network.
|
||||
var TestnetParams = Params{
|
||||
K: defaultGHOSTDAGK,
|
||||
Name: "kaspa-testnet-9",
|
||||
Name: "kaspa-testnet-8",
|
||||
Net: appmessage.Testnet,
|
||||
RPCPort: "16210",
|
||||
DefaultPort: "16211",
|
||||
DNSSeeds: []string{"testnet-9-dnsseed.daglabs-dev.com"},
|
||||
DNSSeeds: []string{"testnet-8-dnsseed.daglabs-dev.com"},
|
||||
|
||||
// DAG parameters
|
||||
GenesisBlock: &testnetGenesisBlock,
|
||||
@@ -347,7 +347,7 @@ var TestnetParams = Params{
|
||||
DeflationaryPhaseDaaScore: defaultDeflationaryPhaseDaaScore,
|
||||
IgnoreHeaderMass: true,
|
||||
|
||||
MaxBlockLevel: 250,
|
||||
MaxBlockLevel: 255,
|
||||
}
|
||||
|
||||
// SimnetParams defines the network parameters for the simulation test Kaspa
|
||||
@@ -412,7 +412,7 @@ var SimnetParams = Params{
|
||||
PruningProofM: defaultPruningProofM,
|
||||
DeflationaryPhaseDaaScore: defaultDeflationaryPhaseDaaScore,
|
||||
|
||||
MaxBlockLevel: 250,
|
||||
MaxBlockLevel: 255,
|
||||
}
|
||||
|
||||
// DevnetParams defines the network parameters for the development Kaspa network.
|
||||
@@ -474,7 +474,7 @@ var DevnetParams = Params{
|
||||
DeflationaryPhaseDaaScore: defaultDeflationaryPhaseDaaScore,
|
||||
IgnoreHeaderMass: true,
|
||||
|
||||
MaxBlockLevel: 250,
|
||||
MaxBlockLevel: 255,
|
||||
}
|
||||
|
||||
// ErrDuplicateNet describes an error where the parameters for a Kaspa
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.3
|
||||
// source: messages.proto
|
||||
|
||||
package protowire
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@@ -21,10 +20,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type KaspadMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -11,7 +11,8 @@ import (
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the grpc package it is being compiled against.
|
||||
const _ = grpc.SupportPackageIsVersion6
|
||||
// Requires gRPC-Go v1.32.0 or later.
|
||||
const _ = grpc.SupportPackageIsVersion7
|
||||
|
||||
// P2PClient is the client API for P2P service.
|
||||
//
|
||||
@@ -29,7 +30,7 @@ func NewP2PClient(cc grpc.ClientConnInterface) P2PClient {
|
||||
}
|
||||
|
||||
func (c *p2PClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (P2P_MessageStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_P2P_serviceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &P2P_ServiceDesc.Streams[0], "/protowire.P2P/MessageStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -71,13 +72,20 @@ type P2PServer interface {
|
||||
type UnimplementedP2PServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
|
||||
func (UnimplementedP2PServer) MessageStream(P2P_MessageStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method MessageStream not implemented")
|
||||
}
|
||||
func (*UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {}
|
||||
func (UnimplementedP2PServer) mustEmbedUnimplementedP2PServer() {}
|
||||
|
||||
func RegisterP2PServer(s *grpc.Server, srv P2PServer) {
|
||||
s.RegisterService(&_P2P_serviceDesc, srv)
|
||||
// UnsafeP2PServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to P2PServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeP2PServer interface {
|
||||
mustEmbedUnimplementedP2PServer()
|
||||
}
|
||||
|
||||
func RegisterP2PServer(s grpc.ServiceRegistrar, srv P2PServer) {
|
||||
s.RegisterService(&P2P_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _P2P_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
@@ -106,7 +114,10 @@ func (x *p2PMessageStreamServer) Recv() (*KaspadMessage, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _P2P_serviceDesc = grpc.ServiceDesc{
|
||||
// P2P_ServiceDesc is the grpc.ServiceDesc for P2P service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var P2P_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "protowire.P2P",
|
||||
HandlerType: (*P2PServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
@@ -137,7 +148,7 @@ func NewRPCClient(cc grpc.ClientConnInterface) RPCClient {
|
||||
}
|
||||
|
||||
func (c *rPCClient) MessageStream(ctx context.Context, opts ...grpc.CallOption) (RPC_MessageStreamClient, error) {
|
||||
stream, err := c.cc.NewStream(ctx, &_RPC_serviceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...)
|
||||
stream, err := c.cc.NewStream(ctx, &RPC_ServiceDesc.Streams[0], "/protowire.RPC/MessageStream", opts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -179,13 +190,20 @@ type RPCServer interface {
|
||||
type UnimplementedRPCServer struct {
|
||||
}
|
||||
|
||||
func (*UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
|
||||
func (UnimplementedRPCServer) MessageStream(RPC_MessageStreamServer) error {
|
||||
return status.Errorf(codes.Unimplemented, "method MessageStream not implemented")
|
||||
}
|
||||
func (*UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {}
|
||||
func (UnimplementedRPCServer) mustEmbedUnimplementedRPCServer() {}
|
||||
|
||||
func RegisterRPCServer(s *grpc.Server, srv RPCServer) {
|
||||
s.RegisterService(&_RPC_serviceDesc, srv)
|
||||
// UnsafeRPCServer may be embedded to opt out of forward compatibility for this service.
|
||||
// Use of this interface is not recommended, as added methods to RPCServer will
|
||||
// result in compilation errors.
|
||||
type UnsafeRPCServer interface {
|
||||
mustEmbedUnimplementedRPCServer()
|
||||
}
|
||||
|
||||
func RegisterRPCServer(s grpc.ServiceRegistrar, srv RPCServer) {
|
||||
s.RegisterService(&RPC_ServiceDesc, srv)
|
||||
}
|
||||
|
||||
func _RPC_MessageStream_Handler(srv interface{}, stream grpc.ServerStream) error {
|
||||
@@ -214,7 +232,10 @@ func (x *rPCMessageStreamServer) Recv() (*KaspadMessage, error) {
|
||||
return m, nil
|
||||
}
|
||||
|
||||
var _RPC_serviceDesc = grpc.ServiceDesc{
|
||||
// RPC_ServiceDesc is the grpc.ServiceDesc for RPC service.
|
||||
// It's only intended for direct use with grpc.RegisterService,
|
||||
// and not to be introspected or modified (even as a copy)
|
||||
var RPC_ServiceDesc = grpc.ServiceDesc{
|
||||
ServiceName: "protowire.RPC",
|
||||
HandlerType: (*RPCServer)(nil),
|
||||
Methods: []grpc.MethodDesc{},
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
// Code generated by protoc-gen-go. DO NOT EDIT.
|
||||
// versions:
|
||||
// protoc-gen-go v1.25.0
|
||||
// protoc-gen-go v1.26.0
|
||||
// protoc v3.12.3
|
||||
// source: p2p.proto
|
||||
|
||||
package protowire
|
||||
|
||||
import (
|
||||
proto "github.com/golang/protobuf/proto"
|
||||
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
|
||||
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
|
||||
reflect "reflect"
|
||||
@@ -21,10 +20,6 @@ const (
|
||||
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
|
||||
)
|
||||
|
||||
// This is a compile-time assertion that a sufficiently up-to-date version
|
||||
// of the legacy proto package is being used.
|
||||
const _ = proto.ProtoPackageIsVersion4
|
||||
|
||||
type RequestAddressesMessage struct {
|
||||
state protoimpl.MessageState
|
||||
sizeCache protoimpl.SizeCache
|
||||
|
||||
@@ -79,9 +79,6 @@
|
||||
- [GetUtxosByAddressesResponseMessage](#protowire.GetUtxosByAddressesResponseMessage)
|
||||
- [GetBalanceByAddressRequestMessage](#protowire.GetBalanceByAddressRequestMessage)
|
||||
- [GetBalanceByAddressResponseMessage](#protowire.GetBalanceByAddressResponseMessage)
|
||||
- [GetBalancesByAddressesRequestMessage](#protowire.GetBalancesByAddressesRequestMessage)
|
||||
- [BalancesByAddressEntry](#protowire.BalancesByAddressEntry)
|
||||
- [GetBalancesByAddressesResponseMessage](#protowire.GetBalancesByAddressesResponseMessage)
|
||||
- [GetVirtualSelectedParentBlueScoreRequestMessage](#protowire.GetVirtualSelectedParentBlueScoreRequestMessage)
|
||||
- [GetVirtualSelectedParentBlueScoreResponseMessage](#protowire.GetVirtualSelectedParentBlueScoreResponseMessage)
|
||||
- [NotifyVirtualSelectedParentBlueScoreChangedRequestMessage](#protowire.NotifyVirtualSelectedParentBlueScoreChangedRequestMessage)
|
||||
@@ -214,9 +211,6 @@ Receivers of any ResponseMessage are expected to check whether its error field i
|
||||
| isHeaderOnly | [bool](#bool) | | |
|
||||
| blueScore | [uint64](#uint64) | | |
|
||||
| childrenHashes | [string](#string) | repeated | |
|
||||
| mergeSetBluesHashes | [string](#string) | repeated | |
|
||||
| mergeSetRedsHashes | [string](#string) | repeated | |
|
||||
| isChainBlock | [bool](#bool) | | |
|
||||
|
||||
|
||||
|
||||
@@ -416,7 +410,6 @@ See: GetBlockTemplateRequestMessage
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| block | [RpcBlock](#protowire.RpcBlock) | | |
|
||||
| allowNonDAABlocks | [bool](#bool) | | |
|
||||
|
||||
|
||||
|
||||
@@ -1335,54 +1328,6 @@ This call is only available when this kaspad was started with `--utxoindex`
|
||||
|
||||
|
||||
|
||||
<a name="protowire.GetBalancesByAddressesRequestMessage"></a>
|
||||
|
||||
### GetBalancesByAddressesRequestMessage
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| addresses | [string](#string) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="protowire.BalancesByAddressEntry"></a>
|
||||
|
||||
### BalancesByAddressEntry
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| address | [string](#string) | | |
|
||||
| balance | [uint64](#uint64) | | |
|
||||
| error | [RPCError](#protowire.RPCError) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="protowire.GetBalancesByAddressesResponseMessage"></a>
|
||||
|
||||
### GetBalancesByAddressesResponseMessage
|
||||
|
||||
|
||||
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| entries | [BalancesByAddressEntry](#protowire.BalancesByAddressEntry) | repeated | |
|
||||
| error | [RPCError](#protowire.RPCError) | | |
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="protowire.GetVirtualSelectedParentBlueScoreRequestMessage"></a>
|
||||
|
||||
### GetVirtualSelectedParentBlueScoreRequestMessage
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,9 +52,6 @@ message RpcBlockVerboseData{
|
||||
bool isHeaderOnly = 15;
|
||||
uint64 blueScore = 16;
|
||||
repeated string childrenHashes = 17;
|
||||
repeated string mergeSetBluesHashes = 18;
|
||||
repeated string mergeSetRedsHashes = 19;
|
||||
bool isChainBlock = 20;
|
||||
}
|
||||
|
||||
message RpcTransaction {
|
||||
|
||||
@@ -193,30 +193,24 @@ func (x *RpcBlockVerboseData) toAppMessage() (*appmessage.RPCBlockVerboseData, e
|
||||
return nil, errors.Wrapf(errorNil, "RpcBlockVerboseData is nil")
|
||||
}
|
||||
return &appmessage.RPCBlockVerboseData{
|
||||
Hash: x.Hash,
|
||||
Difficulty: x.Difficulty,
|
||||
SelectedParentHash: x.SelectedParentHash,
|
||||
TransactionIDs: x.TransactionIds,
|
||||
IsHeaderOnly: x.IsHeaderOnly,
|
||||
BlueScore: x.BlueScore,
|
||||
ChildrenHashes: x.ChildrenHashes,
|
||||
MergeSetBluesHashes: x.MergeSetBluesHashes,
|
||||
MergeSetRedsHashes: x.MergeSetRedsHashes,
|
||||
IsChainBlock: x.IsChainBlock,
|
||||
Hash: x.Hash,
|
||||
Difficulty: x.Difficulty,
|
||||
SelectedParentHash: x.SelectedParentHash,
|
||||
TransactionIDs: x.TransactionIds,
|
||||
IsHeaderOnly: x.IsHeaderOnly,
|
||||
BlueScore: x.BlueScore,
|
||||
ChildrenHashes: x.ChildrenHashes,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (x *RpcBlockVerboseData) fromAppMessage(message *appmessage.RPCBlockVerboseData) {
|
||||
*x = RpcBlockVerboseData{
|
||||
Hash: message.Hash,
|
||||
Difficulty: message.Difficulty,
|
||||
SelectedParentHash: message.SelectedParentHash,
|
||||
TransactionIds: message.TransactionIDs,
|
||||
IsHeaderOnly: message.IsHeaderOnly,
|
||||
BlueScore: message.BlueScore,
|
||||
ChildrenHashes: message.ChildrenHashes,
|
||||
MergeSetBluesHashes: message.MergeSetBluesHashes,
|
||||
MergeSetRedsHashes: message.MergeSetRedsHashes,
|
||||
IsChainBlock: message.IsChainBlock,
|
||||
Hash: message.Hash,
|
||||
Difficulty: message.Difficulty,
|
||||
SelectedParentHash: message.SelectedParentHash,
|
||||
TransactionIds: message.TransactionIDs,
|
||||
IsHeaderOnly: message.IsHeaderOnly,
|
||||
BlueScore: message.BlueScore,
|
||||
ChildrenHashes: message.ChildrenHashes,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user