kaspad/domain/consensus/factory.go
Ori Newman fc5e39f6cc [NOD-1535] fix reachability test (#1061)
* Revert "[NOD-1500] Delete integration tests"

This reverts commit fcb57a206690a884fa6afb69d5d493282954a8bf.

* [NOD-1518] hashserialization -> consenusserialization

* [NOD-1518] Fix add genesis to virtual

* [NOD-1518] Fix a bug in SerializeCoinbasePayload.

* [NOD-1518] Fix a loop error and make pastMedianTime behave correctly everywhere on genesis.

* [NOD-1518] Fix another bug and an infinite loop.

* [NOD-1518] Fix uninitialized slice.

* [NOD-1518] Fix bad should-commit checks and another infinite loop.

* [NOD-1518] Fix nil serialization.

* [NOD-1518] Rename blockHash to currentBlockHash.

* [NOD-1518] Move the check whether stagedVirtualUTXOSet != nil to the top of commitVirtualUTXODiff.

* [NOD-1518] Simplify utxoDiffStore.Commit.

* [NOD-1518] Unextract resolveBlockStatusAndCheckFinality.

* [NOD-1518] Move no-transactions logic into CalculateIDMerkleRoot.

* [NOD-1518] Remove redundant is-staged check.

* [NOD-1518] Fix merge errors.

* [NOD-1518] Don't write anything if utxoDiffChild is nil.

* [NOD-1518] Stage virtualAcceptanceData and virtualMultiset.

* [NOD-1518] Fix bugs in getBlockTemplate and submitBlock.

* [NOD-1518] Fix bad validation order in validateHeaderInContext.

* [NOD-1518] Fix bug in Next().

* [NOD-1518] Fix nil dereference of subnetworks in AddressCache.

* [NOD-1518] Fix multisetStore.Get returning a pointer to a multiset that is changed in place.

* [NOD-1518] Break on genesis in countSubtrees.

* [NOD-1518] Fix createBlockLocator.

* [NOD-1518] Fix MsgTxToDomainTransaction.

* [NOD-1518] Set MaxTxVersion to 1.

* [NOD-1518] Fix missing error handling, bug in MsgTxToDomainTransaction, and bad subnetwork equality check.

* [NOD-1518] Fix bug in hasUTXOByOutpointFromStagedVirtualUTXODiff.

* [NOD-1518] Remove irrelevant comments.

* [NOD-1518] Generate transactions with sufficient fee in tx_relay_test.

* [NOD-1518] Fix broken RPC handlers.

* [NOD-1518] Fix merge errors.

* [NOD-1518] Fix bad exists check in restorePastUTXO and missing genesis check in CalculatePastUTXOAndAcceptanceData.

* [NOD-1518] Add a comment.

* [NOD-1518] Use a regular mutex instead of a read-write mutex in consensus to avoid dealing with sneaky not-actually-read functions.

* [NOD-1518] Fix a deadlock in GetVirtualSelectedParent.

* [NOD-1518] Fix missing handler registration for CmdHeader.

* [NOD-1518] Fix processHeader calling OnNewBlock and LogBlock. Also fix conversion errors in IBDRootUTXOSetAndBlock.

* [NOD-1518] Fix bad Command() in MsgIBDRootUTXOSetAndBlock.

* [NOD-1518] Fix bad SyncStateMissingUTXOSet logic in resolveSyncState.

* [NOD-1518] Rename mode to syncState.

* [NOD-1518] Fix headers-only blocks coming in after the consensus thinks it's synced.

* [NOD-1518] Fix selectedChildIterator.Next not ignoring virtual, infinite loop in HashSet.Length().

* [NOD-1518] Fix not-properly wrapped IBD blocks.

* [NOD-1518] Fix bad conversion in RequestIBDBlocks.

* [NOD-1518] Fix bad string for CmdRequestHeaders.

* [NOD-1518] Fix bad string for CmdDoneHeaders.

* [NOD-1518] Fix bad Command() for MsgIBDRootNotFound.

* [NOD-1518] Fix bad areHeaderTipsSyncedMaxTimeDifference value.

* [NOD-1518] Add missing string for CmdRequestIBDBlocks.

* [NOD-1518] Fix bad check for SyncStateMissingBlockBodies.

* [NOD-1518] Fix bad timeout durations in tests.

* [NOD-1518] Fix IBD blocks not calling OnNewBlock.

* [NOD-1518] Change when IBD finishes.

* [NOD-1518] Properly clone utxoDiffChild.

* [NOD-1535] Fix reachability tests

* [NOD-1518] Fix merge errors.

* [NOD-1518] Move call to LogBlock to into OnNewBlock.

* [NOD-1518] Return "not implemented" in unimplemented RPC handlers.

* [NOD-1518] Extract cloning of hashes to a method over DomainHash.

* [NOD-1518] Use isHeaderOnlyBlock.

* [NOD-1518] Use constants.TransactionVersion.

* [NOD-1518] Break immediately if we reached the virtual in SelectedChildIterator.

* [NOD-1518] Don't stage nil utxoDiffChild.

* [NOD-1518] Properly check the genesis hash in CalculatePastUTXOAndAcceptanceData.

* [NOD-1518] Explain why we break on current == nil in countSubtrees.

* [NOD-1518] Add a comment explaining why we check against StatusValid in resolveSyncState.

* [NOD-1535] Add external reachability tests

* [NOD-1535] Fix reachability tests and fix related bugs

* [NOD-1535] Add setters fox reindex slack and window

* [NOD-1535] Remove redundant line

* [NOD-1535] Add comment

* [NOD-1535] Fix comments

* [NOD-1535] Rename DBReader->DatabaseContext

* [NOD-1535] Check that reindex root is changed

* [NOD-1535] Fix calculateNewTips

Co-authored-by: Mike Zak <feanorr@gmail.com>
Co-authored-by: stasatdaglabs <stas@daglabs.com>
2020-11-17 16:00:16 +02:00

337 lines
10 KiB
Go

package consensus
import (
"github.com/kaspanet/kaspad/domain/consensus/processes/dagtraversalmanager"
"io/ioutil"
"math/rand"
"os"
"sync"
"github.com/kaspanet/kaspad/infrastructure/db/database/ldb"
consensusdatabase "github.com/kaspanet/kaspad/domain/consensus/database"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/acceptancedatastore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockheaderstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockrelationstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockstatusstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/blockstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/consensusstatestore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/ghostdagdatastore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/headertipsstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/multisetstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/pruningstore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/reachabilitydatastore"
"github.com/kaspanet/kaspad/domain/consensus/datastructures/utxodiffstore"
"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/processes/blockbuilder"
"github.com/kaspanet/kaspad/domain/consensus/processes/blockprocessor"
"github.com/kaspanet/kaspad/domain/consensus/processes/blockvalidator"
"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/difficultymanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/ghostdagmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/headertipsmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/mergedepthmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/pastmediantimemanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/pruningmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/reachabilitymanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/syncmanager"
"github.com/kaspanet/kaspad/domain/consensus/processes/transactionvalidator"
"github.com/kaspanet/kaspad/domain/dagconfig"
infrastructuredatabase "github.com/kaspanet/kaspad/infrastructure/db/database"
)
// Factory instantiates new Consensuses
type Factory interface {
NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (externalapi.Consensus, error)
NewTestConsensus(dagParams *dagconfig.Params, testName string) (tc testapi.TestConsensus, teardown func(), err error)
}
type factory struct{}
// NewFactory creates a new Consensus factory
func NewFactory() Factory {
return &factory{}
}
// NewConsensus instantiates a new Consensus
func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (externalapi.Consensus, error) {
// Data Structures
acceptanceDataStore := acceptancedatastore.New()
blockStore := blockstore.New()
blockHeaderStore := blockheaderstore.New()
blockRelationStore := blockrelationstore.New()
blockStatusStore := blockstatusstore.New()
multisetStore := multisetstore.New()
pruningStore := pruningstore.New()
reachabilityDataStore := reachabilitydatastore.New()
utxoDiffStore := utxodiffstore.New()
consensusStateStore := consensusstatestore.New()
ghostdagDataStore := ghostdagdatastore.New()
headerTipsStore := headertipsstore.New()
dbManager := consensusdatabase.New(db)
// Processes
reachabilityManager := reachabilitymanager.New(
dbManager,
ghostdagDataStore,
reachabilityDataStore)
dagTopologyManager := dagtopologymanager.New(
dbManager,
reachabilityManager,
blockRelationStore)
ghostdagManager := ghostdagmanager.New(
dbManager,
dagTopologyManager,
ghostdagDataStore,
model.KType(dagParams.K))
dagTraversalManager := dagtraversalmanager.New(
dbManager,
dagTopologyManager,
ghostdagDataStore,
ghostdagManager)
pastMedianTimeManager := pastmediantimemanager.New(
dagParams.TimestampDeviationTolerance,
dbManager,
dagTraversalManager,
blockHeaderStore,
ghostdagDataStore)
transactionValidator := transactionvalidator.New(dagParams.BlockCoinbaseMaturity,
dagParams.EnableNonNativeSubnetworks,
dbManager,
pastMedianTimeManager,
ghostdagDataStore)
difficultyManager := difficultymanager.New(
dbManager,
ghostdagManager,
ghostdagDataStore,
blockHeaderStore,
dagTopologyManager,
dagTraversalManager,
dagParams.PowMax,
dagParams.DifficultyAdjustmentWindowSize,
dagParams.TargetTimePerBlock)
coinbaseManager := coinbasemanager.New(
dbManager,
ghostdagDataStore,
acceptanceDataStore)
headerTipsManager := headertipsmanager.New(dbManager, dagTopologyManager, ghostdagManager, headerTipsStore)
genesisHash := dagParams.GenesisHash
mergeDepthManager := mergedepthmanager.New(
dagParams.FinalityDepth(),
dbManager,
dagTopologyManager,
dagTraversalManager,
ghostdagDataStore)
blockValidator := blockvalidator.New(
dagParams.PowMax,
false,
genesisHash,
dagParams.EnableNonNativeSubnetworks,
dagParams.DisableDifficultyAdjustment,
dagParams.DifficultyAdjustmentWindowSize,
dbManager,
difficultyManager,
pastMedianTimeManager,
transactionValidator,
ghostdagManager,
dagTopologyManager,
dagTraversalManager,
coinbaseManager,
mergeDepthManager,
blockStore,
ghostdagDataStore,
blockHeaderStore,
blockStatusStore,
)
consensusStateManager, err := consensusstatemanager.New(
dbManager,
dagParams.FinalityDepth(),
dagParams.PruningDepth(),
genesisHash,
ghostdagManager,
dagTopologyManager,
dagTraversalManager,
pastMedianTimeManager,
transactionValidator,
blockValidator,
reachabilityManager,
coinbaseManager,
mergeDepthManager,
blockStatusStore,
ghostdagDataStore,
consensusStateStore,
multisetStore,
blockStore,
utxoDiffStore,
blockRelationStore,
acceptanceDataStore,
blockHeaderStore,
headerTipsStore)
if err != nil {
return nil, err
}
pruningManager := pruningmanager.New(
dbManager,
dagTraversalManager,
dagTopologyManager,
consensusStateManager,
consensusStateStore,
ghostdagDataStore,
pruningStore,
blockStatusStore,
multisetStore,
acceptanceDataStore,
blockStore,
utxoDiffStore,
genesisHash,
dagParams.FinalityDepth(),
dagParams.PruningDepth())
syncManager := syncmanager.New(
dbManager,
genesisHash,
dagParams.TargetTimePerBlock.Milliseconds(),
dagTraversalManager,
dagTopologyManager,
ghostdagManager,
consensusStateManager,
ghostdagDataStore,
blockStatusStore,
blockHeaderStore,
headerTipsStore)
blockBuilder := blockbuilder.New(
dbManager,
difficultyManager,
pastMedianTimeManager,
coinbaseManager,
consensusStateManager,
ghostdagManager,
acceptanceDataStore,
blockRelationStore,
multisetStore,
ghostdagDataStore,
)
blockProcessor := blockprocessor.New(
dagParams,
dbManager,
consensusStateManager,
pruningManager,
blockValidator,
dagTopologyManager,
reachabilityManager,
difficultyManager,
pastMedianTimeManager,
ghostdagManager,
coinbaseManager,
headerTipsManager,
syncManager,
acceptanceDataStore,
blockStore,
blockStatusStore,
blockRelationStore,
multisetStore,
ghostdagDataStore,
consensusStateStore,
pruningStore,
reachabilityDataStore,
utxoDiffStore,
blockHeaderStore,
headerTipsStore)
c := &consensus{
lock: &sync.Mutex{},
databaseContext: dbManager,
blockProcessor: blockProcessor,
blockBuilder: blockBuilder,
consensusStateManager: consensusStateManager,
transactionValidator: transactionValidator,
syncManager: syncManager,
pastMedianTimeManager: pastMedianTimeManager,
blockValidator: blockValidator,
coinbaseManager: coinbaseManager,
dagTopologyManager: dagTopologyManager,
dagTraversalManager: dagTraversalManager,
difficultyManager: difficultyManager,
ghostdagManager: ghostdagManager,
headerTipsManager: headerTipsManager,
mergeDepthManager: mergeDepthManager,
pruningManager: pruningManager,
reachabilityManager: reachabilityManager,
blockStore: blockStore,
blockHeaderStore: blockHeaderStore,
pruningStore: pruningStore,
ghostdagDataStore: ghostdagDataStore,
blockStatusStore: blockStatusStore,
blockRelationStore: blockRelationStore,
consensusStateStore: consensusStateStore,
headerTipsStore: headerTipsStore,
multisetStore: multisetStore,
reachabilityDataStore: reachabilityDataStore,
}
genesisInfo, err := c.GetBlockInfo(genesisHash)
if err != nil {
return nil, err
}
if !genesisInfo.Exists {
err = c.ValidateAndInsertBlock(dagParams.GenesisBlock)
if err != nil {
return nil, err
}
}
return c, nil
}
func (f *factory) NewTestConsensus(dagParams *dagconfig.Params, testName string) (
tc testapi.TestConsensus, teardown func(), err error) {
testDatabaseDir, err := ioutil.TempDir("", testName)
if err != nil {
return nil, nil, err
}
db, err := ldb.NewLevelDB(testDatabaseDir)
if err != nil {
return nil, nil, err
}
consensusAsInterface, err := f.NewConsensus(dagParams, db)
if err != nil {
return nil, nil, err
}
consensusAsImplementation := consensusAsInterface.(*consensus)
testBlockBuilder := blockbuilder.NewTestBlockBuilder(consensusAsImplementation.blockBuilder)
testConsensusStateManager := consensusstatemanager.NewTestConsensusStateManager(consensusAsImplementation.consensusStateManager)
tc = &testConsensus{
rd: rand.New(rand.NewSource(0)),
consensus: consensusAsImplementation,
testBlockBuilder: testBlockBuilder,
testConsensusStateManager: testConsensusStateManager,
testReachabilityManager: reachabilitymanager.NewTestReachabilityManager(consensusAsImplementation.
reachabilityManager),
}
teardown = func() {
db.Close()
os.RemoveAll(testDatabaseDir)
}
return tc, teardown, nil
}