mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-03-30 15:08:33 +00:00
[NOD-1529] Add getters + AddBlock to TestConsensus (#1025)
* [NOD-1529] Add all stores and processes to consensus, and add access to TestConsensus * [NOD-1529] Move the getters of TestConsensus to separate file * [NOD-1529] Add AddBlock to TestConsensus * [NOD-1529] Update NewTestConsensus to be more all-encompassing * [NOD-1529] Remove test directory in teardown * [NOD-1529] Add ForAllNets function * [NOD-1529] Add comment
This commit is contained in:
parent
4736213ba4
commit
135ffbd4f2
@ -19,12 +19,28 @@ type consensus struct {
|
||||
transactionValidator model.TransactionValidator
|
||||
syncManager model.SyncManager
|
||||
pastMedianTimeManager model.PastMedianTimeManager
|
||||
blockValidator model.BlockValidator
|
||||
coinbaseManager model.CoinbaseManager
|
||||
dagTopologyManager model.DAGTopologyManager
|
||||
dagTraversalManager model.DAGTraversalManager
|
||||
difficultyManager model.DifficultyManager
|
||||
ghostdagManager model.GHOSTDAGManager
|
||||
headerTipsManager model.HeaderTipsManager
|
||||
mergeDepthManager model.MergeDepthManager
|
||||
pruningManager model.PruningManager
|
||||
reachabilityManager model.ReachabilityManager
|
||||
|
||||
blockStore model.BlockStore
|
||||
blockHeaderStore model.BlockHeaderStore
|
||||
pruningStore model.PruningStore
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
blockStatusStore model.BlockStatusStore
|
||||
blockStore model.BlockStore
|
||||
blockHeaderStore model.BlockHeaderStore
|
||||
pruningStore model.PruningStore
|
||||
ghostdagDataStore model.GHOSTDAGDataStore
|
||||
blockRelationStore model.BlockRelationStore
|
||||
blockStatusStore model.BlockStatusStore
|
||||
consensusStateStore model.ConsensusStateStore
|
||||
headerTipsStore model.HeaderTipsStore
|
||||
multisetStore model.MultisetStore
|
||||
reachabilityDataStore model.ReachabilityDataStore
|
||||
utxoDiffStore model.UTXODiffStore
|
||||
}
|
||||
|
||||
// BuildBlock builds a block over the current state, with the transactions
|
||||
|
@ -1,8 +1,12 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"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"
|
||||
@ -42,7 +46,7 @@ import (
|
||||
// Factory instantiates new Consensuses
|
||||
type Factory interface {
|
||||
NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (externalapi.Consensus, error)
|
||||
NewTestConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (testapi.TestConsensus, error)
|
||||
NewTestConsensus(dagParams *dagconfig.Params, testName string) (tc testapi.TestConsensus, teardown func(), err error)
|
||||
}
|
||||
|
||||
type factory struct{}
|
||||
@ -255,12 +259,27 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
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,
|
||||
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)
|
||||
@ -278,18 +297,32 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
|
||||
return c, nil
|
||||
}
|
||||
|
||||
func (f *factory) NewTestConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (
|
||||
testapi.TestConsensus, error) {
|
||||
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, err
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
consensusAsImplementation := consensusAsInterface.(*consensus)
|
||||
|
||||
return &testConsensus{
|
||||
tc = &testConsensus{
|
||||
consensus: consensusAsImplementation,
|
||||
testBlockBuilder: blockbuilder.NewTestBlockBuilder(consensusAsImplementation.blockBuilder),
|
||||
}, nil
|
||||
}
|
||||
teardown = func() {
|
||||
db.Close()
|
||||
os.RemoveAll(testDatabaseDir)
|
||||
}
|
||||
|
||||
return tc, teardown, nil
|
||||
}
|
||||
|
@ -1,6 +1,9 @@
|
||||
package testapi
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
)
|
||||
|
||||
// TestConsensus wraps the Consensus interface with some methods that are needed by tests only
|
||||
type TestConsensus interface {
|
||||
@ -8,4 +11,39 @@ type TestConsensus interface {
|
||||
|
||||
BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData,
|
||||
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error)
|
||||
|
||||
// AddBlock builds a block with given information, solves it, and adds to the DAG.
|
||||
// Returns the hash of the added block
|
||||
AddBlock(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData,
|
||||
transactions []*externalapi.DomainTransaction) (*externalapi.DomainHash, error)
|
||||
|
||||
AcceptanceDataStore() model.AcceptanceDataStore
|
||||
BlockHeaderStore() model.BlockHeaderStore
|
||||
BlockRelationStore() model.BlockRelationStore
|
||||
BlockStatusStore() model.BlockStatusStore
|
||||
BlockStore() model.BlockStore
|
||||
ConsensusStateStore() model.ConsensusStateStore
|
||||
GHOSTDAGDataStore() model.GHOSTDAGDataStore
|
||||
HeaderTipsStore() model.HeaderTipsStore
|
||||
MultisetStore() model.MultisetStore
|
||||
PruningStore() model.PruningStore
|
||||
ReachabilityDataStore() model.ReachabilityDataStore
|
||||
UTXODiffStore() model.UTXODiffStore
|
||||
|
||||
BlockBuilder() model.BlockBuilder
|
||||
BlockProcessor() model.BlockProcessor
|
||||
BlockValidator() model.BlockValidator
|
||||
CoinbaseManager() model.CoinbaseManager
|
||||
ConsensusStateManager() model.ConsensusStateManager
|
||||
DAGTopologyManager() model.DAGTopologyManager
|
||||
DAGTraversalManager() model.DAGTraversalManager
|
||||
DifficultyManager() model.DifficultyManager
|
||||
GHOSTDAGManager() model.GHOSTDAGManager
|
||||
HeaderTipsManager() model.HeaderTipsManager
|
||||
MergeDepthManager() model.MergeDepthManager
|
||||
PastMedianTimeManager() model.PastMedianTimeManager
|
||||
PruningManager() model.PruningManager
|
||||
ReachabilityManager() model.ReachabilityManager
|
||||
SyncManager() model.SyncManager
|
||||
TransactionValidator() model.TransactionValidator
|
||||
}
|
||||
|
@ -1,8 +1,14 @@
|
||||
package consensus
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"math"
|
||||
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization"
|
||||
"github.com/kaspanet/kaspad/domain/consensus/utils/hashes"
|
||||
"github.com/kaspanet/kaspad/util"
|
||||
)
|
||||
|
||||
type testConsensus struct {
|
||||
@ -19,3 +25,39 @@ func (tc *testConsensus) BuildBlockWithParents(parentHashes []*externalapi.Domai
|
||||
|
||||
return tc.testBlockBuilder.BuildBlockWithParents(parentHashes, coinbaseData, transactions)
|
||||
}
|
||||
|
||||
func (tc *testConsensus) AddBlock(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData,
|
||||
transactions []*externalapi.DomainTransaction) (*externalapi.DomainHash, error) {
|
||||
|
||||
// Require write lock because BuildBlockWithParents stages temporary data
|
||||
tc.lock.Lock()
|
||||
defer tc.lock.Unlock()
|
||||
|
||||
block, err := tc.testBlockBuilder.BuildBlockWithParents(parentHashes, coinbaseData, transactions)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
solveBlock(block)
|
||||
|
||||
err = tc.ValidateAndInsertBlock(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return consensusserialization.BlockHash(block), nil
|
||||
}
|
||||
|
||||
func solveBlock(block *externalapi.DomainBlock) {
|
||||
targetDifficulty := util.CompactToBig(block.Header.Bits)
|
||||
|
||||
for i := uint64(0); i < math.MaxUint64; i++ {
|
||||
block.Header.Nonce = i
|
||||
hash := consensusserialization.BlockHash(block)
|
||||
if hashes.ToBig(hash).Cmp(targetDifficulty) <= 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
panic(errors.New("went over all the nonce space and couldn't find a single one that gives a valid block"))
|
||||
}
|
||||
|
115
domain/consensus/test_consensus_getters.go
Normal file
115
domain/consensus/test_consensus_getters.go
Normal file
@ -0,0 +1,115 @@
|
||||
package consensus
|
||||
|
||||
import "github.com/kaspanet/kaspad/domain/consensus/model"
|
||||
|
||||
func (tc *testConsensus) AcceptanceDataStore() model.AcceptanceDataStore {
|
||||
return tc.AcceptanceDataStore()
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockHeaderStore() model.BlockHeaderStore {
|
||||
return tc.blockHeaderStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockRelationStore() model.BlockRelationStore {
|
||||
return tc.blockRelationStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockStatusStore() model.BlockStatusStore {
|
||||
return tc.blockStatusStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockStore() model.BlockStore {
|
||||
return tc.blockStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) ConsensusStateStore() model.ConsensusStateStore {
|
||||
return tc.consensusStateStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) GHOSTDAGDataStore() model.GHOSTDAGDataStore {
|
||||
return tc.ghostdagDataStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) HeaderTipsStore() model.HeaderTipsStore {
|
||||
return tc.headerTipsStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) MultisetStore() model.MultisetStore {
|
||||
return tc.multisetStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) PruningStore() model.PruningStore {
|
||||
return tc.pruningStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) ReachabilityDataStore() model.ReachabilityDataStore {
|
||||
return tc.reachabilityDataStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) UTXODiffStore() model.UTXODiffStore {
|
||||
return tc.utxoDiffStore
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockBuilder() model.BlockBuilder {
|
||||
return tc.blockBuilder
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockProcessor() model.BlockProcessor {
|
||||
return tc.blockProcessor
|
||||
}
|
||||
|
||||
func (tc *testConsensus) BlockValidator() model.BlockValidator {
|
||||
return tc.blockValidator
|
||||
}
|
||||
|
||||
func (tc *testConsensus) CoinbaseManager() model.CoinbaseManager {
|
||||
return tc.coinbaseManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) ConsensusStateManager() model.ConsensusStateManager {
|
||||
return tc.consensusStateManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) DAGTopologyManager() model.DAGTopologyManager {
|
||||
return tc.dagTopologyManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) DAGTraversalManager() model.DAGTraversalManager {
|
||||
return tc.dagTraversalManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) DifficultyManager() model.DifficultyManager {
|
||||
return tc.difficultyManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) GHOSTDAGManager() model.GHOSTDAGManager {
|
||||
return tc.ghostdagManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) HeaderTipsManager() model.HeaderTipsManager {
|
||||
return tc.headerTipsManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) MergeDepthManager() model.MergeDepthManager {
|
||||
return tc.mergeDepthManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) PastMedianTimeManager() model.PastMedianTimeManager {
|
||||
return tc.pastMedianTimeManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) PruningManager() model.PruningManager {
|
||||
return tc.pruningManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) ReachabilityManager() model.ReachabilityManager {
|
||||
return tc.reachabilityManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) SyncManager() model.SyncManager {
|
||||
return tc.syncManager
|
||||
}
|
||||
|
||||
func (tc *testConsensus) TransactionValidator() model.TransactionValidator {
|
||||
return tc.transactionValidator
|
||||
}
|
27
domain/consensus/utils/testutils/for_all_nets.go
Normal file
27
domain/consensus/utils/testutils/for_all_nets.go
Normal file
@ -0,0 +1,27 @@
|
||||
package testutils
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"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, setDifficultyToMinimum bool, testFunc func(*testing.T, *dagconfig.Params)) {
|
||||
allParams := []dagconfig.Params{
|
||||
dagconfig.MainnetParams,
|
||||
dagconfig.TestnetParams,
|
||||
dagconfig.SimnetParams,
|
||||
dagconfig.DevnetParams,
|
||||
}
|
||||
|
||||
for _, params := range allParams {
|
||||
if setDifficultyToMinimum {
|
||||
params.DisableDifficultyAdjustment = dagconfig.SimnetParams.DisableDifficultyAdjustment
|
||||
params.TargetTimePerBlock = dagconfig.SimnetParams.TargetTimePerBlock
|
||||
}
|
||||
|
||||
testFunc(t, ¶ms)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user