Compare commits

..

3 Commits

Author SHA1 Message Date
tal
16a83f9bac Initialize the selcted parent on GHOSTDAG. 2021-04-08 14:27:22 +03:00
tal
7d20ee6b58 Adds a comment to exported function (GHOSTDAG). 2021-04-08 14:10:03 +03:00
tal
1ab05c3fbc Redesign the code of GHOSTDAG function. 2021-04-08 14:04:28 +03:00
141 changed files with 1622 additions and 3490 deletions

View File

@@ -13,7 +13,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ ubuntu-16.04, macos-10.15, windows-2019 ]
os: [ ubuntu-16.04, macos-10.15 ]
name: Testing on on ${{ matrix.os }}
steps:

View File

@@ -85,6 +85,12 @@ func (app *kaspadApp) main(startedChan chan<- struct{}) error {
profiling.Start(app.cfg.Profile, log)
}
// Perform upgrades to kaspad as new versions require it.
if err := doUpgrades(); err != nil {
log.Error(err)
return err
}
// Return now if an interrupt signal was triggered.
if signal.InterruptRequested(interrupt) {
return nil
@@ -157,6 +163,12 @@ func (app *kaspadApp) main(startedChan chan<- struct{}) error {
return nil
}
// doUpgrades performs upgrades to kaspad as new versions require it.
// currently it's a placeholder we got from kaspad upstream, that does nothing
func doUpgrades() error {
return nil
}
// dbPath returns the path to the block database given a database type.
func databasePath(cfg *config.Config) string {
return filepath.Join(cfg.AppDir, "data")
@@ -169,17 +181,6 @@ func removeDatabase(cfg *config.Config) error {
func openDB(cfg *config.Config) (database.Database, error) {
dbPath := databasePath(cfg)
err := checkDatabaseVersion(dbPath)
if err != nil {
return nil, err
}
log.Infof("Loading database from '%s'", dbPath)
db, err := ldb.NewLevelDB(dbPath, leveldbCacheSizeMiB)
if err != nil {
return nil, err
}
return db, nil
return ldb.NewLevelDB(dbPath, leveldbCacheSizeMiB)
}

View File

@@ -137,9 +137,6 @@ const (
CmdPruningPointUTXOSetOverrideNotificationMessage
CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage
CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage
CmdNotifyVirtualDaaScoreChangedRequestMessage
CmdNotifyVirtualDaaScoreChangedResponseMessage
CmdVirtualDaaScoreChangedNotificationMessage
)
// ProtocolMessageCommandToString maps all MessageCommands to their string representation
@@ -251,9 +248,6 @@ var RPCMessageCommandToString = map[MessageCommand]string{
CmdPruningPointUTXOSetOverrideNotificationMessage: "PruningPointUTXOSetOverrideNotification",
CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage: "StopNotifyingPruningPointUTXOSetOverrideRequest",
CmdStopNotifyingPruningPointUTXOSetOverrideResponseMessage: "StopNotifyingPruningPointUTXOSetOverrideResponse",
CmdNotifyVirtualDaaScoreChangedRequestMessage: "NotifyVirtualDaaScoreChangedRequest",
CmdNotifyVirtualDaaScoreChangedResponseMessage: "NotifyVirtualDaaScoreChangedResponse",
CmdVirtualDaaScoreChangedNotificationMessage: "VirtualDaaScoreChangedNotification",
}
// Message is an interface that describes a kaspa message. A type that

View File

@@ -28,7 +28,6 @@ type GetBlockDAGInfoResponseMessage struct {
Difficulty float64
PastMedianTime int64
PruningPointHash string
VirtualDAAScore uint64
Error *RPCError
}

View File

@@ -11,8 +11,8 @@ func (msg *GetInfoRequestMessage) Command() MessageCommand {
return CmdGetInfoRequestMessage
}
// NewGetInfoRequestMessage returns a instance of the message
func NewGetInfoRequestMessage() *GetInfoRequestMessage {
// NewGeInfoRequestMessage returns a instance of the message
func NewGeInfoRequestMessage() *GetInfoRequestMessage {
return &GetInfoRequestMessage{}
}

View File

@@ -1,55 +0,0 @@
package appmessage
// NotifyVirtualDaaScoreChangedRequestMessage is an appmessage corresponding to
// its respective RPC message
type NotifyVirtualDaaScoreChangedRequestMessage struct {
baseMessage
}
// Command returns the protocol command string for the message
func (msg *NotifyVirtualDaaScoreChangedRequestMessage) Command() MessageCommand {
return CmdNotifyVirtualDaaScoreChangedRequestMessage
}
// NewNotifyVirtualDaaScoreChangedRequestMessage returns a instance of the message
func NewNotifyVirtualDaaScoreChangedRequestMessage() *NotifyVirtualDaaScoreChangedRequestMessage {
return &NotifyVirtualDaaScoreChangedRequestMessage{}
}
// NotifyVirtualDaaScoreChangedResponseMessage is an appmessage corresponding to
// its respective RPC message
type NotifyVirtualDaaScoreChangedResponseMessage struct {
baseMessage
Error *RPCError
}
// Command returns the protocol command string for the message
func (msg *NotifyVirtualDaaScoreChangedResponseMessage) Command() MessageCommand {
return CmdNotifyVirtualDaaScoreChangedResponseMessage
}
// NewNotifyVirtualDaaScoreChangedResponseMessage returns a instance of the message
func NewNotifyVirtualDaaScoreChangedResponseMessage() *NotifyVirtualDaaScoreChangedResponseMessage {
return &NotifyVirtualDaaScoreChangedResponseMessage{}
}
// VirtualDaaScoreChangedNotificationMessage is an appmessage corresponding to
// its respective RPC message
type VirtualDaaScoreChangedNotificationMessage struct {
baseMessage
VirtualDaaScore uint64
}
// Command returns the protocol command string for the message
func (msg *VirtualDaaScoreChangedNotificationMessage) Command() MessageCommand {
return CmdVirtualDaaScoreChangedNotificationMessage
}
// NewVirtualDaaScoreChangedNotificationMessage returns a instance of the message
func NewVirtualDaaScoreChangedNotificationMessage(
virtualDaaScore uint64) *VirtualDaaScoreChangedNotificationMessage {
return &VirtualDaaScoreChangedNotificationMessage{
VirtualDaaScore: virtualDaaScore,
}
}

View File

@@ -4,19 +4,23 @@ import (
"fmt"
"sync/atomic"
"github.com/kaspanet/kaspad/domain/utxoindex"
infrastructuredatabase "github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/domain"
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/protocol"
"github.com/kaspanet/kaspad/app/rpc"
"github.com/kaspanet/kaspad/domain"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/utxoindex"
"github.com/kaspanet/kaspad/infrastructure/config"
infrastructuredatabase "github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
"github.com/kaspanet/kaspad/infrastructure/network/connmanager"
"github.com/kaspanet/kaspad/infrastructure/network/dnsseed"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/id"
"github.com/kaspanet/kaspad/util/panics"
)
@@ -78,13 +82,7 @@ func (a *ComponentManager) Stop() {
func NewComponentManager(cfg *config.Config, db infrastructuredatabase.Database, interrupt chan<- struct{}) (
*ComponentManager, error) {
consensusConfig := consensus.Config{
Params: *cfg.ActiveNetParams,
IsArchival: cfg.IsArchivalNode,
EnableSanityCheckPruningUTXOSet: cfg.EnableSanityCheckPruningUTXOSet,
}
domain, err := domain.New(&consensusConfig, db)
domain, err := domain.New(cfg.ActiveNetParams, db, cfg.IsArchivalNode)
if err != nil {
return nil, err
}

View File

@@ -1,57 +0,0 @@
package app
import (
"os"
"path"
"strconv"
"github.com/pkg/errors"
)
const currentDatabaseVersion = 1
func checkDatabaseVersion(dbPath string) (err error) {
versionFileName := versionFilePath(dbPath)
versionBytes, err := os.ReadFile(versionFileName)
if err != nil {
if os.IsNotExist(err) { // If version file doesn't exist, we assume that the database is new
return createDatabaseVersionFile(dbPath, versionFileName)
}
return err
}
databaseVersion, err := strconv.Atoi(string(versionBytes))
if err != nil {
return err
}
if databaseVersion != currentDatabaseVersion {
// TODO: Once there's more then one database version, it might make sense to add upgrade logic at this point
return errors.Errorf("Invalid database version %d. Expected version: %d", databaseVersion, currentDatabaseVersion)
}
return nil
}
func createDatabaseVersionFile(dbPath string, versionFileName string) error {
err := os.MkdirAll(dbPath, 0700)
if err != nil {
return err
}
versionFile, err := os.Create(versionFileName)
if err != nil {
return nil
}
defer versionFile.Close()
versionString := strconv.Itoa(currentDatabaseVersion)
_, err = versionFile.Write([]byte(versionString))
return err
}
func versionFilePath(dbPath string) string {
dbVersionFileName := path.Join(dbPath, "version")
return dbVersionFileName
}

View File

@@ -10,7 +10,6 @@ import (
"github.com/kaspanet/kaspad/app/protocol/flows/blockrelay"
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
"github.com/kaspanet/kaspad/domain"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
@@ -130,10 +129,6 @@ type fakeRelayInvsContext struct {
rwLock sync.RWMutex
}
func (f *fakeRelayInvsContext) GetBlockEvenIfHeaderOnly(blockHash *externalapi.DomainHash) (*externalapi.DomainBlock, error) {
panic("implement me")
}
func (f *fakeRelayInvsContext) GetBlockRelations(blockHash *externalapi.DomainHash) ([]*externalapi.DomainHash, *externalapi.DomainHash, []*externalapi.DomainHash, error) {
panic(errors.Errorf("called unimplemented function from test '%s'", f.testName))
}
@@ -1501,7 +1496,7 @@ func TestHandleRelayInvs(t *testing.T) {
},
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
for _, test := range tests {
// This is done to avoid race condition
@@ -1516,7 +1511,7 @@ func TestHandleRelayInvs(t *testing.T) {
errChan := make(chan error)
context := &fakeRelayInvsContext{
testName: test.name,
params: &consensusConfig.Params,
params: params,
finishedIBD: make(chan struct{}),
trySetIBDRunningResponse: true,

View File

@@ -1,16 +1,15 @@
package testing
import (
"testing"
"time"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/protocol/flows/addressexchange"
peerpkg "github.com/kaspanet/kaspad/app/protocol/peer"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/infrastructure/network/addressmanager"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
"testing"
"time"
)
type fakeReceiveAddressesContext struct{}
@@ -20,7 +19,7 @@ func (f fakeReceiveAddressesContext) AddressManager() *addressmanager.AddressMan
}
func TestReceiveAddressesErrors(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
incomingRoute := router.NewRoute()
outgoingRoute := router.NewRoute()
peer := peerpkg.New(nil)

View File

@@ -64,11 +64,6 @@ func (m *Manager) NotifyBlockAddedToDAG(block *externalapi.DomainBlock, blockIns
return err
}
err = m.notifyVirtualDaaScoreChanged()
if err != nil {
return err
}
err = m.notifyVirtualSelectedParentChainChanged(blockInsertionResult)
if err != nil {
return err
@@ -158,19 +153,6 @@ func (m *Manager) notifyVirtualSelectedParentBlueScoreChanged() error {
return m.context.NotificationManager.NotifyVirtualSelectedParentBlueScoreChanged(notification)
}
func (m *Manager) notifyVirtualDaaScoreChanged() error {
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualDaaScoreChanged")
defer onEnd()
virtualInfo, err := m.context.Domain.Consensus().GetVirtualInfo()
if err != nil {
return err
}
notification := appmessage.NewVirtualDaaScoreChangedNotificationMessage(virtualInfo.DAAScore)
return m.context.NotificationManager.NotifyVirtualDaaScoreChanged(notification)
}
func (m *Manager) notifyVirtualSelectedParentChainChanged(blockInsertionResult *externalapi.BlockInsertionResult) error {
onEnd := logger.LogAndMeasureExecutionTime(log, "RPCManager.NotifyVirtualSelectedParentChainChanged")
defer onEnd()

View File

@@ -44,7 +44,6 @@ var handlers = map[appmessage.MessageCommand]handler{
appmessage.CmdGetInfoRequestMessage: rpchandlers.HandleGetInfo,
appmessage.CmdNotifyPruningPointUTXOSetOverrideRequestMessage: rpchandlers.HandleNotifyPruningPointUTXOSetOverrideRequest,
appmessage.CmdStopNotifyingPruningPointUTXOSetOverrideRequestMessage: rpchandlers.HandleStopNotifyingPruningPointUTXOSetOverrideRequest,
appmessage.CmdNotifyVirtualDaaScoreChangedRequestMessage: rpchandlers.HandleNotifyVirtualDaaScoreChanged,
}
func (m *Manager) routerInitializer(router *router.Router, netConnection *netadapter.NetConnection) {

View File

@@ -30,7 +30,6 @@ type NotificationListener struct {
propagateFinalityConflictResolvedNotifications bool
propagateUTXOsChangedNotifications bool
propagateVirtualSelectedParentBlueScoreChangedNotifications bool
propagateVirtualDaaScoreChangedNotifications bool
propagatePruningPointUTXOSetOverrideNotifications bool
propagateUTXOsChangedNotificationAddresses map[utxoindex.ScriptPublicKeyString]*UTXOsChangedNotificationAddress
@@ -182,25 +181,6 @@ func (nm *NotificationManager) NotifyVirtualSelectedParentBlueScoreChanged(
return nil
}
// NotifyVirtualDaaScoreChanged notifies the notification manager that the DAG's
// virtual DAA score has changed
func (nm *NotificationManager) NotifyVirtualDaaScoreChanged(
notification *appmessage.VirtualDaaScoreChangedNotificationMessage) error {
nm.RLock()
defer nm.RUnlock()
for router, listener := range nm.listeners {
if listener.propagateVirtualDaaScoreChangedNotifications {
err := router.OutgoingRoute().Enqueue(notification)
if err != nil {
return err
}
}
}
return nil
}
// NotifyPruningPointUTXOSetOverride notifies the notification manager that the UTXO index
// reset due to pruning point change via IBD.
func (nm *NotificationManager) NotifyPruningPointUTXOSetOverride() error {
@@ -328,12 +308,6 @@ func (nl *NotificationListener) PropagateVirtualSelectedParentBlueScoreChangedNo
nl.propagateVirtualSelectedParentBlueScoreChangedNotifications = true
}
// PropagateVirtualDaaScoreChangedNotifications instructs the listener to send
// virtual DAA score notifications to the remote listener
func (nl *NotificationListener) PropagateVirtualDaaScoreChangedNotifications() {
nl.propagateVirtualDaaScoreChangedNotifications = true
}
// PropagatePruningPointUTXOSetOverrideNotifications instructs the listener to send pruning point UTXO set override notifications
// to the remote listener.
func (nl *NotificationListener) PropagatePruningPointUTXOSetOverrideNotifications() {

View File

@@ -2,11 +2,10 @@ package rpccontext
import (
"encoding/hex"
"math"
"math/big"
difficultyPackage "github.com/kaspanet/kaspad/util/difficulty"
"github.com/pkg/errors"
"math"
"math/big"
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
@@ -63,15 +62,12 @@ func (ctx *Context) PopulateBlockWithVerboseData(block *appmessage.RPCBlock, dom
}
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,
}
// selectedParentHash will be nil in the genesis block
if selectedParentHash != nil {
block.VerboseData.SelectedParentHash = selectedParentHash.String()
Hash: blockHash.String(),
Difficulty: ctx.GetDifficultyRatio(domainBlockHeader.Bits(), ctx.Config.ActiveNetParams),
ChildrenHashes: hashes.ToStrings(childrenHashes),
SelectedParentHash: selectedParentHash.String(),
IsHeaderOnly: blockInfo.BlockStatus == externalapi.StatusHeaderOnly,
BlueScore: blockInfo.BlueScore,
}
if blockInfo.BlockStatus == externalapi.StatusHeaderOnly {
@@ -80,7 +76,7 @@ func (ctx *Context) PopulateBlockWithVerboseData(block *appmessage.RPCBlock, dom
// Get the block if we didn't receive it previously
if domainBlock == nil {
domainBlock, err = ctx.Domain.Consensus().GetBlockEvenIfHeaderOnly(blockHash)
domainBlock, err = ctx.Domain.Consensus().GetBlock(blockHash)
if err != nil {
return err
}

View File

@@ -20,22 +20,18 @@ func HandleGetBlock(context *rpccontext.Context, _ *router.Router, request appme
return errorMessage, nil
}
block, err := context.Domain.Consensus().GetBlockEvenIfHeaderOnly(hash)
header, err := context.Domain.Consensus().GetBlockHeader(hash)
if err != nil {
errorMessage := &appmessage.GetBlockResponseMessage{}
errorMessage.Error = appmessage.RPCErrorf("Block %s not found", hash)
return errorMessage, nil
}
block := &externalapi.DomainBlock{Header: header}
response := appmessage.NewGetBlockResponseMessage()
response.Block = appmessage.DomainBlockToRPCBlock(block)
if getBlockRequest.IncludeTransactionVerboseData {
response.Block = appmessage.DomainBlockToRPCBlock(block)
} else {
response.Block = appmessage.DomainBlockToRPCBlock(&externalapi.DomainBlock{Header: block.Header})
}
err = context.PopulateBlockWithVerboseData(response.Block, block.Header, block, getBlockRequest.IncludeTransactionVerboseData)
err = context.PopulateBlockWithVerboseData(response.Block, header, nil, getBlockRequest.IncludeTransactionVerboseData)
if err != nil {
if errors.Is(err, rpccontext.ErrBuildBlockVerboseDataInvalidBlock) {
errorMessage := &appmessage.GetBlockResponseMessage{}

View File

@@ -35,7 +35,6 @@ func HandleGetBlockDAGInfo(context *rpccontext.Context, _ *router.Router, _ appm
response.VirtualParentHashes = hashes.ToStrings(virtualInfo.ParentHashes)
response.Difficulty = context.GetDifficultyRatio(virtualInfo.Bits, context.Config.ActiveNetParams)
response.PastMedianTime = virtualInfo.PastMedianTime
response.VirtualDAAScore = virtualInfo.DAAScore
pruningPoint, err := context.Domain.Consensus().PruningPoint()
if err != nil {

View File

@@ -84,24 +84,19 @@ func HandleGetBlocks(context *rpccontext.Context, _ *router.Router, request appm
response := appmessage.NewGetBlocksResponseMessage()
response.BlockHashes = hashes.ToStrings(blockHashes)
if getBlocksRequest.IncludeBlocks {
rpcBlocks := make([]*appmessage.RPCBlock, len(blockHashes))
blocks := make([]*appmessage.RPCBlock, len(blockHashes))
for i, blockHash := range blockHashes {
block, err := context.Domain.Consensus().GetBlockEvenIfHeaderOnly(blockHash)
blockHeader, err := context.Domain.Consensus().GetBlockHeader(blockHash)
if err != nil {
return nil, err
}
if getBlocksRequest.IncludeTransactionVerboseData {
rpcBlocks[i] = appmessage.DomainBlockToRPCBlock(block)
} else {
rpcBlocks[i] = appmessage.DomainBlockToRPCBlock(&externalapi.DomainBlock{Header: block.Header})
}
err = context.PopulateBlockWithVerboseData(rpcBlocks[i], block.Header, nil, getBlocksRequest.IncludeTransactionVerboseData)
block := &externalapi.DomainBlock{Header: blockHeader}
blocks[i] = appmessage.DomainBlockToRPCBlock(block)
err = context.PopulateBlockWithVerboseData(blocks[i], blockHeader, nil, getBlocksRequest.IncludeTransactionVerboseData)
if err != nil {
return nil, err
}
}
response.Blocks = rpcBlocks
}
return response, nil

View File

@@ -15,6 +15,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/domain/miningmanager"
"github.com/kaspanet/kaspad/infrastructure/config"
)
@@ -27,18 +28,18 @@ func (d fakeDomain) Consensus() externalapi.Consensus { return d }
func (d fakeDomain) MiningManager() miningmanager.MiningManager { return nil }
func TestHandleGetBlocks(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestHandleGetBlocks")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestHandleGetBlocks")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
fakeContext := rpccontext.Context{
Config: &config.Config{Flags: &config.Flags{NetworkFlags: config.NetworkFlags{ActiveNetParams: &consensusConfig.Params}}},
Config: &config.Config{Flags: &config.Flags{NetworkFlags: config.NetworkFlags{ActiveNetParams: params}}},
Domain: fakeDomain{tc},
}
@@ -80,7 +81,7 @@ func TestHandleGetBlocks(t *testing.T) {
// \ | /
// etc.
expectedOrder := make([]*externalapi.DomainHash, 0, 40)
mergingBlock := consensusConfig.GenesisHash
mergingBlock := params.GenesisHash
for i := 0; i < 10; i++ {
splitBlocks := make([]*externalapi.DomainHash, 0, 3)
for j := 0; j < 3; j++ {
@@ -133,13 +134,13 @@ func TestHandleGetBlocks(t *testing.T) {
virtualSelectedParent, actualBlocks.BlockHashes)
}
expectedOrder = append([]*externalapi.DomainHash{consensusConfig.GenesisHash}, expectedOrder...)
expectedOrder = append([]*externalapi.DomainHash{params.GenesisHash}, expectedOrder...)
actualOrder := getBlocks(nil)
if !reflect.DeepEqual(actualOrder.BlockHashes, hashes.ToStrings(expectedOrder)) {
t.Fatalf("TestHandleGetBlocks \nexpected: %v \nactual:\n%v", expectedOrder, actualOrder.BlockHashes)
}
requestAllExplictly := getBlocks(consensusConfig.GenesisHash)
requestAllExplictly := getBlocks(params.GenesisHash)
if !reflect.DeepEqual(requestAllExplictly.BlockHashes, hashes.ToStrings(expectedOrder)) {
t.Fatalf("TestHandleGetBlocks \nexpected: \n%v\n. actual:\n%v", expectedOrder, requestAllExplictly.BlockHashes)
}

View File

@@ -1,19 +0,0 @@
package rpchandlers
import (
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
)
// HandleNotifyVirtualDaaScoreChanged handles the respectively named RPC command
func HandleNotifyVirtualDaaScoreChanged(context *rpccontext.Context, router *router.Router, _ appmessage.Message) (appmessage.Message, error) {
listener, err := context.NotificationManager.Listener(router)
if err != nil {
return nil, err
}
listener.PropagateVirtualDaaScoreChangedNotifications()
response := appmessage.NewNotifyVirtualDaaScoreChangedResponseMessage()
return response, nil
}

View File

@@ -1,100 +1,11 @@
Kaspad v0.10.3 - 2021-06-06
===========================
Non-breaking changes:
* Implement NotifyVirtualDaaScoreChanged (#1737)
Kaspad v0.10.2 - 2021-05-18
===========================
Non-breaking changes:
* Fix getBlock and getBlocks RPC commands to return blocks and transactions properly (#1716)
* serializeAddress should always serialize as IPv6, since it assumes the IP size is 16 bytes (#1720)
* Add VirtualDaaScore to GetBlockDagInfo (#1719)
* Fix calcTxSequenceLockFromReferencedUTXOEntries for loop break condition (#1723)
* Fix overflow when checking coinbase maturity and don't ban peers that send transactions with immature spend (#1722)
Kaspad v0.10.1 - 2021-05-11
===========================
* Calculate virtual's acceptance data and multiset after importing a new pruning point (#1700)
Kaspad v0.10.0 - 2021-04-26
===========================
Major changes include:
* Implementing a signature hashing scheme similar to BIP-143
* Replacing HASH160 with BLAKE2B
* Replacing ECMH with MuHash
* Removing RIPEMD160 and SHA1 from the codebase entirely
* Making P2PKH transactions non-standard
* Vastly enhancing the CLI wallet
* Restructuring kaspad's app/home directory
* Modifying block and transaction types in the RPC to be easier to consume clientside
A partial list of the more-important commits is as follows:
* Fix data race in GetBlockChildren (#1579)
* Remove payload hash (#1583)
* Add the mempool size to getInfo RPC command (#1584)
* Change the difficulty to be calculated based on the same block instead of its selected parent (#1591)
* Adjust the difficulty in the first difficultyAdjustmentWindowSize blocks (#1592)
* Adding DAA score (#1596)
* Use DAA score where needed (#1602)
* Remove the Services field from NetAddress. (#1610)
* Fix getBlocks to not add the anticone when some blocks were filtered by GetHashesBetween (#1611)
* Restructure the default ~/.kaspad directory layout (#1613)
* Replace the HomeDir flag with a AppDir flag (#1615)
* Implement BIP-143-like sighash (#1598)
* Change --datadir to --appdir and remove symmetrical connection in stability tests (#1617)
* Use BLAKE2B instead of HASH160, and get rid of any usage of RIPEMD160 and SHA1 (#1618)
* Replace ECMH with Muhash (#1624)
* Add support for multiple staging areas (#1633)
* Make sure the ghostdagDataStore cache is at least DifficultyAdjustmentBlockWindow sized (#1635)
* Resolve each block status in it's own staging area (#1634)
* Add mass limit to mempool (#1627)
* In RPC, use RPCTransactions and RPCBlocks instead of TransactionMessages and BlockMessages (#1609)
* Use go-secp256k1 v0.0.5 (#1640)
* Add a show-address subcommand to kaspawallet (#1653)
* Replace p2pkh with p2pk (#1650)
* Implement importing private keys into the wallet (#1655)
* Add dump unencrypted data sub command to the wallet (#1661)
* Add ECDSA support (#1657)
* Add OpCheckMultiSigECDSA (#1663)
* Add ECDSA support to the wallet (#1664)
* Make moving the pruning point faster (#1660)
* Implement new mechanism for updating UTXO Diffs (#1671)
Kaspad v0.9.2 - 2021-03-31
===========================
* Increase the route capacity of InvTransaction messages. (#1603) (#1637)
Kaspad v0.9.1 - 2021-03-14
===========================
* Testnet network reset
Kaspad v0.9.0 - 2021-03-04
===========================
* Merge big subdags in pick virtual parents (#1574)
* Write in the reject message the tx rejection reason (#1573)
* Add nil checks for protowire (#1570)
* Increase getBlocks limit to 1000 (#1572)
* Return RPC error if getBlock's lowHash doesn't exist (#1569)
* Add default dns-seeder to testnet (#1568)
* Fix utxoindex deserialization (#1566)
* Add pruning point hash to GetBlockDagInfo response (#1565)
* Use EmitUnpopulated so that kaspactl prints all fields, even the default ones (#1561)
* Stop logging an error whenever an RPC/P2P connection is canceled (#1562)
* Cleanup the logger and make it asynchronous (#1524)
* Close all iterators (#1542)
* Add childrenHashes to GetBlock/s RPC commands (#1560)
* Add ScriptPublicKey.Version to RPC (#1559)
* Fix the target block rate to create less bursty mining (#1554)
Kaspad v0.8.10 - 2021-02-25
===========================
* Fix bug where invalid mempool transactions were not removed (#1551)
* Add RPC reconnection to the miner (#1552)
* Remove virtual diff parents - only selectedTip is virtualDiffParent now (#1550)
* Fix UTXO index (#1548)
* Prevent fast failing (#1545)
* Increase the sleep time in kaspaminer when the node is not synced (#1544)
* Disallow header only blocks on RPC, relay and when requesting IBD full blocks (#1537)
* Make templateManager hold a DomainBlock and isSynced bool instead of a GetBlockTemplateResponseMessage (#1538)
[*] Fix bug where invalid mempool transactions were not removed (#1551)
[*] Add RPC reconnection to the miner (#1552)
[*] Remove virtual diff parents - only selectedTip is virtualDiffParent now (#1550)
[*] Fix UTXO index (#1548)
[*] Prevent fast failing (#1545)
[*] Increase the sleep time in kaspaminer when the node is not synced (#1544)
[*] Disallow header only blocks on RPC, relay and when requesting IBD full blocks (#1537)
[*] Make templateManager hold a DomainBlock and isSynced bool instead of a GetBlockTemplateResponseMessage (#1538)

View File

@@ -6,14 +6,18 @@ import (
"sync/atomic"
"time"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/cmd/kaspaminer/templatemanager"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/pow"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/domain/consensus/model/pow"
"github.com/kaspanet/kaspad/util/difficulty"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
"github.com/kaspanet/kaspad/util"
"github.com/pkg/errors"
)

View File

@@ -2,7 +2,6 @@ package main
import (
"fmt"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/kaspanet/kaspad/util"
@@ -14,7 +13,7 @@ func balance(conf *balanceConfig) error {
return err
}
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}
@@ -28,14 +27,15 @@ func balance(conf *balanceConfig) error {
if err != nil {
return err
}
blockDAGInfo, err := client.GetBlockDAGInfo()
virtualSelectedParentBlueScoreResponse, err := client.GetVirtualSelectedParentBlueScore()
if err != nil {
return err
}
virtualSelectedParentBlueScore := virtualSelectedParentBlueScoreResponse.BlueScore
var availableBalance, pendingBalance uint64
for _, entry := range getUTXOsByAddressesResponse.Entries {
if isUTXOSpendable(entry, blockDAGInfo.VirtualDAAScore, conf.ActiveNetParams.BlockCoinbaseMaturity) {
if isUTXOSpendable(entry, virtualSelectedParentBlueScore, conf.ActiveNetParams.BlockCoinbaseMaturity) {
availableBalance += entry.UTXOEntry.Amount
} else {
pendingBalance += entry.UTXOEntry.Amount

View File

@@ -8,12 +8,13 @@ import (
"os"
)
func isUTXOSpendable(entry *appmessage.UTXOsByAddressesEntry, virtualDAAScore uint64, coinbaseMaturity uint64) bool {
func isUTXOSpendable(entry *appmessage.UTXOsByAddressesEntry, virtualSelectedParentBlueScore uint64, coinbaseMaturity uint64) bool {
if !entry.UTXOEntry.IsCoinbase {
return true
}
blockBlueScore := entry.UTXOEntry.BlockDAAScore
return blockBlueScore+coinbaseMaturity < virtualDAAScore
// TODO: Check for a better alternative than virtualSelectedParentBlueScore
return blockBlueScore+coinbaseMaturity < virtualSelectedParentBlueScore
}
func printErrorAndExit(err error) {

View File

@@ -4,11 +4,10 @@ import (
"bufio"
"encoding/hex"
"fmt"
"os"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/pkg/errors"
"os"
)
func create(conf *createConfig) error {
@@ -50,13 +49,12 @@ func create(conf *createConfig) error {
publicKeys = append(publicKeys, publicKey)
}
err = keys.WriteKeysFile(
conf.NetParams(), conf.KeysFile, encryptedPrivateKeys, publicKeys, conf.MinimumSignatures, conf.ECDSA)
err = keys.WriteKeysFile(conf.KeysFile, encryptedPrivateKeys, publicKeys, conf.MinimumSignatures, conf.ECDSA)
if err != nil {
return err
}
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}

View File

@@ -3,14 +3,13 @@ package main
import (
"encoding/hex"
"fmt"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/kaspanet/kaspad/util"
)
func createUnsignedTransaction(conf *createUnsignedTransactionConfig) error {
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}

View File

@@ -3,11 +3,10 @@ package main
import (
"bufio"
"fmt"
"os"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
"github.com/pkg/errors"
"os"
)
func dumpUnencryptedData(conf *dumpUnencryptedDataConfig) error {
@@ -16,7 +15,7 @@ func dumpUnencryptedData(conf *dumpUnencryptedDataConfig) error {
return err
}
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}

View File

@@ -11,7 +11,7 @@ import (
// getPassword was adapted from https://gist.github.com/jlinoff/e8e26b4ffa38d379c7f1891fd174a6d0#file-getpassword2-go
func getPassword(prompt string) []byte {
// Get the initial state of the terminal.
initialTermState, e1 := term.GetState(int(syscall.Stdin))
initialTermState, e1 := term.GetState(syscall.Stdin)
if e1 != nil {
panic(e1)
}
@@ -22,13 +22,13 @@ func getPassword(prompt string) []byte {
signal.Notify(c, os.Interrupt, os.Kill)
go func() {
<-c
_ = term.Restore(int(syscall.Stdin), initialTermState)
_ = term.Restore(syscall.Stdin, initialTermState)
os.Exit(1)
}()
// Now get the password.
fmt.Print(prompt)
p, err := term.ReadPassword(int(syscall.Stdin))
p, err := term.ReadPassword(syscall.Stdin)
fmt.Println()
if err != nil {
panic(err)

View File

@@ -6,25 +6,20 @@ import (
"encoding/hex"
"encoding/json"
"fmt"
"os"
"path/filepath"
"runtime"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util"
"github.com/pkg/errors"
"golang.org/x/crypto/argon2"
"golang.org/x/crypto/chacha20poly1305"
"os"
"path/filepath"
"runtime"
)
var (
defaultAppDir = util.AppDir("kaspawallet", false)
defaultAppDir = util.AppDir("kaspawallet", false)
defaultKeysFile = filepath.Join(defaultAppDir, "keys.json")
)
func defaultKeysFile(netParams *dagconfig.Params) string {
return filepath.Join(defaultAppDir, netParams.Name, "keys.json")
}
type encryptedPrivateKeyJSON struct {
Cipher string `json:"cipher"`
Salt string `json:"salt"`
@@ -124,9 +119,9 @@ func (d *Data) DecryptPrivateKeys() ([][]byte, error) {
}
// ReadKeysFile returns the data related to the keys file
func ReadKeysFile(netParams *dagconfig.Params, path string) (*Data, error) {
func ReadKeysFile(path string) (*Data, error) {
if path == "" {
path = defaultKeysFile(netParams)
path = defaultKeysFile
}
file, err := os.Open(path)
@@ -162,7 +157,7 @@ func createFileDirectoryIfDoesntExist(path string) error {
return nil
}
return os.MkdirAll(dir, 0700)
return os.MkdirAll(dir, 0600)
}
func pathExists(path string) (bool, error) {
@@ -181,11 +176,13 @@ func pathExists(path string) (bool, error) {
}
// WriteKeysFile writes a keys file with the given data
func WriteKeysFile(netParams *dagconfig.Params, path string, encryptedPrivateKeys []*EncryptedPrivateKey,
publicKeys [][]byte, minimumSignatures uint32, ecdsa bool) error {
func WriteKeysFile(path string,
encryptedPrivateKeys []*EncryptedPrivateKey,
publicKeys [][]byte,
minimumSignatures uint32,
ecdsa bool) error {
if path == "" {
path = defaultKeysFile(netParams)
path = defaultKeysFile
}
exists, err := pathExists(path)

View File

@@ -9,6 +9,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util"
"strings"
"testing"
@@ -25,10 +26,10 @@ func forSchnorrAndECDSA(t *testing.T, testFunc func(t *testing.T, ecdsa bool)) {
}
func TestMultisig(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
forSchnorrAndECDSA(t, func(t *testing.T, ecdsa bool) {
consensusConfig.BlockCoinbaseMaturity = 0
tc, teardown, err := consensus.NewFactory().NewTestConsensus(consensusConfig, "TestMultisig")
params.BlockCoinbaseMaturity = 0
tc, teardown, err := consensus.NewFactory().NewTestConsensus(params, false, "TestMultisig")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
@@ -45,7 +46,7 @@ func TestMultisig(t *testing.T) {
}
const minimumSignatures = 2
address, err := libkaspawallet.Address(&consensusConfig.Params, publicKeys, minimumSignatures, ecdsa)
address, err := libkaspawallet.Address(params, publicKeys, minimumSignatures, ecdsa)
if err != nil {
t.Fatalf("Address: %+v", err)
}
@@ -64,7 +65,7 @@ func TestMultisig(t *testing.T) {
ExtraData: nil,
}
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, coinbaseData, nil)
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, coinbaseData, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -169,10 +170,10 @@ func TestMultisig(t *testing.T) {
}
func TestP2PK(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
forSchnorrAndECDSA(t, func(t *testing.T, ecdsa bool) {
consensusConfig.BlockCoinbaseMaturity = 0
tc, teardown, err := consensus.NewFactory().NewTestConsensus(consensusConfig, "TestMultisig")
params.BlockCoinbaseMaturity = 0
tc, teardown, err := consensus.NewFactory().NewTestConsensus(params, false, "TestMultisig")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
@@ -189,7 +190,7 @@ func TestP2PK(t *testing.T) {
}
const minimumSignatures = 1
address, err := libkaspawallet.Address(&consensusConfig.Params, publicKeys, minimumSignatures, ecdsa)
address, err := libkaspawallet.Address(params, publicKeys, minimumSignatures, ecdsa)
if err != nil {
t.Fatalf("Address: %+v", err)
}
@@ -214,7 +215,7 @@ func TestP2PK(t *testing.T) {
ExtraData: nil,
}
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, coinbaseData, nil)
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, coinbaseData, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}

View File

@@ -3,7 +3,6 @@ package main
import (
"encoding/hex"
"fmt"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
utxopkg "github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
@@ -18,7 +17,7 @@ import (
)
func send(conf *sendConfig) error {
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}
@@ -96,15 +95,15 @@ func fetchSpendableUTXOs(params *dagconfig.Params, client *rpcclient.RPCClient,
if err != nil {
return nil, err
}
blockDAGInfo, err := client.GetBlockDAGInfo()
virtualSelectedParentBlueScoreResponse, err := client.GetVirtualSelectedParentBlueScore()
if err != nil {
return nil, err
}
virtualSelectedParentBlueScore := virtualSelectedParentBlueScoreResponse.BlueScore
spendableUTXOs := make([]*appmessage.UTXOsByAddressesEntry, 0)
for _, entry := range getUTXOsByAddressesResponse.Entries {
if !isUTXOSpendable(entry, blockDAGInfo.VirtualDAAScore, params.BlockCoinbaseMaturity) {
if !isUTXOSpendable(entry, virtualSelectedParentBlueScore, params.BlockCoinbaseMaturity) {
continue
}
spendableUTXOs = append(spendableUTXOs, entry)

View File

@@ -2,13 +2,12 @@ package main
import (
"fmt"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
)
func showAddress(conf *showAddressConfig) error {
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}

View File

@@ -3,13 +3,12 @@ package main
import (
"encoding/hex"
"fmt"
"github.com/kaspanet/kaspad/cmd/kaspawallet/keys"
"github.com/kaspanet/kaspad/cmd/kaspawallet/libkaspawallet"
)
func sign(conf *signConfig) error {
keysFile, err := keys.ReadKeysFile(conf.NetParams(), conf.KeysFile)
keysFile, err := keys.ReadKeysFile(conf.KeysFile)
if err != nil {
return err
}

View File

@@ -112,30 +112,6 @@ func (s *consensus) GetBlock(blockHash *externalapi.DomainHash) (*externalapi.Do
return block, nil
}
func (s *consensus) GetBlockEvenIfHeaderOnly(blockHash *externalapi.DomainHash) (*externalapi.DomainBlock, error) {
s.lock.Lock()
defer s.lock.Unlock()
stagingArea := model.NewStagingArea()
block, err := s.blockStore.Block(s.databaseContext, stagingArea, blockHash)
if err == nil {
return block, nil
}
if !errors.Is(err, database.ErrNotFound) {
return nil, err
}
header, err := s.blockHeaderStore.BlockHeader(s.databaseContext, stagingArea, blockHash)
if err != nil {
if errors.Is(err, database.ErrNotFound) {
return nil, errors.Wrapf(err, "block %s does not exist", blockHash)
}
return nil, err
}
return &externalapi.DomainBlock{Header: header}, nil
}
func (s *consensus) GetBlockHeader(blockHash *externalapi.DomainHash) (externalapi.BlockHeader, error) {
s.lock.Lock()
defer s.lock.Unlock()
@@ -387,17 +363,11 @@ func (s *consensus) GetVirtualInfo() (*externalapi.VirtualInfo, error) {
return nil, err
}
daaScore, err := s.daaBlocksStore.DAAScore(s.databaseContext, stagingArea, model.VirtualBlockHash)
if err != nil {
return nil, err
}
return &externalapi.VirtualInfo{
ParentHashes: blockRelations.Parents,
Bits: bits,
PastMedianTime: pastMedianTime,
BlueScore: virtualGHOSTDAGData.BlueScore(),
DAAScore: daaScore,
}, nil
}

View File

@@ -1,26 +1,26 @@
package consensus_test
package consensus
import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
func TestConsensus_GetBlockInfo(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestConsensus_GetBlockInfo")
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := NewFactory()
consensus, teardown, err := factory.NewTestConsensus(params, false, "TestConsensus_GetBlockInfo")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
invalidBlock, _, err := consensus.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
invalidBlock, _, err := consensus.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}

View File

@@ -8,8 +8,7 @@ import (
type pruningStagingShard struct {
store *pruningStore
currentPruningPoint *externalapi.DomainHash
previousPruningPoint *externalapi.DomainHash
newPruningPoint *externalapi.DomainHash
newPruningPointCandidate *externalapi.DomainHash
startUpdatingPruningPointUTXOSet bool
}
@@ -18,8 +17,7 @@ func (ps *pruningStore) stagingShard(stagingArea *model.StagingArea) *pruningSta
return stagingArea.GetOrCreateShard(model.StagingShardIDPruning, func() model.StagingShard {
return &pruningStagingShard{
store: ps,
currentPruningPoint: nil,
previousPruningPoint: nil,
newPruningPoint: nil,
newPruningPointCandidate: nil,
startUpdatingPruningPointUTXOSet: false,
}
@@ -27,8 +25,8 @@ func (ps *pruningStore) stagingShard(stagingArea *model.StagingArea) *pruningSta
}
func (mss *pruningStagingShard) Commit(dbTx model.DBTransaction) error {
if mss.currentPruningPoint != nil {
pruningPointBytes, err := mss.store.serializeHash(mss.currentPruningPoint)
if mss.newPruningPoint != nil {
pruningPointBytes, err := mss.store.serializeHash(mss.newPruningPoint)
if err != nil {
return err
}
@@ -36,19 +34,7 @@ func (mss *pruningStagingShard) Commit(dbTx model.DBTransaction) error {
if err != nil {
return err
}
mss.store.pruningPointCache = mss.currentPruningPoint
}
if mss.previousPruningPoint != nil {
oldPruningPointBytes, err := mss.store.serializeHash(mss.previousPruningPoint)
if err != nil {
return err
}
err = dbTx.Put(previousPruningBlockHashKey, oldPruningPointBytes)
if err != nil {
return err
}
mss.store.oldPruningPointCache = mss.previousPruningPoint
mss.store.pruningPointCache = mss.newPruningPoint
}
if mss.newPruningPointCandidate != nil {
@@ -74,5 +60,5 @@ func (mss *pruningStagingShard) Commit(dbTx model.DBTransaction) error {
}
func (mss *pruningStagingShard) isStaged() bool {
return mss.currentPruningPoint != nil || mss.newPruningPointCandidate != nil || mss.previousPruningPoint != nil || mss.startUpdatingPruningPointUTXOSet
return mss.newPruningPoint != nil || mss.startUpdatingPruningPointUTXOSet
}

View File

@@ -9,7 +9,6 @@ import (
)
var pruningBlockHashKey = database.MakeBucket(nil).Key([]byte("pruning-block-hash"))
var previousPruningBlockHashKey = database.MakeBucket(nil).Key([]byte("previous-pruning-block-hash"))
var candidatePruningPointHashKey = database.MakeBucket(nil).Key([]byte("candidate-pruning-point-hash"))
var pruningPointUTXOSetBucket = database.MakeBucket([]byte("pruning-point-utxo-set"))
var updatingPruningPointUTXOSetKey = database.MakeBucket(nil).Key([]byte("updating-pruning-point-utxo-set"))
@@ -17,7 +16,6 @@ var updatingPruningPointUTXOSetKey = database.MakeBucket(nil).Key([]byte("updati
// pruningStore represents a store for the current pruning state
type pruningStore struct {
pruningPointCache *externalapi.DomainHash
oldPruningPointCache *externalapi.DomainHash
pruningPointCandidateCache *externalapi.DomainHash
}
@@ -74,56 +72,54 @@ func (ps *pruningStore) HasPruningPointCandidate(dbContext model.DBReader, stagi
func (ps *pruningStore) StagePruningPoint(stagingArea *model.StagingArea, pruningPointBlockHash *externalapi.DomainHash) {
stagingShard := ps.stagingShard(stagingArea)
stagingShard.currentPruningPoint = pruningPointBlockHash
}
func (ps *pruningStore) StagePreviousPruningPoint(stagingArea *model.StagingArea, oldPruningPointBlockHash *externalapi.DomainHash) {
stagingShard := ps.stagingShard(stagingArea)
stagingShard.previousPruningPoint = oldPruningPointBlockHash
stagingShard.newPruningPoint = pruningPointBlockHash
}
func (ps *pruningStore) IsStaged(stagingArea *model.StagingArea) bool {
return ps.stagingShard(stagingArea).isStaged()
}
func (ps *pruningStore) UpdatePruningPointUTXOSet(dbContext model.DBWriter, diff externalapi.UTXODiff) error {
toRemoveIterator := diff.ToRemove().Iterator()
defer toRemoveIterator.Close()
for ok := toRemoveIterator.First(); ok; ok = toRemoveIterator.Next() {
toRemoveOutpoint, _, err := toRemoveIterator.Get()
func (ps *pruningStore) UpdatePruningPointUTXOSet(dbContext model.DBWriter,
utxoSetIterator externalapi.ReadOnlyUTXOSetIterator) error {
// Delete all the old UTXOs from the database
deleteCursor, err := dbContext.Cursor(pruningPointUTXOSetBucket)
if err != nil {
return err
}
defer deleteCursor.Close()
for ok := deleteCursor.First(); ok; ok = deleteCursor.Next() {
key, err := deleteCursor.Key()
if err != nil {
return err
}
serializedOutpoint, err := serializeOutpoint(toRemoveOutpoint)
if err != nil {
return err
}
err = dbContext.Delete(pruningPointUTXOSetBucket.Key(serializedOutpoint))
err = dbContext.Delete(key)
if err != nil {
return err
}
}
toAddIterator := diff.ToAdd().Iterator()
defer toAddIterator.Close()
for ok := toAddIterator.First(); ok; ok = toAddIterator.Next() {
toAddOutpoint, entry, err := toAddIterator.Get()
// Insert all the new UTXOs into the database
for ok := utxoSetIterator.First(); ok; ok = utxoSetIterator.Next() {
outpoint, entry, err := utxoSetIterator.Get()
if err != nil {
return err
}
serializedOutpoint, err := serializeOutpoint(toAddOutpoint)
serializedOutpoint, err := serializeOutpoint(outpoint)
if err != nil {
return err
}
key := pruningPointUTXOSetBucket.Key(serializedOutpoint)
serializedUTXOEntry, err := serializeUTXOEntry(entry)
if err != nil {
return err
}
err = dbContext.Put(pruningPointUTXOSetBucket.Key(serializedOutpoint), serializedUTXOEntry)
err = dbContext.Put(key, serializedUTXOEntry)
if err != nil {
return err
}
}
return nil
}
@@ -131,8 +127,8 @@ func (ps *pruningStore) UpdatePruningPointUTXOSet(dbContext model.DBWriter, diff
func (ps *pruningStore) PruningPoint(dbContext model.DBReader, stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.currentPruningPoint != nil {
return stagingShard.currentPruningPoint, nil
if stagingShard.newPruningPoint != nil {
return stagingShard.newPruningPoint, nil
}
if ps.pruningPointCache != nil {
@@ -152,30 +148,6 @@ func (ps *pruningStore) PruningPoint(dbContext model.DBReader, stagingArea *mode
return pruningPoint, nil
}
// OldPruningPoint returns the pruning point *before* the current one
func (ps *pruningStore) PreviousPruningPoint(dbContext model.DBReader, stagingArea *model.StagingArea) (*externalapi.DomainHash, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.previousPruningPoint != nil {
return stagingShard.previousPruningPoint, nil
}
if ps.oldPruningPointCache != nil {
return ps.oldPruningPointCache, nil
}
oldPruningPointBytes, err := dbContext.Get(previousPruningBlockHashKey)
if err != nil {
return nil, err
}
oldPruningPoint, err := ps.deserializePruningPoint(oldPruningPointBytes)
if err != nil {
return nil, err
}
ps.oldPruningPointCache = oldPruningPoint
return oldPruningPoint, nil
}
func (ps *pruningStore) serializeHash(hash *externalapi.DomainHash) ([]byte, error) {
return proto.Marshal(serialization.DomainHashToDbHash(hash))
}
@@ -193,7 +165,7 @@ func (ps *pruningStore) deserializePruningPoint(pruningPointBytes []byte) (*exte
func (ps *pruningStore) HasPruningPoint(dbContext model.DBReader, stagingArea *model.StagingArea) (bool, error) {
stagingShard := ps.stagingShard(stagingArea)
if stagingShard.currentPruningPoint != nil {
if stagingShard.newPruningPoint != nil {
return true, nil
}
@@ -204,14 +176,6 @@ func (ps *pruningStore) HasPruningPoint(dbContext model.DBReader, stagingArea *m
return dbContext.Has(pruningBlockHashKey)
}
func (ps *pruningStore) PruningPointUTXOIterator(dbContext model.DBReader) (externalapi.ReadOnlyUTXOSetIterator, error) {
cursor, err := dbContext.Cursor(pruningPointUTXOSetBucket)
if err != nil {
return nil, err
}
return ps.newCursorUTXOSetIterator(cursor), nil
}
func (ps *pruningStore) PruningPointUTXOs(dbContext model.DBReader,
fromOutpoint *externalapi.DomainOutpoint, limit int) ([]*externalapi.OutpointAndUTXOEntryPair, error) {

View File

@@ -28,9 +28,7 @@ func New(cacheSize int, preallocate bool) model.UTXODiffStore {
}
// Stage stages the given utxoDiff for the given blockHash
func (uds *utxoDiffStore) Stage(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
utxoDiff externalapi.UTXODiff, utxoDiffChild *externalapi.DomainHash) {
func (uds *utxoDiffStore) Stage(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash, utxoDiff externalapi.UTXODiff, utxoDiffChild *externalapi.DomainHash) {
stagingShard := uds.stagingShard(stagingArea)
stagingShard.utxoDiffToAdd[*blockHash] = utxoDiff

View File

@@ -5,6 +5,13 @@ import (
"os"
"sync"
daablocksstore "github.com/kaspanet/kaspad/domain/consensus/datastructures/daablocksstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/headersselectedchainstore"
"github.com/kaspanet/kaspad/domain/consensus/processes/dagtraversalmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/finalitymanager"
consensusdatabase "github.com/kaspanet/kaspad/domain/consensus/database"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/acceptancedatastore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockheaderstore"
@@ -12,10 +19,8 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockstatusstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/consensusstatestore"
daablocksstore "github.com/kaspanet/kaspad/domain/consensus/datastructures/daablocksstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/finalitystore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/ghostdagdatastore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/headersselectedchainstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/headersselectedtipstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/multisetstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/pruningstore"
@@ -29,9 +34,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/processes/coinbasemanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/consensusstatemanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/dagtopologymanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/dagtraversalmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/difficultymanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/finalitymanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/headersselectedtipmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/mergedepthmanager"
@@ -51,20 +54,11 @@ const (
defaultTestPreallocateCaches = false
)
// Config is the full config required to run consensus
type Config struct {
dagconfig.Params
// IsArchival tells the consensus if it should not prune old blocks
IsArchival bool
// EnableSanityCheckPruningUTXOSet checks the full pruning point utxo set against the commitment at every pruning movement
EnableSanityCheckPruningUTXOSet bool
}
// Factory instantiates new Consensuses
type Factory interface {
NewConsensus(config *Config, db infrastructuredatabase.Database) (
NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database, isArchivalNode bool) (
externalapi.Consensus, error)
NewTestConsensus(config *Config, testName string) (
NewTestConsensus(dagParams *dagconfig.Params, isArchivalNode bool, testName string) (
tc testapi.TestConsensus, teardown func(keepDataDir bool), err error)
SetTestDataDir(dataDir string)
@@ -94,12 +88,12 @@ func NewFactory() Factory {
}
// NewConsensus instantiates a new Consensus
func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Database) (
func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database, isArchivalNode bool) (
externalapi.Consensus, error) {
dbManager := consensusdatabase.New(db)
pruningWindowSizeForCaches := int(config.PruningDepth())
pruningWindowSizeForCaches := int(dagParams.PruningDepth())
var preallocateCaches bool
if f.preallocateCaches != nil {
@@ -110,7 +104,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
// This is used for caches that are used as part of deletePastBlocks that need to traverse until
// the previous pruning point.
pruningWindowSizePlusFinalityDepthForCache := int(config.PruningDepth() + config.FinalityDepth())
pruningWindowSizePlusFinalityDepthForCache := int(dagParams.PruningDepth() + dagParams.FinalityDepth())
// Data Structures
acceptanceDataStore := acceptancedatastore.New(200, preallocateCaches)
@@ -135,15 +129,15 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
// a single DifficultyAdjustmentWindow. To alleviate this problem we make sure that the cache size is at least
// dagParams.DifficultyAdjustmentWindowSize
ghostdagDataCacheSize := pruningWindowSizeForCaches
if ghostdagDataCacheSize < config.DifficultyAdjustmentWindowSize {
ghostdagDataCacheSize = config.DifficultyAdjustmentWindowSize
if ghostdagDataCacheSize < dagParams.DifficultyAdjustmentWindowSize {
ghostdagDataCacheSize = dagParams.DifficultyAdjustmentWindowSize
}
ghostdagDataStore := ghostdagdatastore.New(ghostdagDataCacheSize, preallocateCaches)
headersSelectedTipStore := headersselectedtipstore.New()
finalityStore := finalitystore.New(200, preallocateCaches)
headersSelectedChainStore := headersselectedchainstore.New(pruningWindowSizeForCaches, preallocateCaches)
daaBlocksStore := daablocksstore.New(pruningWindowSizeForCaches, int(config.FinalityDepth()), preallocateCaches)
daaBlocksStore := daablocksstore.New(pruningWindowSizeForCaches, int(dagParams.FinalityDepth()), preallocateCaches)
// Processes
reachabilityManager := reachabilitymanager.New(
@@ -160,7 +154,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
dagTopologyManager,
ghostdagDataStore,
blockHeaderStore,
config.K)
dagParams.K)
dagTraversalManager := dagtraversalmanager.New(
dbManager,
dagTopologyManager,
@@ -168,20 +162,20 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
reachabilityDataStore,
ghostdagManager,
consensusStateStore,
config.GenesisHash)
dagParams.GenesisHash)
pastMedianTimeManager := f.pastMedianTimeConsructor(
config.TimestampDeviationTolerance,
dagParams.TimestampDeviationTolerance,
dbManager,
dagTraversalManager,
blockHeaderStore,
ghostdagDataStore,
config.GenesisHash)
transactionValidator := transactionvalidator.New(config.BlockCoinbaseMaturity,
config.EnableNonNativeSubnetworks,
config.MassPerTxByte,
config.MassPerScriptPubKeyByte,
config.MassPerSigOp,
config.MaxCoinbasePayloadLength,
dagParams.GenesisHash)
transactionValidator := transactionvalidator.New(dagParams.BlockCoinbaseMaturity,
dagParams.EnableNonNativeSubnetworks,
dagParams.MassPerTxByte,
dagParams.MassPerScriptPubKeyByte,
dagParams.MassPerSigOp,
dagParams.MaxCoinbasePayloadLength,
dbManager,
pastMedianTimeManager,
ghostdagDataStore,
@@ -194,29 +188,29 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
daaBlocksStore,
dagTopologyManager,
dagTraversalManager,
config.PowMax,
config.DifficultyAdjustmentWindowSize,
config.DisableDifficultyAdjustment,
config.TargetTimePerBlock,
config.GenesisHash)
dagParams.PowMax,
dagParams.DifficultyAdjustmentWindowSize,
dagParams.DisableDifficultyAdjustment,
dagParams.TargetTimePerBlock,
dagParams.GenesisHash)
coinbaseManager := coinbasemanager.New(
dbManager,
config.SubsidyReductionInterval,
config.BaseSubsidy,
config.CoinbasePayloadScriptPublicKeyMaxLength,
dagParams.SubsidyReductionInterval,
dagParams.BaseSubsidy,
dagParams.CoinbasePayloadScriptPublicKeyMaxLength,
ghostdagDataStore,
acceptanceDataStore,
daaBlocksStore)
headerTipsManager := headersselectedtipmanager.New(dbManager, dagTopologyManager, dagTraversalManager,
ghostdagManager, headersSelectedTipStore, headersSelectedChainStore)
genesisHash := config.GenesisHash
genesisHash := dagParams.GenesisHash
finalityManager := finalitymanager.New(
dbManager,
dagTopologyManager,
finalityStore,
ghostdagDataStore,
genesisHash,
config.FinalityDepth())
dagParams.FinalityDepth())
mergeDepthManager := mergedepthmanager.New(
dbManager,
dagTopologyManager,
@@ -224,15 +218,15 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
finalityManager,
ghostdagDataStore)
blockValidator := blockvalidator.New(
config.PowMax,
config.SkipProofOfWork,
dagParams.PowMax,
dagParams.SkipProofOfWork,
genesisHash,
config.EnableNonNativeSubnetworks,
config.MaxBlockSize,
config.MergeSetSizeLimit,
config.MaxBlockParents,
config.TimestampDeviationTolerance,
config.TargetTimePerBlock,
dagParams.EnableNonNativeSubnetworks,
dagParams.MaxBlockSize,
dagParams.MergeSetSizeLimit,
dagParams.MaxBlockParents,
dagParams.TimestampDeviationTolerance,
dagParams.TargetTimePerBlock,
dbManager,
difficultyManager,
@@ -255,10 +249,10 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
)
consensusStateManager, err := consensusstatemanager.New(
dbManager,
config.PruningDepth(),
config.MaxMassAcceptedByBlock,
config.MaxBlockParents,
config.MergeSetSizeLimit,
dagParams.PruningDepth(),
dagParams.MaxMassAcceptedByBlock,
dagParams.MaxBlockParents,
dagParams.MergeSetSizeLimit,
genesisHash,
ghostdagManager,
@@ -305,11 +299,10 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
blockHeaderStore,
utxoDiffStore,
daaBlocksStore,
config.IsArchival,
isArchivalNode,
genesisHash,
config.FinalityDepth(),
config.PruningDepth(),
config.EnableSanityCheckPruningUTXOSet)
dagParams.FinalityDepth(),
dagParams.PruningDepth())
syncManager := syncmanager.New(
dbManager,
@@ -343,7 +336,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
blockProcessor := blockprocessor.New(
genesisHash,
config.TargetTimePerBlock,
dagParams.TargetTimePerBlock,
dbManager,
consensusStateManager,
pruningManager,
@@ -418,7 +411,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
}
if !genesisInfo.Exists {
_, err = c.ValidateAndInsertBlock(config.GenesisBlock)
_, err = c.ValidateAndInsertBlock(dagParams.GenesisBlock)
if err != nil {
return nil, err
}
@@ -432,7 +425,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
if err != nil {
return nil, err
}
err = pruningManager.UpdatePruningPointIfRequired()
err = pruningManager.UpdatePruningPointUTXOSetIfRequired()
if err != nil {
return nil, err
}
@@ -440,7 +433,7 @@ func (f *factory) NewConsensus(config *Config, db infrastructuredatabase.Databas
return c, nil
}
func (f *factory) NewTestConsensus(config *Config, testName string) (
func (f *factory) NewTestConsensus(dagParams *dagconfig.Params, isArchivalNode bool, testName string) (
tc testapi.TestConsensus, teardown func(keepDataDir bool), err error) {
datadir := f.dataDir
if datadir == "" {
@@ -462,7 +455,7 @@ func (f *factory) NewTestConsensus(config *Config, testName string) (
if err != nil {
return nil, nil, err
}
consensusAsInterface, err := f.NewConsensus(config, db)
consensusAsInterface, err := f.NewConsensus(dagParams, db, isArchivalNode)
if err != nil {
return nil, nil, err
}
@@ -472,7 +465,7 @@ func (f *factory) NewTestConsensus(config *Config, testName string) (
testTransactionValidator := transactionvalidator.NewTestTransactionValidator(consensusAsImplementation.transactionValidator)
tstConsensus := &testConsensus{
dagParams: &config.Params,
dagParams: dagParams,
consensus: consensusAsImplementation,
database: db,
testConsensusStateManager: testConsensusStateManager,

View File

@@ -11,7 +11,7 @@ import (
func TestNewConsensus(t *testing.T) {
f := NewFactory()
config := &Config{Params: dagconfig.DevnetParams}
dagParams := &dagconfig.DevnetParams
tmpDir, err := ioutil.TempDir("", "TestNewConsensus")
if err != nil {
@@ -23,7 +23,7 @@ func TestNewConsensus(t *testing.T) {
t.Fatalf("error in NewLevelDB: %s", err)
}
_, err = f.NewConsensus(config, db)
_, err = f.NewConsensus(dagParams, db, false)
if err != nil {
t.Fatalf("error in NewConsensus: %+v", err)
}

View File

@@ -1,26 +1,26 @@
package consensus_test
package consensus
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus"
"testing"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
"fmt"
"testing"
)
func TestFinality(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// Set finalityInterval to 50 blocks, so that test runs quickly
consensusConfig.FinalityDuration = 50 * consensusConfig.TargetTimePerBlock
params.FinalityDuration = 50 * params.TargetTimePerBlock
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestFinality")
factory := NewFactory()
consensus, teardown, err := factory.NewTestConsensus(params, false, "TestFinality")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -40,9 +40,9 @@ func TestFinality(t *testing.T) {
}
// Build a chain of `finalityInterval - 1` blocks
finalityInterval := consensusConfig.FinalityDepth()
finalityInterval := params.FinalityDepth()
var mainChainTip *externalapi.DomainBlock
mainChainTipHash := consensusConfig.GenesisHash
mainChainTipHash := params.GenesisHash
for i := uint64(0); i < finalityInterval-1; i++ {
mainChainTip, err = buildAndInsertBlock([]*externalapi.DomainHash{mainChainTipHash})
@@ -63,11 +63,11 @@ func TestFinality(t *testing.T) {
// Mine another chain of `finality-Interval - 2` blocks
var sideChainTip *externalapi.DomainBlock
sideChainTipHash := consensusConfig.GenesisHash
sideChainTipHash := params.GenesisHash
for i := uint64(0); i < finalityInterval-2; i++ {
sideChainTip, err = buildAndInsertBlock([]*externalapi.DomainHash{sideChainTipHash})
if err != nil {
t.Fatalf("TestFinality: Failed to process sidechain Block #%d: %+v", i, err)
t.Fatalf("TestFinality: Failed to process sidechain Block #%d: %v", i, err)
}
sideChainTipHash = consensushashing.BlockHash(sideChainTip)
@@ -127,7 +127,7 @@ func TestFinality(t *testing.T) {
t.Fatalf("TestFinality: Failed getting the virtual's finality point: %v", err)
}
if virtualFinality.Equal(consensusConfig.GenesisHash) {
if virtualFinality.Equal(params.GenesisHash) {
t.Fatalf("virtual's finalityPoint is still genesis after adding finalityInterval + 1 blocks to the main chain")
}
@@ -178,12 +178,12 @@ func TestFinality(t *testing.T) {
}
func TestBoundedMergeDepth(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// Set finalityInterval to 50 blocks, so that test runs quickly
consensusConfig.FinalityDuration = 50 * consensusConfig.TargetTimePerBlock
finalityInterval := int(consensusConfig.FinalityDepth())
params.FinalityDuration = 50 * params.TargetTimePerBlock
finalityInterval := int(params.FinalityDepth())
if int(consensusConfig.K) >= finalityInterval {
if int(params.K) >= finalityInterval {
t.Fatal("K must be smaller than finality duration for this test to run")
}
@@ -235,20 +235,20 @@ func TestBoundedMergeDepth(t *testing.T) {
return blockInfo.BlockStatus
}
factory := consensus.NewFactory()
consensusBuild, teardownFunc1, err := factory.NewTestConsensus(consensusConfig, "TestBoundedMergeTestBuild")
factory := NewFactory()
consensusBuild, teardownFunc1, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestBuild")
if err != nil {
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
}
consensusReal, teardownFunc2, err := factory.NewTestConsensus(consensusConfig, "TestBoundedMergeTestReal")
consensusReal, teardownFunc2, err := factory.NewTestConsensus(params, false, "TestBoundedMergeTestReal")
if err != nil {
t.Fatalf("TestBoundedMergeDepth: Error setting up consensus: %+v", err)
}
defer teardownFunc2(false)
// Create a block on top on genesis
block1 := buildAndInsertBlock(consensusBuild, []*externalapi.DomainHash{consensusConfig.GenesisHash})
block1 := buildAndInsertBlock(consensusBuild, []*externalapi.DomainHash{params.GenesisHash})
// Create a chain
selectedChain := make([]*externalapi.DomainBlock, 0, finalityInterval+1)
@@ -342,7 +342,7 @@ func TestBoundedMergeDepth(t *testing.T) {
// Now let's make the kosherizing block red and try to merge again
tip := consensushashing.BlockHash(selectedChain[len(selectedChain)-1])
// we use k-1 because `kosherizingBlock` points at tip-2, so 2+k-1 = k+1 anticone.
for i := 0; i < int(consensusConfig.K)-1; i++ {
for i := 0; i < int(params.K)-1; i++ {
block := buildAndInsertBlock(consensusReal, []*externalapi.DomainHash{tip})
tip = consensushashing.BlockHash(block)
}

View File

@@ -7,7 +7,6 @@ type Consensus interface {
ValidateTransactionAndPopulateWithConsensusData(transaction *DomainTransaction) error
GetBlock(blockHash *DomainHash) (*DomainBlock, error)
GetBlockEvenIfHeaderOnly(blockHash *DomainHash) (*DomainBlock, error)
GetBlockHeader(blockHash *DomainHash) (BlockHeader, error)
GetBlockInfo(blockHash *DomainHash) (*BlockInfo, error)
GetBlockRelations(blockHash *DomainHash) (parents []*DomainHash, selectedParent *DomainHash, children []*DomainHash, err error)

View File

@@ -14,7 +14,6 @@ type UTXODiff interface {
ToRemove() UTXOCollection
WithDiff(other UTXODiff) (UTXODiff, error)
DiffFrom(other UTXODiff) (UTXODiff, error)
Reversed() UTXODiff
CloneMutable() MutableUTXODiff
}

View File

@@ -6,5 +6,4 @@ type VirtualInfo struct {
Bits uint32
PastMedianTime int64
BlueScore uint64
DAAScore uint64
}

View File

@@ -6,19 +6,17 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
type PruningStore interface {
Store
StagePruningPoint(stagingArea *StagingArea, pruningPointBlockHash *externalapi.DomainHash)
StagePreviousPruningPoint(stagingArea *StagingArea, oldPruningPointBlockHash *externalapi.DomainHash)
StagePruningPointCandidate(stagingArea *StagingArea, candidate *externalapi.DomainHash)
IsStaged(stagingArea *StagingArea) bool
PruningPointCandidate(dbContext DBReader, stagingArea *StagingArea) (*externalapi.DomainHash, error)
HasPruningPointCandidate(dbContext DBReader, stagingArea *StagingArea) (bool, error)
PreviousPruningPoint(dbContext DBReader, stagingArea *StagingArea) (*externalapi.DomainHash, error)
PruningPoint(dbContext DBReader, stagingArea *StagingArea) (*externalapi.DomainHash, error)
HasPruningPoint(dbContext DBReader, stagingArea *StagingArea) (bool, error)
StageStartUpdatingPruningPointUTXOSet(stagingArea *StagingArea)
HadStartedUpdatingPruningPointUTXOSet(dbContext DBWriter) (bool, error)
FinishUpdatingPruningPointUTXOSet(dbContext DBWriter) error
UpdatePruningPointUTXOSet(dbContext DBWriter, diff externalapi.UTXODiff) error
UpdatePruningPointUTXOSet(dbContext DBWriter, utxoSetIterator externalapi.ReadOnlyUTXOSetIterator) error
ClearImportedPruningPointUTXOs(dbContext DBWriter) error
AppendImportedPruningPointUTXOs(dbTx DBTransaction, outpointAndUTXOEntryPairs []*externalapi.OutpointAndUTXOEntryPair) error
@@ -28,5 +26,4 @@ type PruningStore interface {
UpdateImportedPruningPointMultiset(dbTx DBTransaction, multiset Multiset) error
CommitImportedPruningPointUTXOSet(dbContext DBWriter) error
PruningPointUTXOs(dbContext DBReader, fromOutpoint *externalapi.DomainOutpoint, limit int) ([]*externalapi.OutpointAndUTXOEntryPair, error)
PruningPointUTXOIterator(dbContext DBReader) (externalapi.ReadOnlyUTXOSetIterator, error)
}

View File

@@ -4,12 +4,11 @@ import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
// ConsensusStateManager manages the node's consensus state
type ConsensusStateManager interface {
AddBlock(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, externalapi.UTXODiff, *UTXODiffReversalData, error)
AddBlock(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, externalapi.UTXODiff, error)
PopulateTransactionWithUTXOEntries(stagingArea *StagingArea, transaction *externalapi.DomainTransaction) error
ImportPruningPoint(stagingArea *StagingArea, newPruningPoint *externalapi.DomainBlock) error
RestorePastUTXOSetIterator(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (externalapi.ReadOnlyUTXOSetIterator, error)
CalculatePastUTXOAndAcceptanceData(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (externalapi.UTXODiff, externalapi.AcceptanceData, Multiset, error)
GetVirtualSelectedParentChainFromBlock(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, error)
RecoverUTXOIfRequired() error
ReverseUTXODiffs(tipHash *externalapi.DomainHash, reversalData *UTXODiffReversalData) error
}

View File

@@ -8,6 +8,6 @@ type PruningManager interface {
IsValidPruningPoint(stagingArea *StagingArea, blockHash *externalapi.DomainHash) (bool, error)
ClearImportedPruningPointData() error
AppendImportedPruningPointUTXOs(outpointAndUTXOEntryPairs []*externalapi.OutpointAndUTXOEntryPair) error
UpdatePruningPointIfRequired() error
UpdatePruningPointUTXOSetIfRequired() error
PruneAllBlocksBelow(stagingArea *StagingArea, pruningPointHash *externalapi.DomainHash) error
}

View File

@@ -11,5 +11,5 @@ type TestConsensusStateManager interface {
AddUTXOToMultiset(multiset model.Multiset, entry externalapi.UTXOEntry,
outpoint *externalapi.DomainOutpoint) error
ResolveBlockStatus(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
useSeparateStagingAreaPerBlock bool) (externalapi.BlockStatus, error)
useSeparateStagingAreasPerBlock bool) (externalapi.BlockStatus, error)
}

View File

@@ -1,9 +0,0 @@
package model
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
// UTXODiffReversalData is used by ConsensusStateManager to reverse the UTXODiffs during a re-org
type UTXODiffReversalData struct {
SelectedParentHash *externalapi.DomainHash
SelectedParentUTXODiff externalapi.UTXODiff
}

View File

@@ -1,21 +1,24 @@
package blockbuilder_test
import (
"github.com/pkg/errors"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"testing"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
func TestBuildBlockErrorCases(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
testConsensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockBuilderErrorCases")
testConsensus, teardown, err := factory.NewTestConsensus(
params, false, "TestBlockBuilderErrorCases")
if err != nil {
t.Fatalf("Error initializing consensus for: %+v", err)
}
@@ -33,7 +36,7 @@ func TestBuildBlockErrorCases(t *testing.T) {
"scriptPublicKey too long",
&externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: make([]byte, consensusConfig.CoinbasePayloadScriptPublicKeyMaxLength+1),
Script: make([]byte, params.CoinbasePayloadScriptPublicKeyMaxLength+1),
Version: 0,
},
ExtraData: nil,

View File

@@ -6,7 +6,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/pkg/errors"
)
@@ -119,11 +119,7 @@ func (bb *testBlockBuilder) buildBlockWithParents(stagingArea *model.StagingArea
*externalapi.DomainBlock, externalapi.UTXODiff, error) {
if coinbaseData == nil {
scriptPublicKeyScript, err := txscript.PayToScriptHashScript([]byte{txscript.OpTrue})
if err != nil {
panic(errors.Wrapf(err, "Couldn't parse opTrueScript. This should never happen"))
}
scriptPublicKey := &externalapi.ScriptPublicKey{Script: scriptPublicKeyScript, Version: constants.MaxScriptPublicKeyVersion}
scriptPublicKey, _ := testutils.OpTrueScript()
coinbaseData = &externalapi.DomainCoinbaseData{
ScriptPublicKey: scriptPublicKey,
ExtraData: []byte{},

View File

@@ -59,22 +59,6 @@ func (bp *blockProcessor) setBlockStatusAfterBlockValidation(
return nil
}
func (bp *blockProcessor) updateVirtualAcceptanceDataAfterImportingPruningPoint(stagingArea *model.StagingArea) error {
_, virtualAcceptanceData, virtualMultiset, err :=
bp.consensusStateManager.CalculatePastUTXOAndAcceptanceData(stagingArea, model.VirtualBlockHash)
if err != nil {
return err
}
log.Debugf("Staging virtual acceptance data after importing the pruning point")
bp.acceptanceDataStore.Stage(stagingArea, model.VirtualBlockHash, virtualAcceptanceData)
log.Debugf("Staging virtual multiset after importing the pruning point")
bp.multisetStore.Stage(stagingArea, model.VirtualBlockHash, virtualMultiset)
return nil
}
func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea, block *externalapi.DomainBlock,
isPruningPoint bool) (*externalapi.BlockInsertionResult, error) {
@@ -106,7 +90,6 @@ func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea,
var selectedParentChainChanges *externalapi.SelectedChainPath
var virtualUTXODiff externalapi.UTXODiff
var reversalData *model.UTXODiffReversalData
isHeaderOnlyBlock := isHeaderOnlyBlock(block)
if !isHeaderOnlyBlock {
// There's no need to update the consensus state manager when
@@ -114,12 +97,7 @@ func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea,
// in consensusStateManager.ImportPruningPoint
if !isPruningPoint {
// Attempt to add the block to the virtual
selectedParentChainChanges, virtualUTXODiff, reversalData, err = bp.consensusStateManager.AddBlock(stagingArea, blockHash)
if err != nil {
return nil, err
}
} else {
err := bp.updateVirtualAcceptanceDataAfterImportingPruningPoint(stagingArea)
selectedParentChainChanges, virtualUTXODiff, err = bp.consensusStateManager.AddBlock(stagingArea, blockHash)
if err != nil {
return nil, err
}
@@ -146,14 +124,7 @@ func (bp *blockProcessor) validateAndInsertBlock(stagingArea *model.StagingArea,
return nil, err
}
if reversalData != nil {
err = bp.consensusStateManager.ReverseUTXODiffs(blockHash, reversalData)
if err != nil {
return nil, err
}
}
err = bp.pruningManager.UpdatePruningPointIfRequired()
err = bp.pruningManager.UpdatePruningPointUTXOSetIfRequired()
if err != nil {
return nil, err
}

View File

@@ -4,22 +4,25 @@ import (
"strings"
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
func TestBlockStatus(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockStatus")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestBlockStatus")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -36,7 +39,7 @@ func TestBlockStatus(t *testing.T) {
}
}
tipHash := consensusConfig.GenesisHash
tipHash := params.GenesisHash
for i := 0; i < 2; i++ {
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
if err != nil {
@@ -53,7 +56,7 @@ func TestBlockStatus(t *testing.T) {
checkStatus(headerHash, externalapi.StatusHeaderOnly)
nonChainBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
nonChainBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -116,17 +119,17 @@ func TestValidateAndInsertErrors(t *testing.T) {
// Each test is covering the error cases in a sub-function in "validateAndInsertBlock" function.
// Currently, implemented only for some of the errors.
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockStatus")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestBlockStatus")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
tipHash, emptyCoinbase, tx1 := initData(consensusConfig)
tipHash, emptyCoinbase, tx1 := initData(params)
// Tests all the error case on the function: "checkBlockStatus"(sub-function in function validateBlock)
blockWithStatusInvalid, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash},
blockWithStatusInvalid, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash},
&emptyCoinbase, []*externalapi.DomainTransaction{tx1, tx1})
if err != nil {
t.Fatalf("AddBlock: %+v", err)
@@ -181,8 +184,8 @@ func TestValidateAndInsertErrors(t *testing.T) {
})
}
func initData(consensusConfig *consensus.Config) (*externalapi.DomainHash, externalapi.DomainCoinbaseData, *externalapi.DomainTransaction) {
return consensusConfig.GenesisHash,
func initData(params *dagconfig.Params) (*externalapi.DomainHash, externalapi.DomainCoinbaseData, *externalapi.DomainTransaction) {
return params.GenesisHash,
externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil,

View File

@@ -42,27 +42,27 @@ func addBlock(tcSyncer, tcSyncee testapi.TestConsensus, parentHashes []*external
}
func TestValidateAndInsertImportedPruningPoint(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// This is done to reduce the pruning depth to 6 blocks
finalityDepth := 3
consensusConfig.FinalityDuration = time.Duration(finalityDepth) * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = time.Duration(finalityDepth) * params.TargetTimePerBlock
params.K = 0
factory := consensus.NewFactory()
tcSyncer, teardownSyncer, err := factory.NewTestConsensus(consensusConfig, "TestValidateAndInsertPruningPointSyncer")
tcSyncer, teardownSyncer, err := factory.NewTestConsensus(params, false, "TestValidateAndInsertPruningPointSyncer")
if err != nil {
t.Fatalf("Error setting up tcSyncer: %+v", err)
}
defer teardownSyncer(false)
tcSyncee, teardownSyncee, err := factory.NewTestConsensus(consensusConfig, "TestValidateAndInsertPruningPointSyncee")
tcSyncee, teardownSyncee, err := factory.NewTestConsensus(params, false, "TestValidateAndInsertPruningPointSyncee")
if err != nil {
t.Fatalf("Error setting up tcSyncee: %+v", err)
}
defer teardownSyncee(false)
tipHash := consensusConfig.GenesisHash
tipHash := params.GenesisHash
for i := 0; i < finalityDepth-2; i++ {
tipHash = addBlock(tcSyncer, tcSyncee, []*externalapi.DomainHash{tipHash}, t)
}
@@ -83,7 +83,7 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) {
t.Fatalf("PruningPoint: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}
@@ -212,28 +212,28 @@ func TestValidateAndInsertImportedPruningPoint(t *testing.T) {
// IBD, while it already has a non-empty UTXO-Set originating from blocks mined on top of genesis - the resulting
// UTXO set is correct
func TestValidateAndInsertPruningPointWithSideBlocks(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// This is done to reduce the pruning depth to 6 blocks
finalityDepth := 3
consensusConfig.FinalityDuration = time.Duration(finalityDepth) * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = time.Duration(finalityDepth) * params.TargetTimePerBlock
params.K = 0
factory := consensus.NewFactory()
tcSyncer, teardownSyncer, err := factory.NewTestConsensus(consensusConfig, "TestValidateAndInsertPruningPointSyncer")
tcSyncer, teardownSyncer, err := factory.NewTestConsensus(params, false, "TestValidateAndInsertPruningPointSyncer")
if err != nil {
t.Fatalf("Error setting up tcSyncer: %+v", err)
}
defer teardownSyncer(false)
tcSyncee, teardownSyncee, err := factory.NewTestConsensus(consensusConfig, "TestValidateAndInsertPruningPointSyncee")
tcSyncee, teardownSyncee, err := factory.NewTestConsensus(params, false, "TestValidateAndInsertPruningPointSyncee")
if err != nil {
t.Fatalf("Error setting up tcSyncee: %+v", err)
}
defer teardownSyncee(false)
// Mine 2 block in the syncee on top of genesis
side, _, err := tcSyncee.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &externalapi.DomainCoinbaseData{ScriptPublicKey: &externalapi.ScriptPublicKey{}, ExtraData: []byte{1, 2}}, nil)
side, _, err := tcSyncee.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, &externalapi.DomainCoinbaseData{ScriptPublicKey: &externalapi.ScriptPublicKey{}, ExtraData: []byte{1, 2}}, nil)
if err != nil {
t.Fatal(err)
}
@@ -242,7 +242,7 @@ func TestValidateAndInsertPruningPointWithSideBlocks(t *testing.T) {
t.Fatal(err)
}
tipHash := consensusConfig.GenesisHash
tipHash := params.GenesisHash
for i := 0; i < finalityDepth-2; i++ {
tipHash = addBlock(tcSyncer, tcSyncee, []*externalapi.DomainHash{tipHash}, t)
}
@@ -261,7 +261,7 @@ func TestValidateAndInsertPruningPointWithSideBlocks(t *testing.T) {
t.Fatalf("PruningPoint: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}
@@ -421,16 +421,16 @@ func makeFakeUTXOs() []*externalapi.OutpointAndUTXOEntryPair {
}
func TestGetPruningPointUTXOs(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// This is done to reduce the pruning depth to 8 blocks
finalityDepth := 4
consensusConfig.FinalityDuration = time.Duration(finalityDepth) * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = time.Duration(finalityDepth) * params.TargetTimePerBlock
params.K = 0
consensusConfig.BlockCoinbaseMaturity = 0
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
testConsensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestGetPruningPointUTXOs")
testConsensus, teardown, err := factory.NewTestConsensus(params, false, "TestGetPruningPointUTXOs")
if err != nil {
t.Fatalf("Error setting up testConsensus: %+v", err)
}
@@ -518,7 +518,7 @@ func TestGetPruningPointUTXOs(t *testing.T) {
if err != nil {
t.Fatalf("Error getting the pruning point: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}
@@ -580,18 +580,18 @@ func TestGetPruningPointUTXOs(t *testing.T) {
}
func BenchmarkGetPruningPointUTXOs(b *testing.B) {
consensusConfig := consensus.Config{Params: dagconfig.DevnetParams}
params := dagconfig.DevnetParams
// This is done to reduce the pruning depth to 200 blocks
finalityDepth := 100
consensusConfig.FinalityDuration = time.Duration(finalityDepth) * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = time.Duration(finalityDepth) * params.TargetTimePerBlock
params.K = 0
consensusConfig.SkipProofOfWork = true
consensusConfig.BlockCoinbaseMaturity = 0
params.SkipProofOfWork = true
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
testConsensus, teardown, err := factory.NewTestConsensus(&consensusConfig, "TestGetPruningPointUTXOs")
testConsensus, teardown, err := factory.NewTestConsensus(&params, false, "TestGetPruningPointUTXOs")
if err != nil {
b.Fatalf("Error setting up testConsensus: %+v", err)
}
@@ -671,7 +671,7 @@ func BenchmarkGetPruningPointUTXOs(b *testing.B) {
if err != nil {
b.Fatalf("Error getting the pruning point: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}

View File

@@ -11,25 +11,26 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
func TestCheckBlockIsNotPruned(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// This is done to reduce the pruning depth to 6 blocks
consensusConfig.FinalityDuration = 2 * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = 2 * params.TargetTimePerBlock
params.K = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockIsNotPruned")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockIsNotPruned")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Add blocks until the pruning point changes
tipHash := consensusConfig.GenesisHash
tipHash := params.GenesisHash
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
@@ -51,7 +52,7 @@ func TestCheckBlockIsNotPruned(t *testing.T) {
t.Fatalf("PruningPoint: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}
@@ -75,20 +76,20 @@ func TestCheckBlockIsNotPruned(t *testing.T) {
}
func TestCheckParentBlockBodiesExist(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// This is done to reduce the pruning depth to 6 blocks
consensusConfig.FinalityDuration = 2 * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = 2 * params.TargetTimePerBlock
params.K = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckParentBlockBodiesExist")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckParentBlockBodiesExist")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
headerHash, _, err := tc.AddUTXOInvalidHeader([]*externalapi.DomainHash{consensusConfig.GenesisHash})
headerHash, _, err := tc.AddUTXOInvalidHeader([]*externalapi.DomainHash{params.GenesisHash})
if err != nil {
t.Fatalf("AddUTXOInvalidHeader: %+v", err)
}
@@ -104,7 +105,7 @@ func TestCheckParentBlockBodiesExist(t *testing.T) {
}
// Add blocks until the pruning point changes
tipHash := consensusConfig.GenesisHash
tipHash := params.GenesisHash
anticonePruningBlock, err := tc.BuildUTXOInvalidBlock([]*externalapi.DomainHash{tipHash})
if err != nil {
t.Fatalf("BuildUTXOInvalidBlock: %+v", err)
@@ -130,7 +131,7 @@ func TestCheckParentBlockBodiesExist(t *testing.T) {
t.Fatalf("PruningPoint: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}
@@ -145,20 +146,20 @@ func TestCheckParentBlockBodiesExist(t *testing.T) {
}
func TestIsFinalizedTransaction(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
consensusConfig.BlockCoinbaseMaturity = 0
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestIsFinalizedTransaction")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestIsFinalizedTransaction")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Build a small DAG
outerParents := []*externalapi.DomainHash{consensusConfig.GenesisHash}
outerParents := []*externalapi.DomainHash{params.GenesisHash}
for i := 0; i < 5; i++ {
var innerParents []*externalapi.DomainHash
for i := 0; i < 4; i++ {

View File

@@ -2,37 +2,39 @@ package blockvalidator_test
import (
"bytes"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"math"
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
func TestChainedTransactions(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.BlockCoinbaseMaturity = 0
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestChainedTransactions")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestChainedTransactions")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
fundingBlockHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -91,9 +93,9 @@ func TestChainedTransactions(t *testing.T) {
// TestCheckBlockSanity tests the CheckBlockSanity function to ensure it works
// as expected.
func TestCheckBlockSanity(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockSanity")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockSanity")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -998,15 +1000,15 @@ var blockWithWrongTxOrder = externalapi.DomainBlock{
}
func TestCheckBlockHashMerkleRoot(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockHashMerkleRoot")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockHashMerkleRoot")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err)
}
@@ -1028,16 +1030,16 @@ func TestCheckBlockHashMerkleRoot(t *testing.T) {
}
func TestBlockSize(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestBlockSize")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestBlockSize")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block, _, err := initBlockWithInvalidBlockSize(consensusConfig, tc)
block, _, err := initBlockWithInvalidBlockSize(params, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
}
@@ -1053,7 +1055,7 @@ func TestBlockSize(t *testing.T) {
})
}
func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
func initBlockWithInvalidBlockSize(params *dagconfig.Params, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
emptyCoinbase := externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil,
@@ -1082,20 +1084,20 @@ func initBlockWithInvalidBlockSize(consensusConfig *consensus.Config, tc testapi
Payload: []byte{0x01},
}
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})
return tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})
}
func TestCheckBlockDuplicateTransactions(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockDuplicateTransactions")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockDuplicateTransactions")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block, _, err := initBlockWithDuplicateTransaction(consensusConfig, tc)
block, _, err := initBlockWithDuplicateTransaction(params, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
}
@@ -1111,7 +1113,7 @@ func TestCheckBlockDuplicateTransactions(t *testing.T) {
})
}
func initBlockWithDuplicateTransaction(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
func initBlockWithDuplicateTransaction(params *dagconfig.Params, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
emptyCoinbase := externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil,
@@ -1139,20 +1141,20 @@ func initBlockWithDuplicateTransaction(consensusConfig *consensus.Config, tc tes
SubnetworkID: subnetworks.SubnetworkIDNative,
}
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx, tx})
return tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx, tx})
}
func TestCheckBlockContainsOnlyOneCoinbase(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockContainsOnlyOneCoinbase")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockContainsOnlyOneCoinbase")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block, _, err := initBlockWithMoreThanOneCoinbase(consensusConfig, tc)
block, _, err := initBlockWithMoreThanOneCoinbase(params, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
}
@@ -1168,7 +1170,7 @@ func TestCheckBlockContainsOnlyOneCoinbase(t *testing.T) {
})
}
func initBlockWithMoreThanOneCoinbase(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
func initBlockWithMoreThanOneCoinbase(params *dagconfig.Params, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
emptyCoinbase := externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil,
@@ -1196,20 +1198,20 @@ func initBlockWithMoreThanOneCoinbase(consensusConfig *consensus.Config, tc test
SubnetworkID: subnetworks.SubnetworkIDCoinbase,
}
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})
return tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, &emptyCoinbase, []*externalapi.DomainTransaction{tx})
}
func TestCheckBlockDoubleSpends(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockDoubleSpends")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockDoubleSpends")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block, _, err := initBlockWithDoubleSpends(consensusConfig, tc)
block, _, err := initBlockWithDoubleSpends(params, tc)
if err != nil {
t.Fatalf("Error BuildBlockWithParents : %+v", err)
}
@@ -1225,7 +1227,7 @@ func TestCheckBlockDoubleSpends(t *testing.T) {
})
}
func initBlockWithDoubleSpends(consensusConfig *consensus.Config, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
func initBlockWithDoubleSpends(params *dagconfig.Params, tc testapi.TestConsensus) (*externalapi.DomainBlock, externalapi.UTXODiff, error) {
emptyCoinbase := externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{
Script: nil,
@@ -1271,21 +1273,21 @@ func initBlockWithDoubleSpends(consensusConfig *consensus.Config, tc testapi.Tes
SubnetworkID: subnetworks.SubnetworkIDNative,
}
return tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash},
return tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash},
&emptyCoinbase, []*externalapi.DomainTransaction{tx, txSameOutpoint})
}
func TestCheckFirstBlockTransactionIsCoinbase(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckFirstBlockTransactionIsCoinbase")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckFirstBlockTransactionIsCoinbase")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
block := initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig)
block := initBlockWithFirstTransactionDifferentThanCoinbase(params)
blockHash := consensushashing.BlockHash(block)
stagingArea := model.NewStagingArea()
tc.BlockStore().Stage(stagingArea, blockHash, block)
@@ -1298,7 +1300,7 @@ func TestCheckFirstBlockTransactionIsCoinbase(t *testing.T) {
})
}
func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consensus.Config) *externalapi.DomainBlock {
func initBlockWithFirstTransactionDifferentThanCoinbase(params *dagconfig.Params) *externalapi.DomainBlock {
prevOutTxID := &externalapi.DomainTransactionID{}
prevOutPoint := externalapi.DomainOutpoint{TransactionID: *prevOutTxID, Index: 1}
txInput := externalapi.DomainTransactionInput{
@@ -1318,7 +1320,7 @@ func initBlockWithFirstTransactionDifferentThanCoinbase(consensusConfig *consens
return &externalapi.DomainBlock{
Header: blockheader.NewImmutableBlockHeader(
constants.MaxBlockVersion,
[]*externalapi.DomainHash{consensusConfig.GenesisHash},
[]*externalapi.DomainHash{params.GenesisHash},
merkle.CalculateHashMerkleRoot([]*externalapi.DomainTransaction{tx}),
&externalapi.DomainHash{},
externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{

View File

@@ -12,12 +12,13 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestValidateMedianTime(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateMedianTime")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestValidateMedianTime")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -61,8 +62,8 @@ func TestValidateMedianTime(t *testing.T) {
return pastMedianTime
}
tip := consensusConfig.GenesisBlock
tipHash := consensusConfig.GenesisHash
tip := params.GenesisBlock
tipHash := params.GenesisHash
blockTime := tip.Header.TimeInMilliseconds()
@@ -83,15 +84,15 @@ func TestValidateMedianTime(t *testing.T) {
}
func TestCheckParentsIncest(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckParentsIncest")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckParentsIncest")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
a, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
a, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -101,7 +102,7 @@ func TestCheckParentsIncest(t *testing.T) {
t.Fatalf("AddBlock: %+v", err)
}
c, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
c, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -128,7 +129,7 @@ func TestCheckParentsIncest(t *testing.T) {
indirectParentsRelationBlock := &externalapi.DomainBlock{
Header: blockheader.NewImmutableBlockHeader(
0,
[]*externalapi.DomainHash{consensusConfig.GenesisHash, b},
[]*externalapi.DomainHash{params.GenesisHash, b},
&externalapi.DomainHash{},
&externalapi.DomainHash{},
&externalapi.DomainHash{},
@@ -153,25 +154,25 @@ func TestCheckParentsIncest(t *testing.T) {
}
func TestCheckMergeSizeLimit(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.MergeSetSizeLimit = 2 * uint64(consensusConfig.K)
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.MergeSetSizeLimit = 2 * uint64(params.K)
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckParentsIncest")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckParentsIncest")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
chain1TipHash := consensusConfig.GenesisHash
for i := uint64(0); i < consensusConfig.MergeSetSizeLimit+2; i++ {
chain1TipHash := params.GenesisHash
for i := uint64(0); i < params.MergeSetSizeLimit+2; i++ {
chain1TipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{chain1TipHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
}
chain2TipHash := consensusConfig.GenesisHash
for i := uint64(0); i < consensusConfig.MergeSetSizeLimit+1; i++ {
chain2TipHash := params.GenesisHash
for i := uint64(0); i < params.MergeSetSizeLimit+1; i++ {
chain2TipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{chain2TipHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)

View File

@@ -1,8 +1,6 @@
package blockvalidator_test
import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
@@ -10,22 +8,24 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util/mstime"
"github.com/pkg/errors"
"testing"
)
func TestCheckParentsLimit(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckParentsLimit")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckParentsLimit")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
for i := model.KType(0); i < consensusConfig.MaxBlockParents+1; i++ {
_, _, err = tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
for i := model.KType(0); i < params.MaxBlockParents+1; i++ {
_, _, err = tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -44,16 +44,16 @@ func TestCheckParentsLimit(t *testing.T) {
}
func TestCheckBlockVersion(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockVersion")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockVersion")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err)
}
@@ -77,23 +77,23 @@ func TestCheckBlockVersion(t *testing.T) {
}
func TestCheckBlockTimestampInIsolation(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckBlockTimestampInIsolation")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckBlockTimestampInIsolation")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err)
}
// Give 10 seconds slack to take care of the test duration
timestamp := mstime.Now().UnixMilliseconds() +
int64(consensusConfig.TimestampDeviationTolerance)*consensusConfig.TargetTimePerBlock.Milliseconds() + 10_000
int64(params.TimestampDeviationTolerance)*params.TargetTimePerBlock.Milliseconds() + 10_000
block.Header = blockheader.NewImmutableBlockHeader(
block.Header.Version(),

View File

@@ -3,9 +3,9 @@ package blockvalidator
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/pow"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/pow"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/kaspanet/kaspad/util/difficulty"

View File

@@ -7,34 +7,36 @@ import (
"testing"
"time"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/pow"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/merkle"
"github.com/kaspanet/kaspad/domain/consensus/utils/mining"
"github.com/kaspanet/kaspad/domain/consensus/utils/pow"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/util/difficulty"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
// TestPOW tests the validation of the block's POW.
func TestPOW(t *testing.T) {
// We set the flag "skip pow" to be false (second argument in the function) for not skipping the check of POW and validate its correctness.
testutils.ForAllNets(t, false, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, false, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestPOW")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestPOW")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Builds and checks block with invalid POW.
invalidBlockWrongPOW, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
invalidBlockWrongPOW, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -44,12 +46,12 @@ func TestPOW(t *testing.T) {
t.Fatalf("Expected block to be invalid with err: %v, instead found: %v", ruleerrors.ErrInvalidPoW, err)
}
abovePowMaxBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
abovePowMaxBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
abovePowMaxTarget := big.NewInt(0).Add(big.NewInt(1), consensusConfig.PowMax)
abovePowMaxTarget := big.NewInt(0).Add(big.NewInt(1), params.PowMax)
abovePowMaxBlock.Header = blockheader.NewImmutableBlockHeader(
abovePowMaxBlock.Header.Version(),
abovePowMaxBlock.Header.ParentHashes(),
@@ -66,7 +68,7 @@ func TestPOW(t *testing.T) {
t.Fatalf("Unexpected error: %+v", err)
}
negativeTargetBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
negativeTargetBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -88,7 +90,7 @@ func TestPOW(t *testing.T) {
}
// test on a valid block.
validBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
validBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -118,16 +120,16 @@ func solveBlockWithWrongPOW(block *externalapi.DomainBlock) *externalapi.DomainB
}
func TestCheckParentHeadersExist(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckParentHeadersExist")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckParentHeadersExist")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
orphanBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
orphanBlock, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -157,7 +159,7 @@ func TestCheckParentHeadersExist(t *testing.T) {
}
invalidBlock, _, err := tc.BuildBlockWithParents(
[]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
[]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -181,7 +183,7 @@ func TestCheckParentHeadersExist(t *testing.T) {
invalidBlockHash := consensushashing.BlockHash(invalidBlock)
invalidBlockChild, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
invalidBlockChild, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatal(err)
}
@@ -205,21 +207,21 @@ func TestCheckParentHeadersExist(t *testing.T) {
}
func TestCheckPruningPointViolation(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
// This is done to reduce the pruning depth to 6 blocks
consensusConfig.FinalityDuration = 2 * consensusConfig.TargetTimePerBlock
consensusConfig.K = 0
params.FinalityDuration = 2 * params.TargetTimePerBlock
params.K = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCheckPruningPointViolation")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestCheckPruningPointViolation")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Add blocks until the pruning point changes
tipHash := consensusConfig.GenesisHash
tipHash := params.GenesisHash
for {
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
if err != nil {
@@ -231,12 +233,12 @@ func TestCheckPruningPointViolation(t *testing.T) {
t.Fatalf("PruningPoint: %+v", err)
}
if !pruningPoint.Equal(consensusConfig.GenesisHash) {
if !pruningPoint.Equal(params.GenesisHash) {
break
}
}
_, _, err = tc.AddUTXOInvalidBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash})
_, _, err = tc.AddUTXOInvalidBlock([]*externalapi.DomainHash{params.GenesisHash})
if !errors.Is(err, ruleerrors.ErrPruningPointViolation) {
t.Fatalf("Unexpected error: %+v", err)
}
@@ -249,7 +251,7 @@ func TestCheckPruningPointViolation(t *testing.T) {
// "calculated" by the mocDifficultyManager, where mocDifficultyManager is special implementation
// of the type DifficultyManager for this test (defined below).
func TestValidateDifficulty(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
mocDifficulty := &mocDifficultyManager{}
factory.SetTestDifficultyManager(func(_ model.DBReader, _ model.GHOSTDAGManager, _ model.GHOSTDAGDataStore,
@@ -260,10 +262,10 @@ func TestValidateDifficulty(t *testing.T) {
mocDifficulty.daaBlocksStore = daaBlocksStore
return mocDifficulty
})
genesisDifficulty := consensusConfig.GenesisBlock.Header.Bits()
genesisDifficulty := params.GenesisBlock.Header.Bits()
mocDifficulty.testDifficulty = genesisDifficulty
mocDifficulty.testGenesisBits = genesisDifficulty
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateDifficulty")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestValidateDifficulty")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -275,7 +277,7 @@ func TestValidateDifficulty(t *testing.T) {
Version: 0,
},
}
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{consensusConfig.GenesisHash}, &emptyCoinbase, nil)
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, &emptyCoinbase, nil)
if err != nil {
t.Fatalf("TestValidateDifficulty: Failed build block with parents: %v.", err)
}

View File

@@ -9,19 +9,16 @@ import (
// AddBlock submits the given block to be added to the
// current virtual. This process may result in a new virtual block
// getting created
func (csm *consensusStateManager) AddBlock(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (
*externalapi.SelectedChainPath, externalapi.UTXODiff, *model.UTXODiffReversalData, error) {
func (csm *consensusStateManager) AddBlock(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (*externalapi.SelectedChainPath, externalapi.UTXODiff, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "csm.AddBlock")
defer onEnd()
log.Debugf("Resolving whether the block %s is the next virtual selected parent", blockHash)
isCandidateToBeNextVirtualSelectedParent, err := csm.isCandidateToBeNextVirtualSelectedParent(stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
var reversalData *model.UTXODiffReversalData
if isCandidateToBeNextVirtualSelectedParent {
// It's important to check for finality violation before resolving the block status, because the status of
// blocks with a selected chain that doesn't contain the pruning point cannot be resolved because they will
@@ -30,7 +27,7 @@ func (csm *consensusStateManager) AddBlock(stagingArea *model.StagingArea, block
"finality", blockHash)
isViolatingFinality, shouldNotify, err := csm.isViolatingFinality(stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
if shouldNotify {
@@ -40,10 +37,9 @@ func (csm *consensusStateManager) AddBlock(stagingArea *model.StagingArea, block
if !isViolatingFinality {
log.Debugf("Block %s doesn't violate finality. Resolving its block status", blockHash)
var blockStatus externalapi.BlockStatus
blockStatus, reversalData, err = csm.resolveBlockStatus(stagingArea, blockHash, true)
blockStatus, err := csm.resolveBlockStatus(stagingArea, blockHash, true)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
log.Debugf("Block %s resolved to status `%s`", blockHash, blockStatus)
@@ -56,17 +52,17 @@ func (csm *consensusStateManager) AddBlock(stagingArea *model.StagingArea, block
log.Debugf("Adding block %s to the DAG tips", blockHash)
newTips, err := csm.addTip(stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
log.Debugf("After adding %s, the amount of new tips are %d", blockHash, len(newTips))
log.Debugf("Updating the virtual with the new tips")
selectedParentChainChanges, virtualUTXODiff, err := csm.updateVirtual(stagingArea, blockHash, newTips)
if err != nil {
return nil, nil, nil, err
return nil, nil, err
}
return selectedParentChainChanges, virtualUTXODiff, reversalData, nil
return selectedParentChainChanges, virtualUTXODiff, nil
}
func (csm *consensusStateManager) isCandidateToBeNextVirtualSelectedParent(

View File

@@ -10,19 +10,20 @@ import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestVirtualDiff(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestVirtualDiff")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestVirtualDiff")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
defer teardown(false)
// Add block A over the genesis
blockAHash, blockInsertionResult, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
blockAHash, blockInsertionResult, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("Error adding block A: %+v", err)
}

View File

@@ -39,27 +39,15 @@ func (csm *consensusStateManager) CalculatePastUTXOAndAcceptanceData(stagingArea
return nil, nil, nil, err
}
log.Debugf("Restored the past UTXO of block %s with selectedParent %s. "+
"Diff toAdd length: %d, toRemove length: %d", blockHash, blockGHOSTDAGData.SelectedParent(),
selectedParentPastUTXO.ToAdd().Len(), selectedParentPastUTXO.ToRemove().Len())
return csm.calculatePastUTXOAndAcceptanceDataWithSelectedParentUTXO(stagingArea, blockHash, selectedParentPastUTXO)
}
func (csm *consensusStateManager) calculatePastUTXOAndAcceptanceDataWithSelectedParentUTXO(stagingArea *model.StagingArea,
blockHash *externalapi.DomainHash, selectedParentPastUTXO externalapi.UTXODiff) (
externalapi.UTXODiff, externalapi.AcceptanceData, model.Multiset, error) {
blockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
}
daaScore, err := csm.daaBlocksStore.DAAScore(csm.databaseContext, stagingArea, blockHash)
if err != nil {
return nil, nil, nil, err
}
log.Debugf("Restored the past UTXO of block %s with selectedParent %s. "+
"Diff toAdd length: %d, toRemove length: %d", blockHash, blockGHOSTDAGData.SelectedParent(),
selectedParentPastUTXO.ToAdd().Len(), selectedParentPastUTXO.ToRemove().Len())
log.Debugf("Applying blue blocks to the selected parent past UTXO of block %s", blockHash)
acceptanceData, utxoDiff, err := csm.applyMergeSetBlocks(
stagingArea, blockHash, selectedParentPastUTXO, blockGHOSTDAGData, daaScore)
@@ -78,7 +66,7 @@ func (csm *consensusStateManager) calculatePastUTXOAndAcceptanceDataWithSelected
}
func (csm *consensusStateManager) restorePastUTXO(
stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (externalapi.UTXODiff, error) {
stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (externalapi.MutableUTXODiff, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "restorePastUTXO")
defer onEnd()
@@ -132,11 +120,11 @@ func (csm *consensusStateManager) restorePastUTXO(
}
log.Tracef("The accumulated diff for block %s is: %s", blockHash, accumulatedDiff)
return accumulatedDiff.ToImmutable(), nil
return accumulatedDiff, nil
}
func (csm *consensusStateManager) applyMergeSetBlocks(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
selectedParentPastUTXODiff externalapi.UTXODiff, ghostdagData *model.BlockGHOSTDAGData, daaScore uint64) (
selectedParentPastUTXODiff externalapi.MutableUTXODiff, ghostdagData *model.BlockGHOSTDAGData, daaScore uint64) (
externalapi.AcceptanceData, externalapi.MutableUTXODiff, error) {
log.Debugf("applyMergeSetBlocks start for block %s", blockHash)
@@ -156,7 +144,7 @@ func (csm *consensusStateManager) applyMergeSetBlocks(stagingArea *model.Staging
log.Tracef("The past median time for block %s is: %d", blockHash, selectedParentMedianTime)
multiblockAcceptanceData := make(externalapi.AcceptanceData, len(mergeSetBlocks))
accumulatedUTXODiff := selectedParentPastUTXODiff.CloneMutable()
accumulatedUTXODiff := selectedParentPastUTXODiff
accumulatedMass := uint64(0)
for i, mergeSetBlock := range mergeSetBlocks {
@@ -289,13 +277,12 @@ func (csm *consensusStateManager) checkTransactionMass(
}
// RestorePastUTXOSetIterator restores the given block's UTXOSet iterator, and returns it as a externalapi.ReadOnlyUTXOSetIterator
func (csm *consensusStateManager) RestorePastUTXOSetIterator(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (
externalapi.ReadOnlyUTXOSetIterator, error) {
func (csm *consensusStateManager) RestorePastUTXOSetIterator(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (externalapi.ReadOnlyUTXOSetIterator, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "RestorePastUTXOSetIterator")
defer onEnd()
blockStatus, _, err := csm.resolveBlockStatus(stagingArea, blockHash, true)
blockStatus, err := csm.resolveBlockStatus(stagingArea, blockHash, true)
if err != nil {
return nil, err
}
@@ -319,5 +306,5 @@ func (csm *consensusStateManager) RestorePastUTXOSetIterator(stagingArea *model.
return nil, err
}
return utxo.IteratorWithDiff(virtualUTXOSetIterator, blockDiff)
return utxo.IteratorWithDiff(virtualUTXOSetIterator, blockDiff.ToImmutable())
}

View File

@@ -3,21 +3,25 @@ package consensusstatemanager_test
import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/multiset"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestUTXOCommitment(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.BlockCoinbaseMaturity = 0
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestUTXOCommitment")
consensus, teardown, err := factory.NewTestConsensus(params, false, "TestUTXOCommitment")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -27,7 +31,7 @@ func TestUTXOCommitment(t *testing.T) {
// G <- A <- B <- C <- E
// <- D <-
// Where block D has a non-coinbase transaction
genesisHash := consensusConfig.GenesisHash
genesisHash := params.GenesisHash
// Block A:
blockAHash, _, err := consensus.AddBlock([]*externalapi.DomainHash{genesisHash}, nil, nil)
@@ -111,19 +115,19 @@ func checkBlockUTXOCommitment(t *testing.T, consensus testapi.TestConsensus, blo
}
func TestPastUTXOMultiset(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestUTXOCommitment")
consensus, teardown, err := factory.NewTestConsensus(params, false, "TestUTXOCommitment")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Build a short chain
currentHash := consensusConfig.GenesisHash
currentHash := params.GenesisHash
for i := 0; i < 3; i++ {
currentHash, _, err = consensus.AddBlock([]*externalapi.DomainHash{currentHash}, nil, nil)
if err != nil {

View File

@@ -7,19 +7,20 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestCalculateChainPath(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestCalculateChainPath")
consensus, teardown, err := factory.NewTestConsensus(params, false, "TestCalculateChainPath")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Add block A over the genesis
blockAHash, blockAInsertionResult, err := consensus.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
blockAHash, blockAInsertionResult, err := consensus.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("Error adding block A: %+v", err)
}
@@ -41,7 +42,7 @@ func TestCalculateChainPath(t *testing.T) {
}
// Add block B over the genesis
blockBHash, _, err := consensus.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
blockBHash, _, err := consensus.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("Error adding block B: %+v", err)
}
@@ -92,7 +93,7 @@ func TestCalculateChainPath(t *testing.T) {
}
// Add block D over the genesis
_, blockDInsertionResult, err := consensus.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
_, blockDInsertionResult, err := consensus.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("Error adding block D: %+v", err)
}

View File

@@ -3,8 +3,6 @@ package consensusstatemanager
import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/util/staging"
"github.com/kaspanet/kaspad/domain/consensus/model"
@@ -15,7 +13,7 @@ import (
)
func (csm *consensusStateManager) resolveBlockStatus(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
useSeparateStagingAreaPerBlock bool) (externalapi.BlockStatus, *model.UTXODiffReversalData, error) {
useSeparateStagingAreasPerBlock bool) (externalapi.BlockStatus, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, fmt.Sprintf("resolveBlockStatus for %s", blockHash))
defer onEnd()
@@ -24,7 +22,7 @@ func (csm *consensusStateManager) resolveBlockStatus(stagingArea *model.StagingA
"parent chain of %s that have no yet resolved their status", blockHash)
unverifiedBlocks, err := csm.getUnverifiedChainBlocks(stagingArea, blockHash)
if err != nil {
return 0, nil, err
return 0, err
}
log.Debugf("Got %d unverified blocks in the selected parent "+
"chain of %s: %s", len(unverifiedBlocks), blockHash, unverifiedBlocks)
@@ -36,33 +34,26 @@ func (csm *consensusStateManager) resolveBlockStatus(stagingArea *model.StagingA
"This means that the block already has a UTXO-verified status.", blockHash)
status, err := csm.blockStatusStore.Get(csm.databaseContext, stagingArea, blockHash)
if err != nil {
return 0, nil, err
return 0, err
}
log.Debugf("Block %s's status resolved to: %s", blockHash, status)
return status, nil, nil
return status, nil
}
log.Debugf("Finding the status of the selected parent of %s", blockHash)
selectedParentHash, selectedParentStatus, selectedParentUTXOSet, err := csm.selectedParentInfo(stagingArea, unverifiedBlocks)
selectedParentStatus, err := csm.findSelectedParentStatus(stagingArea, unverifiedBlocks)
if err != nil {
return 0, nil, err
return 0, err
}
log.Debugf("The status of the selected parent of %s is: %s", blockHash, selectedParentStatus)
log.Debugf("Resolving the unverified blocks' status in reverse order (past to present)")
var blockStatus externalapi.BlockStatus
previousBlockHash := selectedParentHash
previousBlockUTXOSet := selectedParentUTXOSet
var oneBeforeLastResolvedBlockUTXOSet externalapi.UTXODiff
var oneBeforeLastResolvedBlockHash *externalapi.DomainHash
for i := len(unverifiedBlocks) - 1; i >= 0; i-- {
unverifiedBlockHash := unverifiedBlocks[i]
stagingAreaForCurrentBlock := stagingArea
isResolveTip := i == 0
useSeparateStagingArea := useSeparateStagingAreaPerBlock && !isResolveTip
useSeparateStagingArea := useSeparateStagingAreasPerBlock && (i != 0)
if useSeparateStagingArea {
stagingAreaForCurrentBlock = model.NewStagingArea()
}
@@ -70,13 +61,9 @@ func (csm *consensusStateManager) resolveBlockStatus(stagingArea *model.StagingA
if selectedParentStatus == externalapi.StatusDisqualifiedFromChain {
blockStatus = externalapi.StatusDisqualifiedFromChain
} else {
oneBeforeLastResolvedBlockUTXOSet = previousBlockUTXOSet
oneBeforeLastResolvedBlockHash = previousBlockHash
blockStatus, previousBlockUTXOSet, err = csm.resolveSingleBlockStatus(
stagingAreaForCurrentBlock, unverifiedBlockHash, previousBlockHash, previousBlockUTXOSet, isResolveTip)
blockStatus, err = csm.resolveSingleBlockStatus(stagingAreaForCurrentBlock, unverifiedBlockHash)
if err != nil {
return 0, nil, err
return 0, err
}
}
@@ -88,39 +75,17 @@ func (csm *consensusStateManager) resolveBlockStatus(stagingArea *model.StagingA
if useSeparateStagingArea {
err := staging.CommitAllChanges(csm.databaseContext, stagingAreaForCurrentBlock)
if err != nil {
return 0, nil, err
return 0, err
}
}
previousBlockHash = unverifiedBlockHash
}
var reversalData *model.UTXODiffReversalData
if blockStatus == externalapi.StatusUTXOValid && len(unverifiedBlocks) > 1 {
log.Debugf("Preparing data for reversing the UTXODiff")
// During resolveSingleBlockStatus, all unverifiedBlocks (excluding the tip) were assigned their selectedParent
// as their UTXODiffChild.
// Now that the whole chain has been resolved - we can reverse the UTXODiffs, to create shorter UTXODiffChild paths.
// However, we can't do this right now, because the tip of the chain is not yet committed, so we prepare the
// needed data (tip's selectedParent and selectedParent's UTXODiff)
selectedParentUTXODiff, err := previousBlockUTXOSet.DiffFrom(oneBeforeLastResolvedBlockUTXOSet)
if err != nil {
return 0, nil, err
}
reversalData = &model.UTXODiffReversalData{
SelectedParentHash: oneBeforeLastResolvedBlockHash,
SelectedParentUTXODiff: selectedParentUTXODiff,
}
}
return blockStatus, reversalData, nil
return blockStatus, nil
}
// selectedParentInfo returns the hash and status of the selectedParent of the last block in the unverifiedBlocks
// chain, in addition, if the status is UTXOValid, it return it's pastUTXOSet
func (csm *consensusStateManager) selectedParentInfo(
stagingArea *model.StagingArea, unverifiedBlocks []*externalapi.DomainHash) (
*externalapi.DomainHash, externalapi.BlockStatus, externalapi.UTXODiff, error) {
// findSelectedParentStatus returns the status of the selectedParent of the last block in the unverifiedBlocks chain
func (csm *consensusStateManager) findSelectedParentStatus(
stagingArea *model.StagingArea, unverifiedBlocks []*externalapi.DomainHash) (externalapi.BlockStatus, error) {
log.Debugf("findSelectedParentStatus start")
defer log.Debugf("findSelectedParentStatus end")
@@ -129,26 +94,13 @@ func (csm *consensusStateManager) selectedParentInfo(
if lastUnverifiedBlock.Equal(csm.genesisHash) {
log.Debugf("the most recent unverified block is the genesis block, "+
"which by definition has status: %s", externalapi.StatusUTXOValid)
return lastUnverifiedBlock, externalapi.StatusUTXOValid, utxo.NewUTXODiff(), nil
return externalapi.StatusUTXOValid, nil
}
lastUnverifiedBlockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, stagingArea, lastUnverifiedBlock)
if err != nil {
return nil, 0, nil, err
return 0, err
}
selectedParent := lastUnverifiedBlockGHOSTDAGData.SelectedParent()
selectedParentStatus, err := csm.blockStatusStore.Get(csm.databaseContext, stagingArea, selectedParent)
if err != nil {
return nil, 0, nil, err
}
if selectedParentStatus != externalapi.StatusUTXOValid {
return selectedParent, selectedParentStatus, nil, nil
}
selectedParentUTXOSet, err := csm.restorePastUTXO(stagingArea, selectedParent)
if err != nil {
return nil, 0, nil, err
}
return selectedParent, selectedParentStatus, selectedParentUTXOSet, nil
return csm.blockStatusStore.Get(csm.databaseContext, stagingArea, lastUnverifiedBlockGHOSTDAGData.SelectedParent())
}
func (csm *consensusStateManager) getUnverifiedChainBlocks(stagingArea *model.StagingArea,
@@ -190,17 +142,15 @@ func (csm *consensusStateManager) getUnverifiedChainBlocks(stagingArea *model.St
}
func (csm *consensusStateManager) resolveSingleBlockStatus(stagingArea *model.StagingArea,
blockHash, selectedParentHash *externalapi.DomainHash, selectedParentPastUTXOSet externalapi.UTXODiff, isResolveTip bool) (
externalapi.BlockStatus, externalapi.UTXODiff, error) {
blockHash *externalapi.DomainHash) (externalapi.BlockStatus, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, fmt.Sprintf("resolveSingleBlockStatus for %s", blockHash))
defer onEnd()
log.Tracef("Calculating pastUTXO and acceptance data and multiset for block %s", blockHash)
pastUTXOSet, acceptanceData, multiset, err := csm.calculatePastUTXOAndAcceptanceDataWithSelectedParentUTXO(
stagingArea, blockHash, selectedParentPastUTXOSet)
pastUTXODiff, acceptanceData, multiset, err := csm.CalculatePastUTXOAndAcceptanceData(stagingArea, blockHash)
if err != nil {
return 0, nil, err
return 0, err
}
log.Tracef("Staging the calculated acceptance data of block %s", blockHash)
@@ -208,17 +158,17 @@ func (csm *consensusStateManager) resolveSingleBlockStatus(stagingArea *model.St
block, err := csm.blockStore.Block(csm.databaseContext, stagingArea, blockHash)
if err != nil {
return 0, nil, err
return 0, err
}
log.Tracef("verifying the UTXO of block %s", blockHash)
err = csm.verifyUTXO(stagingArea, block, blockHash, pastUTXOSet, acceptanceData, multiset)
err = csm.verifyUTXO(stagingArea, block, blockHash, pastUTXODiff, acceptanceData, multiset)
if err != nil {
if errors.As(err, &ruleerrors.RuleError{}) {
log.Debugf("UTXO verification for block %s failed: %s", blockHash, err)
return externalapi.StatusDisqualifiedFromChain, nil, nil
return externalapi.StatusDisqualifiedFromChain, nil
}
return 0, nil, err
return 0, err
}
log.Debugf("UTXO verification for block %s passed", blockHash)
@@ -227,62 +177,45 @@ func (csm *consensusStateManager) resolveSingleBlockStatus(stagingArea *model.St
if csm.genesisHash.Equal(blockHash) {
log.Tracef("Staging the utxoDiff of genesis")
csm.stageDiff(stagingArea, blockHash, pastUTXOSet, nil)
return externalapi.StatusUTXOValid, nil, nil
csm.stageDiff(stagingArea, blockHash, pastUTXODiff, nil)
return externalapi.StatusUTXOValid, nil
}
oldSelectedTip, err := csm.selectedTip(stagingArea)
if err != nil {
return 0, nil, err
return 0, err
}
if isResolveTip {
oldSelectedTipUTXOSet, err := csm.restorePastUTXO(stagingArea, oldSelectedTip)
isNewSelectedTip, err := csm.isNewSelectedTip(stagingArea, blockHash, oldSelectedTip)
if err != nil {
return 0, err
}
oldSelectedTipUTXOSet, err := csm.restorePastUTXO(stagingArea, oldSelectedTip)
if err != nil {
return 0, err
}
if isNewSelectedTip {
log.Debugf("Block %s is the new SelectedTip, therefore setting it as old selectedTip's diffChild", blockHash)
oldSelectedTipUTXOSet, err := pastUTXODiff.DiffFrom(oldSelectedTipUTXOSet.ToImmutable())
if err != nil {
return 0, nil, err
}
isNewSelectedTip, err := csm.isNewSelectedTip(stagingArea, blockHash, oldSelectedTip)
if err != nil {
return 0, nil, err
return 0, err
}
csm.stageDiff(stagingArea, oldSelectedTip, oldSelectedTipUTXOSet, blockHash)
if isNewSelectedTip {
log.Debugf("Block %s is the new selected tip, therefore setting it as old selected tip's diffChild", blockHash)
updatedOldSelectedTipUTXOSet, err := pastUTXOSet.DiffFrom(oldSelectedTipUTXOSet)
if err != nil {
return 0, nil, err
}
log.Debugf("Setting the old selected tip's (%s) diffChild to be the new selected tip (%s)",
oldSelectedTip, blockHash)
csm.stageDiff(stagingArea, oldSelectedTip, updatedOldSelectedTipUTXOSet, blockHash)
log.Tracef("Staging the utxoDiff of block %s, with virtual as diffChild", blockHash)
csm.stageDiff(stagingArea, blockHash, pastUTXOSet, nil)
} else {
log.Debugf("Block %s is the tip of currently resolved chain, but not the new selected tip,"+
"therefore setting it's utxoDiffChild to be the current selectedTip %s", blockHash, oldSelectedTip)
utxoDiff, err := oldSelectedTipUTXOSet.DiffFrom(pastUTXOSet)
if err != nil {
return 0, nil, err
}
csm.stageDiff(stagingArea, blockHash, utxoDiff, oldSelectedTip)
}
log.Tracef("Staging the utxoDiff of block %s", blockHash)
csm.stageDiff(stagingArea, blockHash, pastUTXODiff, nil)
} else {
// If the block is not the tip of the currently resolved chain, we set it's diffChild to be the selectedParent,
// this is a temporary measure to ensure there's a restore path to all blocks at all times.
// Later down the process, the diff will be reversed in reverseUTXODiffs.
log.Debugf("Block %s is not the new selected tip, and is not the tip of the currently verified chain, "+
"therefore temporarily setting selectedParent as it's diffChild", blockHash)
utxoDiff, err := selectedParentPastUTXOSet.DiffFrom(pastUTXOSet)
log.Debugf("Block %s is not the new SelectedTip, therefore setting old selectedTip as it's diffChild", blockHash)
pastUTXODiff, err = oldSelectedTipUTXOSet.DiffFrom(pastUTXODiff)
if err != nil {
return 0, nil, err
return 0, err
}
csm.stageDiff(stagingArea, blockHash, utxoDiff, selectedParentHash)
log.Tracef("Staging the utxoDiff of block %s", blockHash)
csm.stageDiff(stagingArea, blockHash, pastUTXODiff, oldSelectedTip)
}
return externalapi.StatusUTXOValid, pastUTXOSet, nil
return externalapi.StatusUTXOValid, nil
}
func (csm *consensusStateManager) isNewSelectedTip(stagingArea *model.StagingArea,

View File

@@ -16,24 +16,25 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestDoubleSpends(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
consensusConfig.BlockCoinbaseMaturity = 0
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestUTXOCommitment")
consensus, teardown, err := factory.NewTestConsensus(params, false, "TestUTXOCommitment")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Mine chain of two blocks to fund our double spend
firstBlockHash, _, err := consensus.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
firstBlockHash, _, err := consensus.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("Error creating firstBlock: %+v", err)
}
@@ -160,19 +161,19 @@ func TestDoubleSpends(t *testing.T) {
// TestTransactionAcceptance checks that blue blocks transactions are favoured above
// red blocks transactions, and that the block reward is paid only for blue blocks.
func TestTransactionAcceptance(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
consensusConfig.BlockCoinbaseMaturity = 0
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
testConsensus, teardown, err := factory.NewTestConsensus(consensusConfig, "TestTransactionAcceptance")
testConsensus, teardown, err := factory.NewTestConsensus(params, false, "TestTransactionAcceptance")
if err != nil {
t.Fatalf("Error setting up testConsensus: %+v", err)
}
defer teardown(false)
fundingBlock1Hash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
fundingBlock1Hash, _, err := testConsensus.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("Error creating fundingBlock1: %+v", err)
}
@@ -191,7 +192,7 @@ func TestTransactionAcceptance(t *testing.T) {
// Add a chain of K blocks above fundingBlock3 so we'll
// be able to mine a red block on top of it.
tipHash := fundingBlock3Hash
for i := model.KType(0); i < consensusConfig.K; i++ {
for i := model.KType(0); i < params.K; i++ {
var err error
tipHash, _, err = testConsensus.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
if err != nil {
@@ -393,16 +394,16 @@ func TestTransactionAcceptance(t *testing.T) {
}
func TestResolveBlockStatusSanity(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
consensus, teardown, err := consensus.NewFactory().NewTestConsensus(consensusConfig, "TestResolveBlockStatusSanity")
consensus, teardown, err := consensus.NewFactory().NewTestConsensus(params, false, "TestResolveBlockStatusSanity")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
genesisHash := consensusConfig.GenesisHash
genesisHash := params.GenesisHash
allHashes := []*externalapi.DomainHash{genesisHash}
// Make sure that the status of genesisHash is valid
@@ -414,7 +415,7 @@ func TestResolveBlockStatusSanity(t *testing.T) {
t.Fatalf("genesis is unexpectedly non-valid. Its status is: %s", genesisStatus)
}
chainLength := int(consensusConfig.K) + 1
chainLength := int(params.K) + 1
// Add a chain of blocks over the genesis and make sure all their
// statuses are valid

View File

@@ -1,94 +0,0 @@
package consensusstatemanager
import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/kaspanet/kaspad/util/staging"
)
func (csm *consensusStateManager) ReverseUTXODiffs(tipHash *externalapi.DomainHash,
reversalData *model.UTXODiffReversalData) error {
// During the process of resolving a chain of blocks, we temporarily set all blocks' (except the tip)
// UTXODiffChild to be the selected parent.
// Once the process is complete, we can reverse said chain, to now go directly to virtual through the relevant tip
onEnd := logger.LogAndMeasureExecutionTime(log, "reverseUTXODiffs")
defer onEnd()
readStagingArea := model.NewStagingArea()
log.Debugf("Reversing utxoDiffs")
// Set previousUTXODiff and previousBlock to tip.SelectedParent before we start touching them,
// since previousBlock's UTXODiff is going to be over-written in the next step
previousBlock := reversalData.SelectedParentHash
previousUTXODiff, err := csm.utxoDiffStore.UTXODiff(csm.databaseContext, readStagingArea, previousBlock)
if err != nil {
return err
}
// tip.selectedParent is special in the sense that we don't have it's diff available in reverse, however,
// we were able to calculate it when the tip's and tip.selectedParent's UTXOSets were known during resolveBlockStatus.
// Therefore - we treat it separately
err = csm.commitUTXODiffInSeparateStagingArea(previousBlock, reversalData.SelectedParentUTXODiff, tipHash)
if err != nil {
return err
}
log.Trace("Reversed 1 utxoDiff")
previousBlockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, readStagingArea, previousBlock)
if err != nil {
return err
}
// Now go over the rest of the blocks and assign for every block Bi.UTXODiff = Bi+1.UTXODiff.Reversed()
for i := 1; ; i++ {
currentBlock := previousBlockGHOSTDAGData.SelectedParent()
currentBlockUTXODiffChild, err := csm.utxoDiffStore.UTXODiffChild(csm.databaseContext, readStagingArea, currentBlock)
if err != nil {
return err
}
currentBlockGHOSTDAGData, err := csm.ghostdagDataStore.Get(csm.databaseContext, readStagingArea, currentBlock)
if err != nil {
return err
}
// We stop reversing when current's UTXODiffChild is not current's SelectedParent
if !currentBlockGHOSTDAGData.SelectedParent().Equal(currentBlockUTXODiffChild) {
log.Debugf("Block %s's UTXODiffChild is not it's selected parent - finish reversing", currentBlock)
break
}
currentUTXODiff := previousUTXODiff.Reversed()
// retrieve current utxoDiff for Bi, to be used by next block
previousUTXODiff, err = csm.utxoDiffStore.UTXODiff(csm.databaseContext, readStagingArea, currentBlock)
if err != nil {
return err
}
err = csm.commitUTXODiffInSeparateStagingArea(currentBlock, currentUTXODiff, previousBlock)
if err != nil {
return err
}
previousBlock = currentBlock
previousBlockGHOSTDAGData = currentBlockGHOSTDAGData
log.Tracef("Reversed %d utxoDiffs", i)
}
return nil
}
func (csm *consensusStateManager) commitUTXODiffInSeparateStagingArea(
blockHash *externalapi.DomainHash, utxoDiff externalapi.UTXODiff, utxoDiffChild *externalapi.DomainHash) error {
stagingAreaForCurrentBlock := model.NewStagingArea()
csm.utxoDiffStore.Stage(stagingAreaForCurrentBlock, blockHash, utxoDiff, utxoDiffChild)
return staging.CommitAllChanges(csm.databaseContext, stagingAreaForCurrentBlock)
}

View File

@@ -1,115 +0,0 @@
package consensusstatemanager_test
import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
)
func TestReverseUTXODiffs(t *testing.T) {
// This test doesn't check ReverseUTXODiffs directly, since that would be quite complicated,
// instead, it creates a situation where a reversal would defenitely happen - a reorg of 5 blocks,
// then verifies that the resulting utxo-diffs and utxo-diff-children are all correct.
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestUTXOCommitment")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// Create a chain of 5 blocks
const initialChainLength = 5
previousBlockHash := consensusConfig.GenesisHash
for i := 0; i < initialChainLength; i++ {
previousBlockHash, _, err = tc.AddBlock([]*externalapi.DomainHash{previousBlockHash}, nil, nil)
if err != nil {
t.Fatalf("Error mining block no. %d in initial chain: %+v", i, err)
}
}
// Mine a chain of 6 blocks, to re-organize the DAG
const reorgChainLength = initialChainLength + 1
reorgChain := make([]*externalapi.DomainHash, reorgChainLength)
previousBlockHash = consensusConfig.GenesisHash
for i := 0; i < reorgChainLength; i++ {
previousBlockHash, _, err = tc.AddBlock([]*externalapi.DomainHash{previousBlockHash}, nil, nil)
reorgChain[i] = previousBlockHash
if err != nil {
t.Fatalf("Error mining block no. %d in re-org chain: %+v", i, err)
}
}
stagingArea := model.NewStagingArea()
// Check that every block in the reorg chain has the next block as it's UTXODiffChild,
// except that tip that has virtual, And that the diff is only `{ toRemove: { coinbase } }`
for i, currentBlockHash := range reorgChain {
if i == reorgChainLength-1 {
hasUTXODiffChild, err := tc.UTXODiffStore().HasUTXODiffChild(tc.DatabaseContext(), stagingArea, currentBlockHash)
if err != nil {
t.Fatalf("Error getting HasUTXODiffChild of %s: %+v", currentBlockHash, err)
}
if hasUTXODiffChild {
t.Errorf("Block %s expected utxoDiffChild is virtual, but HasUTXODiffChild returned true",
currentBlockHash)
}
} else {
utxoDiffChild, err := tc.UTXODiffStore().UTXODiffChild(tc.DatabaseContext(), stagingArea, currentBlockHash)
if err != nil {
t.Fatalf("Error getting utxoDiffChild of block No. %d, %s: %+v", i, currentBlockHash, err)
}
expectedUTXODiffChild := reorgChain[i+1]
if !expectedUTXODiffChild.Equal(utxoDiffChild) {
t.Errorf("Block %s expected utxoDiffChild is %s, but got %s instead",
currentBlockHash, expectedUTXODiffChild, utxoDiffChild)
continue
}
}
// skip the first block, since it's coinbase doesn't create outputs
if i == 0 {
continue
}
currentBlock, err := tc.BlockStore().Block(tc.DatabaseContext(), stagingArea, currentBlockHash)
if err != nil {
t.Fatalf("Error getting block %s: %+v", currentBlockHash, err)
}
utxoDiff, err := tc.UTXODiffStore().UTXODiff(tc.DatabaseContext(), stagingArea, currentBlockHash)
if err != nil {
t.Fatalf("Error getting utxoDiffChild of %s: %+v", currentBlockHash, err)
}
if !checkIsUTXODiffOnlyRemoveCoinbase(t, utxoDiff, currentBlock) {
t.Errorf("Expected %s to only have toRemove: {%s}, but got %s instead",
currentBlockHash, consensushashing.TransactionID(currentBlock.Transactions[0]), utxoDiff)
}
}
})
}
func checkIsUTXODiffOnlyRemoveCoinbase(t *testing.T, utxoDiff externalapi.UTXODiff, currentBlock *externalapi.DomainBlock) bool {
if utxoDiff.ToAdd().Len() > 0 || utxoDiff.ToRemove().Len() > 1 {
return false
}
iterator := utxoDiff.ToRemove().Iterator()
iterator.First()
outpoint, _, err := iterator.Get()
if err != nil {
t.Fatalf("Error getting from UTXODiff's iterator: %+v", err)
}
if !outpoint.TransactionID.Equal(consensushashing.TransactionID(currentBlock.Transactions[0])) {
return false
}
return true
}

View File

@@ -22,8 +22,7 @@ func (csm *testConsensusStateManager) AddUTXOToMultiset(
}
func (csm *testConsensusStateManager) ResolveBlockStatus(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash,
useSeparateStagingAreaPerBlock bool) (externalapi.BlockStatus, error) {
useSeparateStagingAreasPerBlock bool) (externalapi.BlockStatus, error) {
status, _, err := csm.resolveBlockStatus(stagingArea, blockHash, useSeparateStagingAreaPerBlock)
return status, err
return csm.resolveBlockStatus(stagingArea, blockHash, useSeparateStagingAreasPerBlock)
}

View File

@@ -10,13 +10,14 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestConsensusStateManager_pickVirtualParents(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
tc, teardown, err := consensus.NewFactory().NewTestConsensus(consensusConfig, "TestConsensusStateManager_pickVirtualParents")
tc, teardown, err := consensus.NewFactory().NewTestConsensus(params, false, "TestConsensusStateManager_pickVirtualParents")
if err != nil {
t.Fatalf("Error setting up tc: %+v", err)
}
@@ -41,14 +42,14 @@ func TestConsensusStateManager_pickVirtualParents(t *testing.T) {
return virtualRelations.Parents
}
// We build 2*consensusConfig.MaxBlockParents each one with blueWork higher than the other.
parents := make([]*externalapi.DomainHash, 0, consensusConfig.MaxBlockParents)
for i := 0; i < 2*int(consensusConfig.MaxBlockParents); i++ {
lastBlock := consensusConfig.GenesisHash
// We build 2*params.MaxBlockParents each one with blueWork higher than the other.
parents := make([]*externalapi.DomainHash, 0, params.MaxBlockParents)
for i := 0; i < 2*int(params.MaxBlockParents); i++ {
lastBlock := params.GenesisHash
for j := 0; j <= i; j++ {
lastBlock, _, err = tc.AddBlock([]*externalapi.DomainHash{lastBlock}, nil, nil)
if err != nil {
t.Fatalf("Failed Adding block to tc: %+v", err)
t.Fatalf("Failed Adding block to tc: %v", err)
}
}
parents = append(parents, lastBlock)
@@ -59,15 +60,15 @@ func TestConsensusStateManager_pickVirtualParents(t *testing.T) {
// Make sure the first half of the blocks are with highest blueWork
// we use (max+1)/2 because the first "half" is rounded up, so `(dividend + (divisor - 1)) / divisor` = `(max + (2-1))/2` = `(max+1)/2`
for i := 0; i < int(consensusConfig.MaxBlockParents+1)/2; i++ {
for i := 0; i < int(params.MaxBlockParents+1)/2; i++ {
if !virtualParents[i].Equal(parents[i]) {
t.Fatalf("Expected block at %d to be equal, instead found %s != %s", i, virtualParents[i], parents[i])
}
}
// Make sure the second half is the candidates with lowest blueWork
end := len(parents) - int(consensusConfig.MaxBlockParents)/2
for i := (consensusConfig.MaxBlockParents + 1) / 2; i < consensusConfig.MaxBlockParents; i++ {
end := len(parents) - int(params.MaxBlockParents)/2
for i := (params.MaxBlockParents + 1) / 2; i < params.MaxBlockParents; i++ {
if !virtualParents[i].Equal(parents[end]) {
t.Fatalf("Expected block at %d to be equal, instead found %s != %s", i, virtualParents[i], parents[end])
}
@@ -93,12 +94,12 @@ func TestConsensusStateManager_pickVirtualParents(t *testing.T) {
break
}
}
// build exactly consensusConfig.MaxBlockParents
parents = make([]*externalapi.DomainHash, 0, consensusConfig.MaxBlockParents)
for i := 0; i < int(consensusConfig.MaxBlockParents); i++ {
// build exactly params.MaxBlockParents
parents = make([]*externalapi.DomainHash, 0, params.MaxBlockParents)
for i := 0; i < int(params.MaxBlockParents); i++ {
block, _, err := tc.AddBlock([]*externalapi.DomainHash{virtualSelectedParent}, nil, nil)
if err != nil {
t.Fatalf("Failed Adding block to tc: %+v", err)
t.Fatalf("Failed Adding block to tc: %v", err)
}
parents = append(parents, block)
}

View File

@@ -8,12 +8,13 @@ import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestIsAncestorOf(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestIsAncestorOf")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestIsAncestorOf")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
@@ -21,7 +22,7 @@ func TestIsAncestorOf(t *testing.T) {
// Add a chain of two blocks above the genesis. This will be the
// selected parent chain.
blockA, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
blockA, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -32,7 +33,7 @@ func TestIsAncestorOf(t *testing.T) {
}
// Add another block above the genesis
blockC, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
blockC, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %s", err)
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
const commonChainSize = 5
@@ -16,18 +17,18 @@ const depth uint64 = 2
//TestBlockAtDepthOnChainDag compares the result of BlockAtDepth to the result of looping over the SelectedChain on a single chain DAG.
func TestBlockAtDepthOnChainDag(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestBlockAtDepthOnChainDag")
if err != nil {
t.Fatalf("Failed creating a NewTestConsensus: %s", err)
}
defer tearDown(false)
highHash, err := createAChainDAG(consensusConfig.GenesisHash, tc)
highHash, err := createAChainDAG(params.GenesisHash, tc)
if err != nil {
t.Fatalf("Failed creating a Chain DAG In BlockAtDepthTEST: %+v", err)
}
@@ -73,9 +74,9 @@ func createAChainDAG(genesisHash *externalapi.DomainHash, tc testapi.TestConsens
// TestBlockAtDepthOnDAGWhereTwoBlocksHaveSameSelectedParent compares the results of BlockAtDepth
// of 2 children that have the same selectedParent.
func TestBlockAtDepthOnDAGWhereTwoBlocksHaveSameSelectedParent(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestBlockAtDepthOnDAGWhereTwoBlocksHaveSameSelectedParent")
if err != nil {
t.Fatalf("Failed creating a NewTestConsensus: %s", err)
@@ -84,7 +85,7 @@ func TestBlockAtDepthOnDAGWhereTwoBlocksHaveSameSelectedParent(t *testing.T) {
stagingArea := model.NewStagingArea()
firstChild, secondChild, err := createADAGTwoChildrenWithSameSelectedParent(consensusConfig.GenesisHash, tc)
firstChild, secondChild, err := createADAGTwoChildrenWithSameSelectedParent(params.GenesisHash, tc)
if err != nil {
t.Fatalf("Failed creating a DAG where two blocks have same selected parent: %+v", err)
}
@@ -127,9 +128,9 @@ func createADAGTwoChildrenWithSameSelectedParent(genesisHash *externalapi.Domain
// TestBlockAtDepthOnDAGWithTwoDifferentChains compares results of BlockAtDepth on two different chains,
// on the same DAG, and validates they merge at the correct point.
func TestBlockAtDepthOnDAGWithTwoDifferentChains(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestBlockAtDepthOnDAGWithTwoDifferentChains")
if err != nil {
t.Fatalf("Failed creating a NewTestConsensus: %s", err)
@@ -139,7 +140,7 @@ func TestBlockAtDepthOnDAGWithTwoDifferentChains(t *testing.T) {
const sizeOfTheFirstChildSubChainDAG = 3
const sizeOfTheSecondChildSubChainDAG = 2
firstChild, secondChild, err := createADAGWithTwoDifferentChains(consensusConfig.GenesisHash, tc, sizeOfTheFirstChildSubChainDAG,
firstChild, secondChild, err := createADAGWithTwoDifferentChains(params.GenesisHash, tc, sizeOfTheFirstChildSubChainDAG,
sizeOfTheSecondChildSubChainDAG)
if err != nil {
t.Fatalf("Failed creating a DAG with two different chains in BlockAtDepthTEST: %+v", err)
@@ -206,10 +207,10 @@ func createADAGWithTwoDifferentChains(genesisHash *externalapi.DomainHash, tc te
}
func TestLowestChainBlockAboveOrEqualToBlueScore(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.FinalityDuration = 10 * consensusConfig.TargetTimePerBlock
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.FinalityDuration = 10 * params.TargetTimePerBlock
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestLowestChainBlockAboveOrEqualToBlueScore")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
@@ -240,8 +241,8 @@ func TestLowestChainBlockAboveOrEqualToBlueScore(t *testing.T) {
}
}
chain := []*externalapi.DomainHash{consensusConfig.GenesisHash}
tipHash := consensusConfig.GenesisHash
chain := []*externalapi.DomainHash{params.GenesisHash}
tipHash := params.GenesisHash
for i := 0; i < 9; i++ {
var err error
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
@@ -252,7 +253,7 @@ func TestLowestChainBlockAboveOrEqualToBlueScore(t *testing.T) {
chain = append(chain, tipHash)
}
sideChain1TipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
sideChain1TipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -276,7 +277,7 @@ func TestLowestChainBlockAboveOrEqualToBlueScore(t *testing.T) {
chain = append(chain, tipHash)
}
sideChain2TipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
sideChain2TipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -301,7 +302,7 @@ func TestLowestChainBlockAboveOrEqualToBlueScore(t *testing.T) {
}
// Check by exact blue score
checkExpectedBlock(tipHash, 0, consensusConfig.GenesisHash)
checkExpectedBlock(tipHash, 0, params.GenesisHash)
checkExpectedBlock(tipHash, 5, chain[5])
checkExpectedBlock(tipHash, 19, chain[len(chain)-3])

View File

@@ -132,37 +132,37 @@ func TestBlockWindow(t *testing.T) {
{
parents: []string{"H", "F"},
id: "I",
expectedWindow: []string{"F", "D", "C", "H", "G", "B"},
expectedWindow: []string{"F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"I"},
id: "J",
expectedWindow: []string{"I", "F", "D", "C", "H", "G", "B"},
expectedWindow: []string{"I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"J"},
id: "K",
expectedWindow: []string{"J", "I", "F", "D", "C", "H", "G", "B"},
expectedWindow: []string{"J", "I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"K"},
id: "L",
expectedWindow: []string{"K", "J", "I", "F", "D", "C", "H", "G", "B"},
expectedWindow: []string{"K", "J", "I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"L"},
id: "M",
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "C", "H", "G", "B"},
expectedWindow: []string{"L", "K", "J", "I", "F", "D", "H", "C", "G", "B"},
},
{
parents: []string{"M"},
id: "N",
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "C", "H", "G"},
expectedWindow: []string{"M", "L", "K", "J", "I", "F", "D", "H", "C", "G"},
},
{
parents: []string{"N"},
id: "O",
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "C", "H"},
expectedWindow: []string{"N", "M", "L", "K", "J", "I", "F", "D", "H", "C"},
},
},
dagconfig.DevnetParams.Name: {
@@ -310,10 +310,10 @@ func TestBlockWindow(t *testing.T) {
},
},
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.K = 1
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.K = 1
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestBlockWindow")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestBlockWindow")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
@@ -322,10 +322,10 @@ func TestBlockWindow(t *testing.T) {
windowSize := 10
blockByIDMap := make(map[string]*externalapi.DomainHash)
idByBlockMap := make(map[externalapi.DomainHash]string)
blockByIDMap["A"] = consensusConfig.GenesisHash
idByBlockMap[*consensusConfig.GenesisHash] = "A"
blockByIDMap["A"] = params.GenesisHash
idByBlockMap[*params.GenesisHash] = "A"
blocksData := tests[consensusConfig.Name]
blocksData := tests[params.Name]
for _, blockData := range blocksData {
parents := hashset.New()

View File

@@ -18,23 +18,23 @@ import (
)
func TestDifficulty(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
if consensusConfig.DisableDifficultyAdjustment {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
if params.DisableDifficultyAdjustment {
return
}
// This test generates 3066 blocks above genesis with at least 1 second between each block, amounting to
// a bit less then an hour of timestamps.
// To prevent rejected blocks due to timestamps in the future, the following safeguard makes sure
// the genesis block is at least 1 hour in the past.
if consensusConfig.GenesisBlock.Header.TimeInMilliseconds() > mstime.ToMSTime(time.Now().Add(-time.Hour)).UnixMilliseconds() {
if params.GenesisBlock.Header.TimeInMilliseconds() > mstime.ToMSTime(time.Now().Add(-time.Hour)).UnixMilliseconds() {
t.Fatalf("TestDifficulty requires the GenesisBlock to be at least 1 hour old to pass")
}
consensusConfig.K = 1
consensusConfig.DifficultyAdjustmentWindowSize = 264
params.K = 1
params.DifficultyAdjustmentWindowSize = 264
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestDifficulty")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestDifficulty")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -54,7 +54,7 @@ func TestDifficulty(t *testing.T) {
t.Fatalf("BlockHeader: %+v", err)
}
blockTime = header.TimeInMilliseconds() + consensusConfig.TargetTimePerBlock.Milliseconds()
blockTime = header.TimeInMilliseconds() + params.TargetTimePerBlock.Milliseconds()
}
block, _, err := tc.BuildBlockWithParents(parents, nil, nil)
@@ -99,18 +99,18 @@ func TestDifficulty(t *testing.T) {
return addBlock(minTime, parents...)
}
tipHash := consensusConfig.GenesisHash
tip := consensusConfig.GenesisBlock
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize; i++ {
tipHash := params.GenesisHash
tip := params.GenesisBlock
for i := 0; i < params.DifficultyAdjustmentWindowSize; i++ {
tip, tipHash = addBlock(0, tipHash)
if tip.Header.Bits() != consensusConfig.GenesisBlock.Header.Bits() {
if tip.Header.Bits() != params.GenesisBlock.Header.Bits() {
t.Fatalf("As long as the block blue score is less then the difficulty adjustment " +
"window size, the difficulty should be the same as genesis'")
}
}
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize+100; i++ {
for i := 0; i < params.DifficultyAdjustmentWindowSize+100; i++ {
tip, tipHash = addBlock(0, tipHash)
if tip.Header.Bits() != consensusConfig.GenesisBlock.Header.Bits() {
if tip.Header.Bits() != params.GenesisBlock.Header.Bits() {
t.Fatalf("As long as the block rate remains the same, the difficulty shouldn't change")
}
}
@@ -128,7 +128,7 @@ func TestDifficulty(t *testing.T) {
}
var expectedBits uint32
switch consensusConfig.Name {
switch params.Name {
case dagconfig.TestnetParams.Name, dagconfig.DevnetParams.Name:
expectedBits = uint32(0x1e7f83df)
case dagconfig.MainnetParams.Name:
@@ -140,7 +140,7 @@ func TestDifficulty(t *testing.T) {
}
// Increase block rate to increase difficulty
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize; i++ {
for i := 0; i < params.DifficultyAdjustmentWindowSize; i++ {
tip, tipHash = addBlockWithMinimumTime(tipHash)
tipGHOSTDAGData, err := tc.GHOSTDAGDataStore().Get(tc.DatabaseContext(), stagingArea, tipHash)
if err != nil {
@@ -161,7 +161,7 @@ func TestDifficulty(t *testing.T) {
// Add blocks until difficulty stabilizes
lastBits := tip.Header.Bits()
sameBitsCount := 0
for sameBitsCount < consensusConfig.DifficultyAdjustmentWindowSize+1 {
for sameBitsCount < params.DifficultyAdjustmentWindowSize+1 {
tip, tipHash = addBlock(0, tipHash)
if tip.Header.Bits() == lastBits {
sameBitsCount++
@@ -171,7 +171,7 @@ func TestDifficulty(t *testing.T) {
}
}
slowBlockTime := tip.Header.TimeInMilliseconds() + consensusConfig.TargetTimePerBlock.Milliseconds() + 1000
slowBlockTime := tip.Header.TimeInMilliseconds() + params.TargetTimePerBlock.Milliseconds() + 1000
slowBlock, tipHash := addBlock(slowBlockTime, tipHash)
if slowBlock.Header.Bits() != tip.Header.Bits() {
t.Fatalf("The difficulty should only change when slowBlock is in the past of a block")
@@ -192,7 +192,7 @@ func TestDifficulty(t *testing.T) {
// blocks in its past and one without.
splitBlockHash := tipHash
blueTipHash := splitBlockHash
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize; i++ {
for i := 0; i < params.DifficultyAdjustmentWindowSize; i++ {
_, blueTipHash = addBlock(0, blueTipHash)
}
@@ -212,7 +212,7 @@ func TestDifficulty(t *testing.T) {
// out the red blocks from the window, and check that the red blocks don't
// affect the difficulty.
blueTipHash = splitBlockHash
for i := 0; i < consensusConfig.DifficultyAdjustmentWindowSize+redChainLength+1; i++ {
for i := 0; i < params.DifficultyAdjustmentWindowSize+redChainLength+1; i++ {
_, blueTipHash = addBlock(0, blueTipHash)
}
@@ -230,24 +230,24 @@ func TestDifficulty(t *testing.T) {
}
func TestDAAScore(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.DifficultyAdjustmentWindowSize = 264
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.DifficultyAdjustmentWindowSize = 264
stagingArea := model.NewStagingArea()
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestDifficulty")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestDifficulty")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
// We create a small DAG in order to skip from block with blue score of 1 directly to 3
split1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
split1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
block, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
block, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -287,7 +287,7 @@ func TestDAAScore(t *testing.T) {
split2Hash := tipHash
split2DAAScore := tipDAAScore
for i := uint64(0); i < uint64(consensusConfig.DifficultyAdjustmentWindowSize)-1; i++ {
for i := uint64(0); i < uint64(params.DifficultyAdjustmentWindowSize)-1; i++ {
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
@@ -309,7 +309,7 @@ func TestDAAScore(t *testing.T) {
t.Fatalf("AddBlock: %+v", err)
}
// This block is in the anticone of consensusConfig.DifficultyAdjustmentWindowSize-1 blocks, so it must be part
// This block is in the anticone of params.DifficultyAdjustmentWindowSize-1 blocks, so it must be part
// of the DAA window of a merging block
blockAboveSplit2, _, err := tc.AddBlock([]*externalapi.DomainHash{split2Hash}, nil, nil)
if err != nil {

View File

@@ -1,9 +1,8 @@
package ghostdag2
import (
"sort"
"github.com/kaspanet/kaspad/util/difficulty"
"sort"
"math/big"
@@ -19,7 +18,7 @@ type ghostdagHelper struct {
headerStore model.BlockHeaderStore
}
// New creates a new instance of this alternative ghostdag impl
// New creates a new instance of this alternative GHOSTDAG impl
func New(
databaseContext model.DBReader,
dagTopologyManager model.DAGTopologyManager,
@@ -36,53 +35,60 @@ func New(
}
}
/* --------------------------------------------- */
func (gh *ghostdagHelper) GHOSTDAG(stagingArea *model.StagingArea, blockCandidate *externalapi.DomainHash) error {
myWork := new(big.Int)
maxWork := new(big.Int)
var myScore uint64
var spScore uint64
/* find the selectedParent */
blockParents, err := gh.dagTopologyManager.Parents(stagingArea, blockCandidate)
var blueScore uint64 = 0
var blueWork = new(big.Int)
blueWork.SetUint64(0)
var selectedParent *externalapi.DomainHash = nil
var mergeSetBlues = make([]*externalapi.DomainHash, 0)
var mergeSetReds = make([]*externalapi.DomainHash, 0)
parents, err := gh.dagTopologyManager.Parents(stagingArea, blockCandidate)
if err != nil {
return err
}
var selectedParent = blockParents[0]
for _, parent := range blockParents {
blockData, err := gh.dataStore.Get(gh.dbAccess, stagingArea, parent)
// If genesis:
if len(parents) == 0 {
blockGHOSTDAGData := model.NewBlockGHOSTDAGData(blueScore, blueWork, selectedParent, mergeSetBlues, mergeSetReds, nil)
gh.dataStore.Stage(stagingArea, blockCandidate, blockGHOSTDAGData)
return nil
}
maxBlueWork := new(big.Int)
maxBlueWork.SetUint64(0)
maxBlueScore := uint64(0)
selectedParent = parents[0]
// Find the selected parent.
for _, parent := range parents {
parentBlockData, err := gh.dataStore.Get(gh.dbAccess, stagingArea, parent)
if err != nil {
return err
}
blockWork := blockData.BlueWork()
blockScore := blockData.BlueScore()
if blockWork.Cmp(maxWork) == 1 {
parentBlueWork := parentBlockData.BlueWork()
switch parentBlueWork.Cmp(maxBlueWork) {
case 0:
if isMoreHash(parent, selectedParent) {
selectedParent = parent
maxBlueWork = parentBlueWork
maxBlueScore = parentBlockData.BlueScore()
}
case 1:
selectedParent = parent
maxWork = blockWork
spScore = blockScore
}
if blockWork.Cmp(maxWork) == 0 && ismoreHash(parent, selectedParent) {
selectedParent = parent
maxWork = blockWork
spScore = blockScore
maxBlueWork = parentBlueWork
maxBlueScore = parentBlockData.BlueScore()
}
}
myWork.Set(maxWork)
myScore = spScore
/* Goal: iterate blockCandidate's mergeSet and divide it to : blue, blues, reds. */
var mergeSetBlues = make([]*externalapi.DomainHash, 0)
var mergeSetReds = make([]*externalapi.DomainHash, 0)
var blueSet = make([]*externalapi.DomainHash, 0)
blueWork.Set(maxBlueWork)
blueScore = maxBlueScore
blueSet := make([]*externalapi.DomainHash, 0)
blueSet = append(blueSet, selectedParent)
mergeSetBlues = append(mergeSetBlues, selectedParent)
mergeSetArr, err := gh.findMergeSet(stagingArea, blockParents, selectedParent)
mergeSet, err := gh.findMergeSet(stagingArea, parents, selectedParent)
if err != nil {
return err
}
err = gh.sortByBlueWork(stagingArea, mergeSetArr)
err = gh.sortByBlueWork(stagingArea, mergeSet)
if err != nil {
return err
}
@@ -90,41 +96,36 @@ func (gh *ghostdagHelper) GHOSTDAG(stagingArea *model.StagingArea, blockCandidat
if err != nil {
return err
}
for _, mergeSetBlock := range mergeSetArr {
// Iterate on mergeSet and divide it to mergeSetBlues and mergeSetReds.
for _, mergeSetBlock := range mergeSet {
if mergeSetBlock.Equal(selectedParent) {
if !contains(selectedParent, mergeSetBlues) {
mergeSetBlues = append(mergeSetBlues, selectedParent)
blueSet = append(blueSet, selectedParent)
}
continue
}
err := gh.divideBlueRed(stagingArea, selectedParent, mergeSetBlock, &mergeSetBlues, &mergeSetReds, &blueSet)
err := gh.divideToBlueAndRed(stagingArea, mergeSetBlock, &mergeSetBlues, &mergeSetReds, &blueSet)
if err != nil {
return err
}
}
myScore += uint64(len(mergeSetBlues))
blueScore += uint64(len(mergeSetBlues))
// We add up all the *work*(not blueWork) that all our blues and selected parent did
// Calculation of blue work
for _, blue := range mergeSetBlues {
header, err := gh.headerStore.BlockHeader(gh.dbAccess, stagingArea, blue)
if err != nil {
return err
}
myWork.Add(myWork, difficulty.CalcWork(header.Bits()))
blueWork.Add(blueWork, difficulty.CalcWork(header.Bits()))
}
e := model.NewBlockGHOSTDAGData(myScore, myWork, selectedParent, mergeSetBlues, mergeSetReds, nil)
gh.dataStore.Stage(stagingArea, blockCandidate, e)
blockGHOSTDAGData := model.NewBlockGHOSTDAGData(blueScore, blueWork, selectedParent, mergeSetBlues, mergeSetReds, nil)
gh.dataStore.Stage(stagingArea, blockCandidate, blockGHOSTDAGData)
return nil
}
/* --------isMoreHash(w, selectedParent)----------------*/
func ismoreHash(parent *externalapi.DomainHash, selectedParent *externalapi.DomainHash) bool {
func isMoreHash(parent *externalapi.DomainHash, selectedParent *externalapi.DomainHash) bool {
parentByteArray := parent.ByteArray()
selectedParentByteArray := selectedParent.ByteArray()
//Check if parentHash is more then selectedParentHash
for i := 0; i < len(parentByteArray); i++ {
switch {
case parentByteArray[i] < selectedParentByteArray[i]:
@@ -136,46 +137,39 @@ func ismoreHash(parent *externalapi.DomainHash, selectedParent *externalapi.Doma
return false
}
/* 1. blue = selectedParent.blue + blues
2. not connected to at most K blocks (from the blue group)
3. for each block at blue , check if not destroy
*/
/* ---------------divideBluesReds--------------------- */
func (gh *ghostdagHelper) divideBlueRed(stagingArea *model.StagingArea,
selectedParent *externalapi.DomainHash, desiredBlock *externalapi.DomainHash,
func (gh *ghostdagHelper) divideToBlueAndRed(stagingArea *model.StagingArea, blockToCheck *externalapi.DomainHash,
blues *[]*externalapi.DomainHash, reds *[]*externalapi.DomainHash, blueSet *[]*externalapi.DomainHash) error {
var k = int(gh.k)
counter := 0
var suspectsBlues = make([]*externalapi.DomainHash, 0)
anticoneBlocksCounter := 0
anticoneBlues := make([]*externalapi.DomainHash, 0)
isMergeBlue := true
//check that not-connected to at most k.
for _, block := range *blueSet {
isAnticone, err := gh.isAnticone(stagingArea, block, desiredBlock)
for _, blueblock := range *blueSet {
isAnticone, err := gh.isAnticone(stagingArea, blueblock, blockToCheck)
if err != nil {
return err
}
if isAnticone {
counter++
suspectsBlues = append(suspectsBlues, block)
anticoneBlocksCounter++
anticoneBlues = append(anticoneBlues, blueblock)
}
if counter > k {
if anticoneBlocksCounter > k {
isMergeBlue = false
break
}
}
if !isMergeBlue {
if !contains(desiredBlock, *reds) {
*reds = append(*reds, desiredBlock)
if !contains(blockToCheck, *reds) {
*reds = append(*reds, blockToCheck)
}
return nil
}
// check that the k-cluster of each blue is still valid.
for _, blue := range suspectsBlues {
isDestroyed, err := gh.checkIfDestroy(stagingArea, blue, blueSet)
// check that the k-cluster of each anticone blue block is still valid.
for _, blueBlock := range anticoneBlues {
isDestroyed, err := gh.checkIfDestroy(stagingArea, blueBlock, blueSet)
if err != nil {
return err
}
@@ -185,39 +179,37 @@ func (gh *ghostdagHelper) divideBlueRed(stagingArea *model.StagingArea,
}
}
if !isMergeBlue {
if !contains(desiredBlock, *reds) {
*reds = append(*reds, desiredBlock)
if !contains(blockToCheck, *reds) {
*reds = append(*reds, blockToCheck)
}
return nil
}
if !contains(desiredBlock, *blues) {
*blues = append(*blues, desiredBlock)
if !contains(blockToCheck, *blues) {
*blues = append(*blues, blockToCheck)
}
if !contains(desiredBlock, *blueSet) {
*blueSet = append(*blueSet, desiredBlock)
if !contains(blockToCheck, *blueSet) {
*blueSet = append(*blueSet, blockToCheck)
}
return nil
}
/* ---------------isAnticone-------------------------- */
func (gh *ghostdagHelper) isAnticone(stagingArea *model.StagingArea, blockA, blockB *externalapi.DomainHash) (bool, error) {
isAAncestorOfAB, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, blockA, blockB)
isBlockAAncestorOfBlockB, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, blockA, blockB)
if err != nil {
return false, err
}
isBAncestorOfA, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, blockB, blockA)
isBlockBAncestorOfBlockA, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, blockB, blockA)
if err != nil {
return false, err
}
return !isAAncestorOfAB && !isBAncestorOfA, nil
return !isBlockAAncestorOfBlockB && !isBlockBAncestorOfBlockA, nil
}
/* ----------------validateKCluster------------------- */
func (gh *ghostdagHelper) validateKCluster(stagingArea *model.StagingArea, chain *externalapi.DomainHash,
checkedBlock *externalapi.DomainHash, counter *int, blueSet *[]*externalapi.DomainHash) (bool, error) {
func (gh *ghostdagHelper) validateKCluster(stagingArea *model.StagingArea, chain *externalapi.DomainHash, checkedBlock *externalapi.DomainHash,
counter *int, blueSet *[]*externalapi.DomainHash) (bool, error) {
var k = int(gh.k)
k := int(gh.k)
isAnticone, err := gh.isAnticone(stagingArea, chain, checkedBlock)
if err != nil {
return false, err
@@ -236,6 +228,7 @@ func (gh *ghostdagHelper) validateKCluster(stagingArea *model.StagingArea, chain
*counter++
return true, nil
}
isAncestorOf, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, checkedBlock, chain)
if err != nil {
return false, err
@@ -251,27 +244,24 @@ func (gh *ghostdagHelper) validateKCluster(stagingArea *model.StagingArea, chain
} else {
return true, nil
}
return false, nil
}
/*----------------contains-------------------------- */
func contains(item *externalapi.DomainHash, items []*externalapi.DomainHash) bool {
for _, r := range items {
if r.Equal(item) {
func contains(desiredItem *externalapi.DomainHash, items []*externalapi.DomainHash) bool {
for _, item := range items {
if item.Equal(desiredItem) {
return true
}
}
return false
}
/* ----------------checkIfDestroy------------------- */
/* find number of not-connected in his blue*/
// find number of not-connected in blueSet
func (gh *ghostdagHelper) checkIfDestroy(stagingArea *model.StagingArea, blockBlue *externalapi.DomainHash,
blueSet *[]*externalapi.DomainHash) (bool, error) {
// Goal: check that the K-cluster of each block in the blueSet is not destroyed when adding the block to the mergeSet.
var k = int(gh.k)
// check that the K-cluster of each block in the blueSet is not destroyed when adding the block to the mergeSet.
k := int(gh.k)
counter := 0
for _, blue := range *blueSet {
isAnticone, err := gh.isAnticone(stagingArea, blue, blockBlue)
@@ -288,51 +278,45 @@ func (gh *ghostdagHelper) checkIfDestroy(stagingArea *model.StagingArea, blockBl
return false, nil
}
/* ----------------findMergeSet------------------- */
func (gh *ghostdagHelper) findMergeSet(stagingArea *model.StagingArea, parents []*externalapi.DomainHash,
selectedParent *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
allMergeSet := make([]*externalapi.DomainHash, 0)
blockQueue := make([]*externalapi.DomainHash, 0)
mergeSet := make([]*externalapi.DomainHash, 0)
blocksQueue := make([]*externalapi.DomainHash, 0)
for _, parent := range parents {
if !contains(parent, blockQueue) {
blockQueue = append(blockQueue, parent)
if !contains(parent, blocksQueue) {
blocksQueue = append(blocksQueue, parent)
}
}
for len(blockQueue) > 0 {
block := blockQueue[0]
blockQueue = blockQueue[1:]
for len(blocksQueue) > 0 {
block := blocksQueue[0]
blocksQueue = blocksQueue[1:]
if selectedParent.Equal(block) {
if !contains(block, allMergeSet) {
allMergeSet = append(allMergeSet, block)
if !contains(block, mergeSet) {
mergeSet = append(mergeSet, block)
}
continue
}
isancestorOf, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, block, selectedParent)
isAncestorOf, err := gh.dagTopologyManager.IsAncestorOf(stagingArea, block, selectedParent)
if err != nil {
return nil, err
}
if isancestorOf {
if isAncestorOf {
continue
}
if !contains(block, allMergeSet) {
allMergeSet = append(allMergeSet, block)
if !contains(block, mergeSet) {
mergeSet = append(mergeSet, block)
}
err = gh.insertParent(stagingArea, block, &blockQueue)
err = gh.insertParent(stagingArea, block, &blocksQueue)
if err != nil {
return nil, err
}
}
return allMergeSet, nil
return mergeSet, nil
}
/* ----------------insertParent------------------- */
/* Insert all parents to the queue*/
func (gh *ghostdagHelper) insertParent(stagingArea *model.StagingArea, child *externalapi.DomainHash,
queue *[]*externalapi.DomainHash) error {
// Insert all parents to the queue
func (gh *ghostdagHelper) insertParent(stagingArea *model.StagingArea, child *externalapi.DomainHash, queue *[]*externalapi.DomainHash) error {
parents, err := gh.dagTopologyManager.Parents(stagingArea, child)
if err != nil {
return err
@@ -346,8 +330,9 @@ func (gh *ghostdagHelper) insertParent(stagingArea *model.StagingArea, child *ex
return nil
}
/* ----------------findBlueSet------------------- */
func (gh *ghostdagHelper) findBlueSet(stagingArea *model.StagingArea, blueSet *[]*externalapi.DomainHash, selectedParent *externalapi.DomainHash) error {
func (gh *ghostdagHelper) findBlueSet(stagingArea *model.StagingArea, blueSet *[]*externalapi.DomainHash,
selectedParent *externalapi.DomainHash) error {
for selectedParent != nil {
if !contains(selectedParent, *blueSet) {
*blueSet = append(*blueSet, selectedParent)
@@ -368,44 +353,41 @@ func (gh *ghostdagHelper) findBlueSet(stagingArea *model.StagingArea, blueSet *[
return nil
}
/* ----------------sortByBlueScore------------------- */
func (gh *ghostdagHelper) sortByBlueWork(stagingArea *model.StagingArea, arr []*externalapi.DomainHash) error {
var err error = nil
var err error
sort.Slice(arr, func(i, j int) bool {
blockLeft, error := gh.dataStore.Get(gh.dbAccess, stagingArea, arr[i])
if error != nil {
err = error
blockLeft, err := gh.dataStore.Get(gh.dbAccess, stagingArea, arr[i])
if err != nil {
return false
}
blockRight, error := gh.dataStore.Get(gh.dbAccess, stagingArea, arr[j])
if error != nil {
err = error
blockRight, err := gh.dataStore.Get(gh.dbAccess, stagingArea, arr[j])
if err != nil {
return false
}
if blockLeft.BlueWork().Cmp(blockRight.BlueWork()) == -1 {
return true
}
if blockLeft.BlueWork().Cmp(blockRight.BlueWork()) == 0 {
return ismoreHash(arr[j], arr[i])
return isMoreHash(arr[j], arr[i])
}
return false
})
return err
}
/* --------------------------------------------- */
func (gh *ghostdagHelper) BlockData(stagingArea *model.StagingArea, blockHash *externalapi.DomainHash) (*model.BlockGHOSTDAGData, error) {
return gh.dataStore.Get(gh.dbAccess, stagingArea, blockHash)
}
func (gh *ghostdagHelper) ChooseSelectedParent(stagingArea *model.StagingArea, blockHashes ...*externalapi.DomainHash) (*externalapi.DomainHash, error) {
func (gh *ghostdagHelper) ChooseSelectedParent(*model.StagingArea, ...*externalapi.DomainHash) (*externalapi.DomainHash, error) {
panic("implement me")
}
func (gh *ghostdagHelper) Less(blockHashA *externalapi.DomainHash, ghostdagDataA *model.BlockGHOSTDAGData, blockHashB *externalapi.DomainHash, ghostdagDataB *model.BlockGHOSTDAGData) bool {
func (gh *ghostdagHelper) Less(*externalapi.DomainHash, *model.BlockGHOSTDAGData, *externalapi.DomainHash, *model.BlockGHOSTDAGData) bool {
panic("implement me")
}
func (gh *ghostdagHelper) GetSortedMergeSet(*model.StagingArea, *externalapi.DomainHash) ([]*externalapi.DomainHash, error) {
panic("implement me")
}

View File

@@ -9,15 +9,16 @@ import (
"reflect"
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/util/difficulty"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdag2"
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
"github.com/kaspanet/kaspad/domain/consensus/utils/blockheader"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/util/difficulty"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
@@ -57,7 +58,7 @@ func TestGHOSTDAG(t *testing.T) {
{ghostdagmanager.New, "Original"},
{ghostdag2.New, "Tal's impl"},
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
dagTopology := &DAGTopologyManagerImpl{
parentsMap: make(map[externalapi.DomainHash][]*externalapi.DomainHash),
}
@@ -71,7 +72,7 @@ func TestGHOSTDAG(t *testing.T) {
}
blockGHOSTDAGDataGenesis := model.NewBlockGHOSTDAGData(0, new(big.Int), nil, nil, nil, nil)
genesisHeader := consensusConfig.GenesisBlock.Header
genesisHeader := params.GenesisBlock.Header
genesisWork := difficulty.CalcWork(genesisHeader.Bits())
var testsCounter int
@@ -94,7 +95,7 @@ func TestGHOSTDAG(t *testing.T) {
if err != nil {
t.Fatalf("TestGHOSTDAG:failed decoding json: %v", err)
}
consensusConfig.K = test.K
params.K = test.K
genesisHash := *StringToDomainHash(test.GenesisID)

View File

@@ -8,14 +8,15 @@ import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/pkg/errors"
)
func TestAddHeaderTip(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestAddHeaderTip")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestAddHeaderTip")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
@@ -50,8 +51,8 @@ func TestAddHeaderTip(t *testing.T) {
}
}
expectedSelectedChain := []*externalapi.DomainHash{consensusConfig.GenesisHash}
tipHash := consensusConfig.GenesisHash
expectedSelectedChain := []*externalapi.DomainHash{params.GenesisHash}
tipHash := params.GenesisHash
for i := 0; i < 10; i++ {
var err error
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
@@ -63,8 +64,8 @@ func TestAddHeaderTip(t *testing.T) {
checkExpectedSelectedChain(expectedSelectedChain)
}
expectedSelectedChain = []*externalapi.DomainHash{consensusConfig.GenesisHash}
tipHash = consensusConfig.GenesisHash
expectedSelectedChain = []*externalapi.DomainHash{params.GenesisHash}
tipHash = params.GenesisHash
for i := 0; i < 11; i++ {
var err error
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)

View File

@@ -9,12 +9,13 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestPastMedianTime(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestUpdateReindexRoot")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestUpdateReindexRoot")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
@@ -22,8 +23,8 @@ func TestPastMedianTime(t *testing.T) {
numBlocks := uint32(300)
blockHashes := make([]*externalapi.DomainHash, numBlocks)
blockHashes[0] = consensusConfig.GenesisHash
blockTime := consensusConfig.GenesisBlock.Header.TimeInMilliseconds()
blockHashes[0] = params.GenesisHash
blockTime := params.GenesisBlock.Header.TimeInMilliseconds()
for i := uint32(1); i < numBlocks; i++ {
blockTime += 1000
block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{blockHashes[i-1]}, nil, nil)
@@ -72,7 +73,7 @@ func TestPastMedianTime(t *testing.T) {
}
millisecondsSinceGenesis := pastMedianTime -
consensusConfig.GenesisBlock.Header.TimeInMilliseconds()
params.GenesisBlock.Header.TimeInMilliseconds()
if millisecondsSinceGenesis != test.expectedMillisecondsSinceGenesis {
t.Errorf("TestCalcPastMedianTime: expected past median time of block %v to be %v milliseconds "+

View File

@@ -42,7 +42,7 @@ func TestPruning(t *testing.T) {
},
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
err := filepath.Walk("./testdata", func(path string, info os.FileInfo, err error) error {
if err != nil {
return err
@@ -65,22 +65,22 @@ func TestPruning(t *testing.T) {
t.Fatalf("TestPruning: failed decoding json: %v", err)
}
consensusConfig.FinalityDuration = time.Duration(test.FinalityDepth) * consensusConfig.TargetTimePerBlock
consensusConfig.MergeSetSizeLimit = test.MergeSetSizeLimit
params.FinalityDuration = time.Duration(test.FinalityDepth) * params.TargetTimePerBlock
params.MergeSetSizeLimit = test.MergeSetSizeLimit
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestPruning")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestPruning")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
defer teardown(false)
blockIDToHash := map[string]*externalapi.DomainHash{
"0": consensusConfig.GenesisHash,
"0": params.GenesisHash,
}
blockHashToID := map[externalapi.DomainHash]string{
*consensusConfig.GenesisHash: "0",
*params.GenesisHash: "0",
}
stagingArea := model.NewStagingArea()
@@ -133,7 +133,7 @@ func TestPruning(t *testing.T) {
}
pruningPointID := blockHashToID[*pruningPoint]
expectedPruningPoint := expectedPruningPointByNet[info.Name()][consensusConfig.Name]
expectedPruningPoint := expectedPruningPointByNet[info.Name()][params.Name]
if expectedPruningPoint != pruningPointID {
t.Fatalf("%s: Expected pruning point to be %s but got %s", info.Name(), expectedPruningPoint, pruningPointID)
}

View File

@@ -7,7 +7,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/utxo"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/kaspanet/kaspad/infrastructure/logger"
"github.com/kaspanet/kaspad/util/staging"
"github.com/pkg/errors"
)
@@ -31,11 +30,10 @@ type pruningManager struct {
utxoDiffStore model.UTXODiffStore
daaBlocksStore model.DAABlocksStore
isArchivalNode bool
genesisHash *externalapi.DomainHash
finalityInterval uint64
pruningDepth uint64
shouldSanityCheckPruningUTXOSet bool
isArchivalNode bool
genesisHash *externalapi.DomainHash
finalityInterval uint64
pruningDepth uint64
}
// New instantiates a new PruningManager
@@ -62,30 +60,28 @@ func New(
genesisHash *externalapi.DomainHash,
finalityInterval uint64,
pruningDepth uint64,
shouldSanityCheckPruningUTXOSet bool,
) model.PruningManager {
return &pruningManager{
databaseContext: databaseContext,
dagTraversalManager: dagTraversalManager,
dagTopologyManager: dagTopologyManager,
consensusStateManager: consensusStateManager,
consensusStateStore: consensusStateStore,
ghostdagDataStore: ghostdagDataStore,
pruningStore: pruningStore,
blockStatusStore: blockStatusStore,
multiSetStore: multiSetStore,
acceptanceDataStore: acceptanceDataStore,
blocksStore: blocksStore,
blockHeaderStore: blockHeaderStore,
utxoDiffStore: utxoDiffStore,
headerSelectedTipStore: headerSelectedTipStore,
daaBlocksStore: daaBlocksStore,
isArchivalNode: isArchivalNode,
genesisHash: genesisHash,
pruningDepth: pruningDepth,
finalityInterval: finalityInterval,
shouldSanityCheckPruningUTXOSet: shouldSanityCheckPruningUTXOSet,
databaseContext: databaseContext,
dagTraversalManager: dagTraversalManager,
dagTopologyManager: dagTopologyManager,
consensusStateManager: consensusStateManager,
consensusStateStore: consensusStateStore,
ghostdagDataStore: ghostdagDataStore,
pruningStore: pruningStore,
blockStatusStore: blockStatusStore,
multiSetStore: multiSetStore,
acceptanceDataStore: acceptanceDataStore,
blocksStore: blocksStore,
blockHeaderStore: blockHeaderStore,
utxoDiffStore: utxoDiffStore,
headerSelectedTipStore: headerSelectedTipStore,
daaBlocksStore: daaBlocksStore,
isArchivalNode: isArchivalNode,
genesisHash: genesisHash,
pruningDepth: pruningDepth,
finalityInterval: finalityInterval,
}
}
@@ -201,6 +197,7 @@ func (pm *pruningManager) UpdatePruningPointByVirtual(stagingArea *model.Staging
if err != nil {
return err
}
return pm.deletePastBlocks(stagingArea, newPruningPoint)
}
return nil
@@ -326,14 +323,13 @@ func (pm *pruningManager) savePruningPoint(stagingArea *model.StagingArea, pruni
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.savePruningPoint")
defer onEnd()
// If pruningPointHash is the genesis then there's no pruning point set right now.
if !pruningPointHash.Equal(pm.genesisHash) {
previousPruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea)
if err != nil {
return err
}
pm.pruningStore.StagePreviousPruningPoint(stagingArea, previousPruningPoint)
// TODO: This is an assert that takes ~30 seconds to run
// It must be removed or optimized before launching testnet
err := pm.validateUTXOSetFitsCommitment(stagingArea, pruningPointHash)
if err != nil {
return err
}
pm.pruningStore.StagePruningPoint(stagingArea, pruningPointHash)
pm.pruningStore.StageStartUpdatingPruningPointUTXOSet(stagingArea)
@@ -435,7 +431,7 @@ func (pm *pruningManager) validateUTXOSetFitsCommitment(stagingArea *model.Stagi
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.validateUTXOSetFitsCommitment")
defer onEnd()
utxoSetIterator, err := pm.pruningStore.PruningPointUTXOIterator(pm.databaseContext)
utxoSetIterator, err := pm.consensusStateManager.RestorePastUTXOSetIterator(stagingArea, pruningPointHash)
if err != nil {
return err
}
@@ -472,96 +468,6 @@ func (pm *pruningManager) validateUTXOSetFitsCommitment(stagingArea *model.Stagi
return nil
}
// This function takes 2 points (currentPruningHash, previousPruningHash) and traverses the UTXO diff children DAG
// until it finds a common descendant, at the worse case this descendant will be the current SelectedTip.
// it then creates 2 diffs, one from that descendant to previousPruningHash and another from that descendant to currentPruningHash
// then using `DiffFrom` it converts these 2 diffs to a single diff from previousPruningHash to currentPruningHash.
// this way should be the fastest way to get the difference between the 2 points, and should perform much better than restoring the full UTXO set.
func (pm *pruningManager) calculateDiffBetweenPreviousAndCurrentPruningPoints(stagingArea *model.StagingArea, currentPruningHash *externalapi.DomainHash) (externalapi.UTXODiff, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "pruningManager.calculateDiffBetweenPreviousAndCurrentPruningPoints")
defer onEnd()
if currentPruningHash.Equal(pm.genesisHash) {
return utxo.NewUTXODiff(), nil
}
previousPruningHash, err := pm.pruningStore.PreviousPruningPoint(pm.databaseContext, stagingArea)
if err != nil {
return nil, err
}
currentPruningGhostDAG, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, currentPruningHash)
if err != nil {
return nil, err
}
previousPruningGhostDAG, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, previousPruningHash)
if err != nil {
return nil, err
}
currentPruningCurrentDiffChild := currentPruningHash
previousPruningCurrentDiffChild := previousPruningHash
// We need to use BlueWork because it's the only thing that's monotonic in the whole DAG
// We use the BlueWork to know which point is currently lower on the DAG so we can keep climbing its children,
// that way we keep climbing on the lowest point until they both reach the exact same descendant
currentPruningCurrentDiffChildBlueWork := currentPruningGhostDAG.BlueWork()
previousPruningCurrentDiffChildBlueWork := previousPruningGhostDAG.BlueWork()
var diffsFromPrevious []externalapi.UTXODiff
var diffsFromCurrent []externalapi.UTXODiff
for {
// if currentPruningCurrentDiffChildBlueWork > previousPruningCurrentDiffChildBlueWork
if currentPruningCurrentDiffChildBlueWork.Cmp(previousPruningCurrentDiffChildBlueWork) == 1 {
utxoDiff, err := pm.utxoDiffStore.UTXODiff(pm.databaseContext, stagingArea, previousPruningCurrentDiffChild)
if err != nil {
return nil, err
}
diffsFromPrevious = append(diffsFromPrevious, utxoDiff)
previousPruningCurrentDiffChild, err = pm.utxoDiffStore.UTXODiffChild(pm.databaseContext, stagingArea, previousPruningCurrentDiffChild)
if err != nil {
return nil, err
}
diffChildGhostDag, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, previousPruningCurrentDiffChild)
if err != nil {
return nil, err
}
previousPruningCurrentDiffChildBlueWork = diffChildGhostDag.BlueWork()
} else if currentPruningCurrentDiffChild.Equal(previousPruningCurrentDiffChild) {
break
} else {
utxoDiff, err := pm.utxoDiffStore.UTXODiff(pm.databaseContext, stagingArea, currentPruningCurrentDiffChild)
if err != nil {
return nil, err
}
diffsFromCurrent = append(diffsFromCurrent, utxoDiff)
currentPruningCurrentDiffChild, err = pm.utxoDiffStore.UTXODiffChild(pm.databaseContext, stagingArea, currentPruningCurrentDiffChild)
if err != nil {
return nil, err
}
diffChildGhostDag, err := pm.ghostdagDataStore.Get(pm.databaseContext, stagingArea, currentPruningCurrentDiffChild)
if err != nil {
return nil, err
}
currentPruningCurrentDiffChildBlueWork = diffChildGhostDag.BlueWork()
}
}
// The order in which we apply the diffs should be from top to bottom, but we traversed from bottom to top
// so we apply the diffs in reverse order.
oldDiff := utxo.NewMutableUTXODiff()
for i := len(diffsFromPrevious) - 1; i >= 0; i-- {
err = oldDiff.WithDiffInPlace(diffsFromPrevious[i])
if err != nil {
return nil, err
}
}
newDiff := utxo.NewMutableUTXODiff()
for i := len(diffsFromCurrent) - 1; i >= 0; i-- {
err = newDiff.WithDiffInPlace(diffsFromCurrent[i])
if err != nil {
return nil, err
}
}
return oldDiff.DiffFrom(newDiff.ToImmutable())
}
// finalityScore is the number of finality intervals passed since
// the given block.
func (pm *pruningManager) finalityScore(blueScore uint64) uint64 {
@@ -610,7 +516,7 @@ func (pm *pruningManager) AppendImportedPruningPointUTXOs(outpointAndUTXOEntryPa
return dbTx.Commit()
}
func (pm *pruningManager) UpdatePruningPointIfRequired() error {
func (pm *pruningManager) UpdatePruningPointUTXOSetIfRequired() error {
hadStartedUpdatingPruningPointUTXOSet, err := pm.pruningStore.HadStartedUpdatingPruningPointUTXOSet(pm.databaseContext)
if err != nil {
return err
@@ -620,7 +526,7 @@ func (pm *pruningManager) UpdatePruningPointIfRequired() error {
}
log.Debugf("Pruning point UTXO set update is required")
err = pm.updatePruningPoint()
err = pm.updatePruningPointUTXOSet(model.NewStagingArea())
if err != nil {
return err
}
@@ -629,14 +535,13 @@ func (pm *pruningManager) UpdatePruningPointIfRequired() error {
return nil
}
func (pm *pruningManager) updatePruningPoint() error {
onEnd := logger.LogAndMeasureExecutionTime(log, "updatePruningPoint")
func (pm *pruningManager) updatePruningPointUTXOSet(stagingArea *model.StagingArea) error {
onEnd := logger.LogAndMeasureExecutionTime(log, "updatePruningPointUTXOSet")
defer onEnd()
logger.LogMemoryStats(log, "updatePruningPoint start")
defer logger.LogMemoryStats(log, "updatePruningPoint end")
logger.LogMemoryStats(log, "updatePruningPointUTXOSet start")
defer logger.LogMemoryStats(log, "updatePruningPointUTXOSet end")
stagingArea := model.NewStagingArea()
log.Debugf("Getting the pruning point")
pruningPoint, err := pm.pruningStore.PruningPoint(pm.databaseContext, stagingArea)
if err != nil {
@@ -644,27 +549,14 @@ func (pm *pruningManager) updatePruningPoint() error {
}
log.Debugf("Restoring the pruning point UTXO set")
utxoSetDiff, err := pm.calculateDiffBetweenPreviousAndCurrentPruningPoints(stagingArea, pruningPoint)
if err != nil {
return err
}
log.Debugf("Updating the pruning point UTXO set")
err = pm.pruningStore.UpdatePruningPointUTXOSet(pm.databaseContext, utxoSetDiff)
if err != nil {
return err
}
if pm.shouldSanityCheckPruningUTXOSet {
err = pm.validateUTXOSetFitsCommitment(stagingArea, pruningPoint)
if err != nil {
return err
}
}
err = pm.deletePastBlocks(stagingArea, pruningPoint)
utxoSetIterator, err := pm.consensusStateManager.RestorePastUTXOSetIterator(stagingArea, pruningPoint)
if err != nil {
return err
}
defer utxoSetIterator.Close()
err = staging.CommitAllChanges(pm.databaseContext, stagingArea)
log.Debugf("Updating the pruning point UTXO set")
err = pm.pruningStore.UpdatePruningPointUTXOSet(pm.databaseContext, utxoSetIterator)
if err != nil {
return err
}

View File

@@ -8,12 +8,13 @@ import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestReachabilityIsDAGAncestorOf(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestReachabilityIsDAGAncestorOf")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestReachabilityIsDAGAncestorOf")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -24,7 +25,7 @@ func TestReachabilityIsDAGAncestorOf(t *testing.T) {
// genesis \ \ sharedBlock
// \ \ /
// C <- D - - - - /
genesisHash := consensusConfig.GenesisHash
genesisHash := params.GenesisHash
blockHashA, _, err := tc.AddBlock([]*externalapi.DomainHash{genesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %v", err)

View File

@@ -9,13 +9,14 @@ import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot(t *testing.T) {
reachabilityReindexWindow := uint64(10)
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot")
if err != nil {
t.Fatalf("NewTestConsensus: %+v", err)
@@ -31,12 +32,12 @@ func TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot(t *t
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if !reindexRoot.Equal(consensusConfig.GenesisHash) {
if !reindexRoot.Equal(params.GenesisHash) {
t.Fatalf("reindex root is expected to initially be genesis")
}
// Add a block on top of the genesis block
chainRootBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
chainRootBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -66,13 +67,13 @@ func TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot(t *t
slackSize := tc.ReachabilityManager().ReachabilityReindexSlack()
blocksToAdd := uint64(math.Log2(float64(slackSize))) + 2
for i := uint64(0); i < blocksToAdd; i++ {
_, _, err = tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
_, _, err = tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}
@@ -81,9 +82,9 @@ func TestAddChildThatPointsDirectlyToTheSelectedParentChainBelowReindexRoot(t *t
func TestUpdateReindexRoot(t *testing.T) {
reachabilityReindexWindow := uint64(10)
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestUpdateReindexRoot")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestUpdateReindexRoot")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
@@ -102,12 +103,12 @@ func TestUpdateReindexRoot(t *testing.T) {
}
// Add two blocks on top of the genesis block
chain1RootBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
chain1RootBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
chain2RootBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
chain2RootBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -131,7 +132,7 @@ func TestUpdateReindexRoot(t *testing.T) {
t.Fatalf("ReachabilityReindexRoot: %s", err)
}
if !reindexRoot.Equal(consensusConfig.GenesisHash) {
if !reindexRoot.Equal(params.GenesisHash) {
t.Fatalf("reindex root unexpectedly moved")
}
}
@@ -162,14 +163,14 @@ func TestUpdateReindexRoot(t *testing.T) {
// Make sure that the rest of the interval has been allocated to
// chain1RootNode, minus slack from both sides
expectedChain1RootIntervalSize := intervalSize(consensusConfig.GenesisHash) - 1 -
expectedChain1RootIntervalSize := intervalSize(params.GenesisHash) - 1 -
intervalSize(chain2RootBlock) - 2*tc.ReachabilityManager().ReachabilityReindexSlack()
if intervalSize(chain1RootBlock) != expectedChain1RootIntervalSize {
t.Fatalf("got unexpected chain1RootBlock interval. Want: %d, got: %d",
intervalSize(chain1RootBlock), expectedChain1RootIntervalSize)
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}
@@ -178,9 +179,9 @@ func TestUpdateReindexRoot(t *testing.T) {
func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
reachabilityReindexWindow := uint64(10)
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestUpdateReindexRoot")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestUpdateReindexRoot")
if err != nil {
t.Fatalf("NewTestConsensus: %+v", err)
}
@@ -199,17 +200,17 @@ func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
}
// Add three children to the genesis: leftBlock, centerBlock, rightBlock
leftBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
leftBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
centerBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
centerBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
rightBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
rightBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -247,7 +248,7 @@ func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
t.Fatalf("rightBlock interval not tight after reindex")
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}
@@ -265,7 +266,7 @@ func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
t.Fatalf("AddBlock: %+v", err)
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}
@@ -283,13 +284,13 @@ func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
t.Fatalf("AddBlock: %+v", err)
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}
@@ -298,9 +299,9 @@ func TestReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
func TestTipsAfterReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
reachabilityReindexWindow := uint64(10)
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig, "TestUpdateReindexRoot")
tc, tearDown, err := factory.NewTestConsensus(params, false, "TestUpdateReindexRoot")
if err != nil {
t.Fatalf("NewTestConsensus: %s", err)
}
@@ -310,7 +311,7 @@ func TestTipsAfterReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
// Add a chain of reachabilityReindexWindow + 1 blocks above the genesis.
// This will set the reindex root to the child of genesis
chainTipHash := consensusConfig.GenesisHash
chainTipHash := params.GenesisHash
for i := uint64(0); i < reachabilityReindexWindow+1; i++ {
chainTipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{chainTipHash}, nil, nil)
if err != nil {
@@ -320,7 +321,7 @@ func TestTipsAfterReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
// Add another block above the genesis block. This will trigger an
// earlier-than-reindex-root reindex
sideBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
sideBlock, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -332,7 +333,7 @@ func TestTipsAfterReindexIntervalsEarlierThanReindexRoot(t *testing.T) {
t.Fatalf("AddBlock: %+v", err)
}
err = tc.ReachabilityManager().ValidateIntervals(consensusConfig.GenesisHash)
err = tc.ReachabilityManager().ValidateIntervals(params.GenesisHash)
if err != nil {
t.Fatal(err)
}

View File

@@ -22,9 +22,9 @@ const numBlocksExponent = 12
func initializeTest(t *testing.T, testName string) (tc testapi.TestConsensus, teardown func(keepDataDir bool)) {
t.Parallel()
consensusConfig := consensus.Config{Params: dagconfig.SimnetParams}
consensusConfig.SkipProofOfWork = true
tc, teardown, err := consensus.NewFactory().NewTestConsensus(&consensusConfig, testName)
params := dagconfig.SimnetParams
params.SkipProofOfWork = true
tc, teardown, err := consensus.NewFactory().NewTestConsensus(&params, false, testName)
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}

View File

@@ -8,22 +8,23 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/infrastructure/db/database"
"github.com/pkg/errors"
)
func TestCreateBlockLocator(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestCreateBlockLocator")
if err != nil {
t.Fatalf("NewTestConsensus: %+v", err)
}
defer tearDown(false)
chain := []*externalapi.DomainHash{consensusConfig.GenesisHash}
tipHash := consensusConfig.GenesisHash
chain := []*externalapi.DomainHash{params.GenesisHash}
tipHash := params.GenesisHash
for i := 0; i < 20; i++ {
var err error
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
@@ -34,13 +35,13 @@ func TestCreateBlockLocator(t *testing.T) {
chain = append(chain, tipHash)
}
sideChainTipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
sideChainTipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
// Check a situation where low hash is not on the exact step blue score
locator, err := tc.CreateBlockLocator(consensusConfig.GenesisHash, tipHash, 0)
locator, err := tc.CreateBlockLocator(params.GenesisHash, tipHash, 0)
if err != nil {
t.Fatalf("CreateBlockLocator: %+v", err)
}
@@ -73,7 +74,7 @@ func TestCreateBlockLocator(t *testing.T) {
}
// Check block locator with limit
locator, err = tc.CreateBlockLocator(consensusConfig.GenesisHash, tipHash, 3)
locator, err = tc.CreateBlockLocator(params.GenesisHash, tipHash, 3)
if err != nil {
t.Fatalf("CreateBlockLocator: %+v", err)
}
@@ -87,13 +88,13 @@ func TestCreateBlockLocator(t *testing.T) {
}
// Check a block locator from genesis to genesis
locator, err = tc.CreateBlockLocator(consensusConfig.GenesisHash, consensusConfig.GenesisHash, 0)
locator, err = tc.CreateBlockLocator(params.GenesisHash, params.GenesisHash, 0)
if err != nil {
t.Fatalf("CreateBlockLocator: %+v", err)
}
if !externalapi.HashesEqual(locator, []*externalapi.DomainHash{
consensusConfig.GenesisHash,
params.GenesisHash,
}) {
t.Fatalf("unexpected block locator %s", locator)
}
@@ -133,17 +134,17 @@ func TestCreateBlockLocator(t *testing.T) {
}
func TestCreateHeadersSelectedChainBlockLocator(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestCreateHeadersSelectedChainBlockLocator")
if err != nil {
t.Fatalf("NewTestConsensus: %+v", err)
}
defer tearDown(false)
chain := []*externalapi.DomainHash{consensusConfig.GenesisHash}
tipHash := consensusConfig.GenesisHash
chain := []*externalapi.DomainHash{params.GenesisHash}
tipHash := params.GenesisHash
for i := 0; i < 20; i++ {
var err error
tipHash, _, err = tc.AddBlock([]*externalapi.DomainHash{tipHash}, nil, nil)
@@ -154,13 +155,13 @@ func TestCreateHeadersSelectedChainBlockLocator(t *testing.T) {
chain = append(chain, tipHash)
}
sideChainTipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, nil, nil)
sideChainTipHash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
// Check a situation where low hash is not on the exact step
locator, err := tc.CreateHeadersSelectedChainBlockLocator(consensusConfig.GenesisHash, tipHash)
locator, err := tc.CreateHeadersSelectedChainBlockLocator(params.GenesisHash, tipHash)
if err != nil {
t.Fatalf("CreateBlockLocator: %+v", err)
}
@@ -193,13 +194,13 @@ func TestCreateHeadersSelectedChainBlockLocator(t *testing.T) {
}
// Check a block locator from genesis to genesis
locator, err = tc.CreateHeadersSelectedChainBlockLocator(consensusConfig.GenesisHash, consensusConfig.GenesisHash)
locator, err = tc.CreateHeadersSelectedChainBlockLocator(params.GenesisHash, params.GenesisHash)
if err != nil {
t.Fatalf("CreateBlockLocator: %+v", err)
}
if !externalapi.HashesEqual(locator, []*externalapi.DomainHash{
consensusConfig.GenesisHash,
params.GenesisHash,
}) {
t.Fatalf("unexpected block locator %s", locator)
}
@@ -224,7 +225,7 @@ func TestCreateHeadersSelectedChainBlockLocator(t *testing.T) {
}
// Check block locator with non chain blocks
_, err = tc.CreateHeadersSelectedChainBlockLocator(consensusConfig.GenesisHash, sideChainTipHash)
_, err = tc.CreateHeadersSelectedChainBlockLocator(params.GenesisHash, sideChainTipHash)
if !errors.Is(err, model.ErrBlockNotInSelectedParentChain) {
t.Fatalf("expected error '%s' but got '%s'", database.ErrNotFound, err)
}

View File

@@ -11,14 +11,15 @@ import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
func TestSyncManager_GetHashesBetween(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
stagingArea := model.NewStagingArea()
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestSyncManager_GetHashesBetween")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestSyncManager_GetHashesBetween")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -35,7 +36,7 @@ func TestSyncManager_GetHashesBetween(t *testing.T) {
// \ | /
// etc.
expectedOrder := make([]*externalapi.DomainHash, 0, 40)
mergingBlock := consensusConfig.GenesisHash
mergingBlock := params.GenesisHash
for i := 0; i < 10; i++ {
splitBlocks := make([]*externalapi.DomainHash, 0, 3)
for j := 0; j < 3; j++ {
@@ -69,7 +70,7 @@ func TestSyncManager_GetHashesBetween(t *testing.T) {
}
actualOrder, _, err := tc.SyncManager().GetHashesBetween(
stagingArea, consensusConfig.GenesisHash, expectedOrder[len(expectedOrder)-1], math.MaxUint64)
stagingArea, params.GenesisHash, expectedOrder[len(expectedOrder)-1], math.MaxUint64)
if err != nil {
t.Fatalf("TestSyncManager_GetHashesBetween failed returning actualOrder: %v", err)
}

View File

@@ -68,7 +68,8 @@ func (v *transactionValidator) checkTransactionCoinbaseMaturity(stagingArea *mod
missingOutpoints = append(missingOutpoints, &input.PreviousOutpoint)
} else if utxoEntry.IsCoinbase() {
originDAAScore := utxoEntry.BlockDAAScore()
if originDAAScore+v.blockCoinbaseMaturity > povDAAScore {
daaScoreSincePrev := povDAAScore - originDAAScore
if daaScoreSincePrev < v.blockCoinbaseMaturity {
return errors.Wrapf(ruleerrors.ErrImmatureSpend, "tried to spend coinbase "+
"transaction output %s from DAA score %d "+
"to DAA score %d before required maturity "+
@@ -265,7 +266,7 @@ func (v *transactionValidator) calcTxSequenceLockFromReferencedUTXOEntries(stagi
baseHash := povBlockHash
for {
selectedParentDAAScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, stagingArea, baseHash)
selectedParentDAAScore, err := v.daaBlocksStore.DAAScore(v.databaseContext, stagingArea, povBlockHash)
if err != nil {
return nil, err
}

View File

@@ -10,6 +10,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util"
"github.com/pkg/errors"
)
@@ -21,9 +22,9 @@ type txSubnetworkData struct {
}
func TestValidateTransactionInIsolation(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestValidateTransactionInIsolation")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestValidateTransactionInIsolation")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -78,7 +79,7 @@ func TestValidateTransactionInIsolation(t *testing.T) {
1,
1,
subnetworks.SubnetworkIDNative,
&txSubnetworkData{subnetworks.SubnetworkIDCoinbase, 0, make([]byte, consensusConfig.MaxCoinbasePayloadLength+1)},
&txSubnetworkData{subnetworks.SubnetworkIDCoinbase, 0, make([]byte, params.MaxCoinbasePayloadLength+1)},
nil,
ruleerrors.ErrBadCoinbasePayloadLen},
{"non-zero gas in Kaspa", 1, 1, 0,

View File

@@ -16,6 +16,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/subnetworks"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors"
)
@@ -29,7 +30,7 @@ func (mdf *mocPastMedianTimeManager) PastMedianTime(*model.StagingArea, *externa
}
func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
factory := consensus.NewFactory()
pastMedianManager := &mocPastMedianTimeManager{}
@@ -37,7 +38,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
model.GHOSTDAGDataStore, *externalapi.DomainHash) model.PastMedianTimeManager {
return pastMedianManager
})
tc, tearDown, err := factory.NewTestConsensus(consensusConfig,
tc, tearDown, err := factory.NewTestConsensus(params, false,
"TestValidateTransactionInContextAndPopulateMassAndFee")
if err != nil {
t.Fatalf("Failed create a NewTestConsensus: %s", err)
@@ -57,7 +58,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
if err != nil {
t.Fatalf("Failed to serialize public key: %v", err)
}
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], consensusConfig.Prefix)
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], params.Prefix)
if err != nil {
t.Fatalf("Failed to generate p2pk address: %v", err)
}
@@ -78,17 +79,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
true,
uint64(5)),
}
immatureInput := externalapi.DomainTransactionInput{
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.MaxTxInSequenceNum,
UTXOEntry: utxo.NewUTXOEntry(
100_000_000, // 1 KAS
scriptPublicKey,
true,
uint64(6)),
}
txInputWithSequenceLockTimeIsSeconds := externalapi.DomainTransactionInput{
txInputWithMaxSequence := externalapi.DomainTransactionInput{
PreviousOutpoint: prevOutPoint,
SignatureScript: []byte{},
Sequence: constants.SequenceLockTimeIsSeconds,
@@ -120,7 +111,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
validTx := externalapi.DomainTransaction{
Version: constants.MaxTransactionVersion,
Inputs: []*externalapi.DomainTransactionInput{&txInputWithSequenceLockTimeIsSeconds},
Inputs: []*externalapi.DomainTransactionInput{&txInputWithMaxSequence},
Outputs: []*externalapi.DomainTransactionOutput{&txOut},
SubnetworkID: subnetworks.SubnetworkIDRegistry,
Gas: 0,
@@ -137,7 +128,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
txWithImmatureCoinbase := externalapi.DomainTransaction{
Version: constants.MaxTransactionVersion,
Inputs: []*externalapi.DomainTransactionInput{&immatureInput},
Inputs: []*externalapi.DomainTransactionInput{&txInput},
Outputs: []*externalapi.DomainTransactionOutput{&txOut},
SubnetworkID: subnetworks.SubnetworkIDRegistry,
Gas: 0,
@@ -167,16 +158,8 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
stagingArea := model.NewStagingArea()
povBlockHash := externalapi.NewDomainHashFromByteArray(&[32]byte{0x01})
tc.DAABlocksStore().StageDAAScore(stagingArea, povBlockHash, consensusConfig.BlockCoinbaseMaturity+txInput.UTXOEntry.BlockDAAScore())
// Just use some stub ghostdag data
tc.GHOSTDAGDataStore().Stage(stagingArea, povBlockHash, model.NewBlockGHOSTDAGData(
0,
nil,
consensusConfig.GenesisHash,
nil,
nil,
nil))
tc.DAABlocksStore().StageDAAScore(stagingArea, povBlockHash, params.BlockCoinbaseMaturity+txInput.UTXOEntry.BlockDAAScore())
tc.DAABlocksStore().StageDAAScore(stagingArea, povBlockHash, 10)
tests := []struct {
name string
@@ -189,7 +172,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
{
name: "Valid transaction",
tx: &validTx,
povBlockHash: povBlockHash,
povBlockHash: model.VirtualBlockHash,
selectedParentMedianTime: 1,
isValid: true,
expectedError: nil,
@@ -207,7 +190,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
{ // The total inputs amount is bigger than the allowed maximum (constants.MaxSompi)
name: "checkTransactionInputAmounts",
tx: &txWithLargeAmount,
povBlockHash: povBlockHash,
povBlockHash: model.VirtualBlockHash,
selectedParentMedianTime: 1,
isValid: false,
expectedError: ruleerrors.ErrBadTxOutValue,
@@ -215,7 +198,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
{ // The total SompiIn (sum of inputs amount) is smaller than the total SompiOut (sum of outputs value) and hence invalid.
name: "checkTransactionOutputAmounts",
tx: &txWithBigValue,
povBlockHash: povBlockHash,
povBlockHash: model.VirtualBlockHash,
selectedParentMedianTime: 1,
isValid: false,
expectedError: ruleerrors.ErrSpendTooHigh,
@@ -223,15 +206,15 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
{ // the selectedParentMedianTime is negative and hence invalid.
name: "checkTransactionSequenceLock",
tx: &validTx,
povBlockHash: povBlockHash,
povBlockHash: model.VirtualBlockHash,
selectedParentMedianTime: -1,
isValid: false,
expectedError: ruleerrors.ErrUnfinalizedTx,
},
{ // The SignatureScript (in the immatureInput) is empty and hence invalid.
{ // The SignatureScript (in the txInput) is empty and hence invalid.
name: "checkTransactionScripts",
tx: &txWithInvalidSignature,
povBlockHash: povBlockHash,
povBlockHash: model.VirtualBlockHash,
selectedParentMedianTime: 1,
isValid: false,
expectedError: ruleerrors.ErrScriptValidation,
@@ -244,7 +227,7 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
if test.isValid {
if err != nil {
t.Fatalf("Unexpected error on TestValidateTransactionInContextAndPopulateMassAndFee"+
" on test '%v': %+v", test.name, err)
" on test '%v': %v", test.name, err)
}
} else {
if err == nil || !errors.Is(err, test.expectedError) {
@@ -257,10 +240,10 @@ func TestValidateTransactionInContextAndPopulateMassAndFee(t *testing.T) {
}
func TestSigningTwoInputs(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.BlockCoinbaseMaturity = 0
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestSigningTwoInputs")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestSigningTwoInputs")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -278,7 +261,7 @@ func TestSigningTwoInputs(t *testing.T) {
if err != nil {
t.Fatalf("Failed to serialize public key: %v", err)
}
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], consensusConfig.Prefix)
addr, err := util.NewAddressPublicKey(publicKeySerialized[:], params.Prefix)
if err != nil {
t.Fatalf("Failed to generate p2pk address: %v", err)
}
@@ -292,7 +275,7 @@ func TestSigningTwoInputs(t *testing.T) {
ScriptPublicKey: scriptPublicKey,
}
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, coinbaseData, nil)
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, coinbaseData, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}
@@ -381,10 +364,10 @@ func TestSigningTwoInputs(t *testing.T) {
}
func TestSigningTwoInputsECDSA(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
consensusConfig.BlockCoinbaseMaturity = 0
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory()
tc, teardown, err := factory.NewTestConsensus(consensusConfig, "TestSigningTwoInputsECDSA")
tc, teardown, err := factory.NewTestConsensus(params, false, "TestSigningTwoInputsECDSA")
if err != nil {
t.Fatalf("Error setting up consensus: %+v", err)
}
@@ -402,7 +385,7 @@ func TestSigningTwoInputsECDSA(t *testing.T) {
if err != nil {
t.Fatalf("Failed to serialize public key: %v", err)
}
addr, err := util.NewAddressPublicKeyECDSA(publicKeySerialized[:], consensusConfig.Prefix)
addr, err := util.NewAddressPublicKeyECDSA(publicKeySerialized[:], params.Prefix)
if err != nil {
t.Fatalf("Failed to generate p2pk address: %v", err)
}
@@ -416,7 +399,7 @@ func TestSigningTwoInputsECDSA(t *testing.T) {
ScriptPublicKey: scriptPublicKey,
}
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{consensusConfig.GenesisHash}, coinbaseData, nil)
block1Hash, _, err := tc.AddBlock([]*externalapi.DomainHash{params.GenesisHash}, coinbaseData, nil)
if err != nil {
t.Fatalf("AddBlock: %+v", err)
}

View File

@@ -1,9 +1,8 @@
package consensus_test
package consensus
import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
@@ -15,13 +14,13 @@ func TestPruningDepth(t *testing.T) {
dagconfig.DevnetParams.Name: 244838,
dagconfig.SimnetParams.Name: 192038,
}
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
expected, found := expectedResult[consensusConfig.Name]
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
expected, found := expectedResult[params.Name]
if !found {
t.Fatalf("TestPruningDepth: expectedResult doesn't contain '%s'", consensusConfig.Name)
t.Fatalf("TestPruningDepth: expectedResult doesn't contain '%s'", params.Name)
}
if consensusConfig.PruningDepth() != expected {
t.Errorf("pruningDepth in %s is expected to be %d but got %d", consensusConfig.Name, expected, consensusConfig.PruningDepth())
if params.PruningDepth() != expected {
t.Errorf("pruningDepth in %s is expected to be %d but got %d", params.Name, expected, params.PruningDepth())
}
})
}

View File

@@ -7,8 +7,6 @@ import (
"io/ioutil"
"os/exec"
"strings"
"github.com/kaspanet/kaspad/domain/consensus/model"
)
// RenderDAGToDot is a helper function for debugging tests.
@@ -30,7 +28,6 @@ func (tc *testConsensus) convertToDot() (string, error) {
}
defer blocksIterator.Close()
stagingArea := model.NewStagingArea()
for ok := blocksIterator.First(); ok; ok = blocksIterator.Next() {
hash, err := blocksIterator.Get()
if err != nil {
@@ -38,7 +35,7 @@ func (tc *testConsensus) convertToDot() (string, error) {
}
dotScriptBuilder.WriteString(fmt.Sprintf("\t\"%s\";\n", hash))
parents, err := tc.dagTopologyManager.Parents(stagingArea, hash)
parents, err := tc.dagTopologyManager.Parents(nil, hash)
if err != nil {
return "", err
}

View File

@@ -1,12 +1,12 @@
package mining
import (
"github.com/kaspanet/kaspad/domain/consensus/model/pow"
"github.com/kaspanet/kaspad/util/difficulty"
"math"
"math/rand"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/pow"
"github.com/kaspanet/kaspad/util/difficulty"
"github.com/pkg/errors"
)

View File

@@ -3,13 +3,12 @@ package testutils
import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/dagconfig"
)
// ForAllNets runs the passed testFunc with all available networks
// if setDifficultyToMinumum = true - will modify the net params to have minimal difficulty, like in SimNet
func ForAllNets(t *testing.T, skipPow bool, testFunc func(*testing.T, *consensus.Config)) {
func ForAllNets(t *testing.T, skipPow bool, testFunc func(*testing.T, *dagconfig.Params)) {
allParams := []dagconfig.Params{
dagconfig.MainnetParams,
dagconfig.TestnetParams,
@@ -18,12 +17,12 @@ func ForAllNets(t *testing.T, skipPow bool, testFunc func(*testing.T, *consensus
}
for _, params := range allParams {
consensusConfig := consensus.Config{Params: params}
t.Run(consensusConfig.Name, func(t *testing.T) {
paramsCopy := params
t.Run(paramsCopy.Name, func(t *testing.T) {
t.Parallel()
consensusConfig.SkipProofOfWork = skipPow
t.Logf("Running test for %s", consensusConfig.Name)
testFunc(t, &consensusConfig)
paramsCopy.SkipProofOfWork = skipPow
t.Logf("Running test for %s", paramsCopy.Name)
testFunc(t, &paramsCopy)
})
}
}

View File

@@ -5,6 +5,7 @@ import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/model/testapi"
)

View File

@@ -34,6 +34,23 @@ func checkIntersectionWithRule(collection1 utxoCollection, collection2 utxoColle
return nil, false
}
// minInt returns the smaller of x or y integer values
func minInt(a, b int) int {
if a < b {
return a
}
return b
}
// intersectionWithRemainderHavingDAAScore calculates an intersection between two utxoCollections
// having same DAA score, returns the result and the remainder from collection1
func intersectionWithRemainderHavingDAAScore(collection1, collection2 utxoCollection) (result, remainder utxoCollection) {
result = make(utxoCollection, minInt(len(collection1), len(collection2)))
remainder = make(utxoCollection, len(collection1))
intersectionWithRemainderHavingDAAScoreInPlace(collection1, collection2, result, remainder)
return
}
// intersectionWithRemainderHavingDAAScoreInPlace calculates an intersection between two utxoCollections
// having same DAA score, puts it into result and into remainder from collection1
func intersectionWithRemainderHavingDAAScoreInPlace(collection1, collection2, result, remainder utxoCollection) {
@@ -46,6 +63,15 @@ func intersectionWithRemainderHavingDAAScoreInPlace(collection1, collection2, re
}
}
// subtractionHavingDAAScore calculates a subtraction between collection1 and collection2
// having same DAA score, returns the result
func subtractionHavingDAAScore(collection1, collection2 utxoCollection) (result utxoCollection) {
result = make(utxoCollection, len(collection1))
subtractionHavingDAAScoreInPlace(collection1, collection2, result)
return
}
// subtractionHavingDAAScoreInPlace calculates a subtraction between collection1 and collection2
// having same DAA score, puts it into result
func subtractionHavingDAAScoreInPlace(collection1, collection2, result utxoCollection) {
@@ -56,6 +82,16 @@ func subtractionHavingDAAScoreInPlace(collection1, collection2, result utxoColle
}
}
// subtractionWithRemainderHavingDAAScore calculates a subtraction between collection1 and collection2
// having same DAA score, returns the result and the remainder from collection1
func subtractionWithRemainderHavingDAAScore(collection1, collection2 utxoCollection) (result, remainder utxoCollection) {
result = make(utxoCollection, len(collection1))
remainder = make(utxoCollection, len(collection1))
subtractionWithRemainderHavingDAAScoreInPlace(collection1, collection2, result, remainder)
return
}
// subtractionWithRemainderHavingDAAScoreInPlace calculates a subtraction between collection1 and collection2
// having same DAA score, puts it into result and into remainder from collection1
func subtractionWithRemainderHavingDAAScoreInPlace(collection1, collection2, result, remainder utxoCollection) {
@@ -139,13 +175,13 @@ func diffFrom(this, other *mutableUTXODiff) (*mutableUTXODiff, error) {
}
result := &mutableUTXODiff{
toAdd: make(utxoCollection),
toRemove: make(utxoCollection),
toAdd: make(utxoCollection, len(this.toRemove)+len(other.toAdd)),
toRemove: make(utxoCollection, len(this.toAdd)+len(other.toRemove)),
}
// All transactions in this.toAdd:
// If they are not in other.toAdd - should be added in result.toRemove
inBothToAdd := make(utxoCollection)
inBothToAdd := make(utxoCollection, len(this.toAdd))
subtractionWithRemainderHavingDAAScoreInPlace(this.toAdd, other.toAdd, result.toRemove, inBothToAdd)
// If they are in other.toRemove - base utxoSet is not the same
if checkIntersection(inBothToAdd, this.toRemove) != checkIntersection(inBothToAdd, other.toRemove) {
@@ -187,13 +223,13 @@ func withDiffInPlace(this *mutableUTXODiff, other *mutableUTXODiff) error {
"withDiffInPlace: outpoint %s both in this.toAdd and in other.toAdd", offendingOutpoint)
}
intersection := make(utxoCollection)
intersection := make(utxoCollection, minInt(len(other.toRemove), len(this.toAdd)))
// If not exists neither in toAdd nor in toRemove - add to toRemove
intersectionWithRemainderHavingDAAScoreInPlace(other.toRemove, this.toAdd, intersection, this.toRemove)
// If already exists in toAdd with the same DAA score - remove from toAdd
this.toAdd.removeMultiple(intersection)
intersection = make(utxoCollection)
intersection = make(utxoCollection, minInt(len(other.toAdd), len(this.toRemove)))
// If not exists neither in toAdd nor in toRemove, or exists in toRemove with different DAA score - add to toAdd
intersectionWithRemainderHavingDAAScoreInPlace(other.toAdd, this.toRemove, intersection, this.toAdd)
// If already exists in toRemove with the same DAA score - remove from toRemove

View File

@@ -13,7 +13,7 @@ type immutableUTXODiff struct {
func (iud *immutableUTXODiff) ToAdd() externalapi.UTXOCollection {
if iud.isInvalidated {
panic(errors.New("Attempt to read from an invalidated UTXODiff"))
panic("Attempt to read from an invalidated UTXODiff")
}
return iud.mutableUTXODiff.ToAdd()
@@ -21,7 +21,7 @@ func (iud *immutableUTXODiff) ToAdd() externalapi.UTXOCollection {
func (iud *immutableUTXODiff) ToRemove() externalapi.UTXOCollection {
if iud.isInvalidated {
panic(errors.New("Attempt to read from an invalidated UTXODiff"))
panic("Attempt to read from an invalidated UTXODiff")
}
return iud.mutableUTXODiff.ToRemove()
@@ -29,7 +29,7 @@ func (iud *immutableUTXODiff) ToRemove() externalapi.UTXOCollection {
func (iud *immutableUTXODiff) WithDiff(other externalapi.UTXODiff) (externalapi.UTXODiff, error) {
if iud.isInvalidated {
panic(errors.New("Attempt to read from an invalidated UTXODiff"))
panic("Attempt to read from an invalidated UTXODiff")
}
return iud.mutableUTXODiff.WithDiff(other)
@@ -37,7 +37,7 @@ func (iud *immutableUTXODiff) WithDiff(other externalapi.UTXODiff) (externalapi.
func (iud *immutableUTXODiff) DiffFrom(other externalapi.UTXODiff) (externalapi.UTXODiff, error) {
if iud.isInvalidated {
panic(errors.New("Attempt to read from an invalidated UTXODiff"))
panic("Attempt to read from an invalidated UTXODiff")
}
return iud.mutableUTXODiff.DiffFrom(other)
@@ -74,22 +74,9 @@ func NewUTXODiffFromCollections(toAdd, toRemove externalapi.UTXOCollection) (ext
}
func (iud *immutableUTXODiff) CloneMutable() externalapi.MutableUTXODiff {
if iud.isInvalidated {
panic(errors.New("Attempt to read from an invalidated UTXODiff"))
}
return iud.cloneMutable()
}
func (iud *immutableUTXODiff) Reversed() externalapi.UTXODiff {
if iud.isInvalidated {
panic(errors.New("Attempt to read from an invalidated UTXODiff"))
}
return &immutableUTXODiff{
mutableUTXODiff: iud.mutableUTXODiff.Reversed(),
isInvalidated: false,
}
}
func (iud *immutableUTXODiff) cloneMutable() *mutableUTXODiff {
if iud == nil {
return nil
@@ -97,7 +84,3 @@ func (iud *immutableUTXODiff) cloneMutable() *mutableUTXODiff {
return iud.mutableUTXODiff.clone()
}
func (iud immutableUTXODiff) String() string {
return iud.mutableUTXODiff.String()
}

View File

@@ -157,11 +157,3 @@ func (mud *mutableUTXODiff) clone() *mutableUTXODiff {
func (mud *mutableUTXODiff) String() string {
return fmt.Sprintf("toAdd: %s; toRemove: %s", mud.toAdd, mud.toRemove)
}
func (mud *mutableUTXODiff) Reversed() *mutableUTXODiff {
return &mutableUTXODiff{
toAdd: mud.toRemove,
toRemove: mud.toAdd,
immutableReferences: mud.immutableReferences,
}
}

View File

@@ -177,10 +177,10 @@ var testnetGenesisCoinbaseTx = transactionhelper.NewSubnetworkTransaction(0,
// testnetGenesisHash is the hash of the first block in the block DAG for the test
// network (genesis block).
var testnetGenesisHash = externalapi.NewDomainHashFromByteArray(&[externalapi.DomainHashSize]byte{
0xac, 0x23, 0xff, 0xc3, 0x85, 0xd3, 0x88, 0x99,
0xfd, 0xb8, 0x83, 0x30, 0x80, 0x3a, 0x3d, 0xbf,
0xf7, 0x9b, 0x96, 0x9e, 0x4c, 0xd5, 0x1b, 0xf0,
0x0e, 0x77, 0xb6, 0x87, 0x70, 0xaa, 0x4e, 0x1f,
0x8f, 0x83, 0xf5, 0x33, 0x77, 0xa4, 0x80, 0xa7,
0x93, 0xf3, 0x17, 0xee, 0x3e, 0x8f, 0xf5, 0xaf,
0x16, 0x6d, 0x87, 0x1d, 0x54, 0xfd, 0xe7, 0x79,
0xa2, 0xab, 0x6f, 0xc3, 0x76, 0x60, 0xc3, 0x64,
})
// testnetGenesisMerkleRoot is the hash of the first transaction in the genesis block
@@ -201,9 +201,9 @@ var testnetGenesisBlock = externalapi.DomainBlock{
testnetGenesisMerkleRoot,
&externalapi.DomainHash{},
externalapi.NewDomainHashFromByteArray(muhash.EmptyMuHashHash.AsArray()),
0x178547bee50,
0x177bfd44a10,
0x1e7fffff,
0x2de70,
0x64d74,
),
Transactions: []*externalapi.DomainTransaction{testnetGenesisCoinbaseTx},
}

View File

@@ -256,11 +256,11 @@ var MainnetParams = Params{
// TestnetParams defines the network parameters for the test Kaspa network.
var TestnetParams = Params{
K: defaultGHOSTDAGK,
Name: "kaspa-testnet-5",
Name: "kaspa-testnet-2",
Net: appmessage.Testnet,
RPCPort: "16210",
DefaultPort: "16211",
DNSSeeds: []string{"testnet-5-dnsseed.daglabs-dev.com"},
DNSSeeds: []string{"testnet-2-dnsseed.daglabs-dev.com"},
// DAG parameters
GenesisBlock: &testnetGenesisBlock,

View File

@@ -3,6 +3,7 @@ package domain
import (
"github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/domain/miningmanager"
infrastructuredatabase "github.com/kaspanet/kaspad/infrastructure/db/database"
)
@@ -27,15 +28,15 @@ func (d domain) MiningManager() miningmanager.MiningManager {
}
// New instantiates a new instance of a Domain object
func New(consensusConfig *consensus.Config, db infrastructuredatabase.Database) (Domain, error) {
func New(dagParams *dagconfig.Params, db infrastructuredatabase.Database, isArchivalNode bool) (Domain, error) {
consensusFactory := consensus.NewFactory()
consensusInstance, err := consensusFactory.NewConsensus(consensusConfig, db)
consensusInstance, err := consensusFactory.NewConsensus(dagParams, db, isArchivalNode)
if err != nil {
return nil, err
}
miningManagerFactory := miningmanager.NewFactory()
miningManager := miningManagerFactory.NewMiningManager(consensusInstance, &consensusConfig.Params)
miningManager := miningManagerFactory.NewMiningManager(consensusInstance, dagParams)
return &domain{
consensus: consensusInstance,

Some files were not shown because too many files have changed in this diff Show More