[NOD-1551] Requirements for performance tests (#1154)

* [NOD-1551] Add NewTestConsensusWithDataDir to factory

* [NOD-1551] Cache transaction ID

* [NOD-1551] Should return err if err != nil

* [NOD-1551] BuildBlockWithParents returns the blocks pastUTXOData

* [NOD-1551] Set BlockCoinbaseMaturity to 0 in TestDoubleSpends

* [NOD-1551] Fix comments

* --amend

Co-authored-by: Ori Newman <orinewman1@gmail.com>
This commit is contained in:
Svarog 2020-11-26 12:12:01 +02:00 committed by GitHub
parent 546ea83123
commit f7fa823f17
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 65 additions and 37 deletions

View File

@ -1,13 +1,14 @@
package consensus package consensus
import ( import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors" "github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization" "github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils" "github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig" "github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/pkg/errors" "github.com/pkg/errors"
"testing"
) )
func TestConsensus_GetBlockInfo(t *testing.T) { func TestConsensus_GetBlockInfo(t *testing.T) {
@ -20,7 +21,7 @@ func TestConsensus_GetBlockInfo(t *testing.T) {
} }
defer teardown() defer teardown()
invalidBlock, err := consensus.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil) invalidBlock, _, err := consensus.BuildBlockWithParents([]*externalapi.DomainHash{params.GenesisHash}, nil, nil)
if err != nil { if err != nil {
t.Fatal(err) t.Fatal(err)
} }

View File

@ -48,6 +48,8 @@ import (
type Factory interface { type Factory interface {
NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (externalapi.Consensus, error) NewConsensus(dagParams *dagconfig.Params, db infrastructuredatabase.Database) (externalapi.Consensus, error)
NewTestConsensus(dagParams *dagconfig.Params, testName string) (tc testapi.TestConsensus, teardown func(), err error) NewTestConsensus(dagParams *dagconfig.Params, testName string) (tc testapi.TestConsensus, teardown func(), err error)
NewTestConsensusWithDataDir(dagParams *dagconfig.Params, dataDir string) (
tc testapi.TestConsensus, teardown func(), err error)
} }
type factory struct{} type factory struct{}
@ -312,11 +314,18 @@ func (f *factory) NewConsensus(dagParams *dagconfig.Params, db infrastructuredat
func (f *factory) NewTestConsensus(dagParams *dagconfig.Params, testName string) ( func (f *factory) NewTestConsensus(dagParams *dagconfig.Params, testName string) (
tc testapi.TestConsensus, teardown func(), err error) { tc testapi.TestConsensus, teardown func(), err error) {
testDatabaseDir, err := ioutil.TempDir("", testName) dataDir, err := ioutil.TempDir("", testName)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
db, err := ldb.NewLevelDB(testDatabaseDir)
return f.NewTestConsensusWithDataDir(dagParams, dataDir)
}
func (f *factory) NewTestConsensusWithDataDir(dagParams *dagconfig.Params, dataDir string) (
tc testapi.TestConsensus, teardown func(), err error) {
db, err := ldb.NewLevelDB(dataDir)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -338,7 +347,7 @@ func (f *factory) NewTestConsensus(dagParams *dagconfig.Params, testName string)
tstConsensus.testBlockBuilder = blockbuilder.NewTestBlockBuilder(consensusAsImplementation.blockBuilder, tstConsensus) tstConsensus.testBlockBuilder = blockbuilder.NewTestBlockBuilder(consensusAsImplementation.blockBuilder, tstConsensus)
teardown = func() { teardown = func() {
db.Close() db.Close()
os.RemoveAll(testDatabaseDir) os.RemoveAll(dataDir)
} }
return tstConsensus, teardown, nil return tstConsensus, teardown, nil

View File

@ -27,7 +27,7 @@ func TestFinality(t *testing.T) {
defer teardown() defer teardown()
buildAndInsertBlock := func(parentHashes []*externalapi.DomainHash) (*externalapi.DomainBlock, error) { buildAndInsertBlock := func(parentHashes []*externalapi.DomainHash) (*externalapi.DomainBlock, error) {
block, err := consensus.BuildBlockWithParents(parentHashes, nil, nil) block, _, err := consensus.BuildBlockWithParents(parentHashes, nil, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -184,7 +184,7 @@ func TestBoundedMergeDepth(t *testing.T) {
} }
checkViolatingMergeDepth := func(consensus testapi.TestConsensus, parents []*externalapi.DomainHash) (*externalapi.DomainBlock, bool) { checkViolatingMergeDepth := func(consensus testapi.TestConsensus, parents []*externalapi.DomainHash) (*externalapi.DomainBlock, bool) {
block, err := consensus.BuildBlockWithParents(parents, nil, nil) block, _, err := consensus.BuildBlockWithParents(parents, nil, nil)
if err != nil { if err != nil {
t.Fatalf("TestBoundedMergeDepth: BuildBlockWithParents failed: %v", err) t.Fatalf("TestBoundedMergeDepth: BuildBlockWithParents failed: %v", err)
return nil, false // fo some reason go doesn't recognize that t.Fatalf never returns return nil, false // fo some reason go doesn't recognize that t.Fatalf never returns
@ -210,7 +210,7 @@ func TestBoundedMergeDepth(t *testing.T) {
} }
buildAndInsertBlock := func(consensus testapi.TestConsensus, parentHashes []*externalapi.DomainHash) *externalapi.DomainBlock { buildAndInsertBlock := func(consensus testapi.TestConsensus, parentHashes []*externalapi.DomainHash) *externalapi.DomainBlock {
block, err := consensus.BuildBlockWithParents(parentHashes, nil, nil) block, _, err := consensus.BuildBlockWithParents(parentHashes, nil, nil)
if err != nil { if err != nil {
t.Fatalf("TestBoundedMergeDepth: Failed building block: %v", err) t.Fatalf("TestBoundedMergeDepth: Failed building block: %v", err)
} }

View File

@ -17,6 +17,10 @@ type DomainTransaction struct {
Fee uint64 Fee uint64
Mass uint64 Mass uint64
// ID is a field that is used to cache the transaction ID.
// Always use consensusserialization.TransactionID instead of accessing this field directly
ID *DomainTransactionID
} }
// Clone returns a clone of DomainTransaction // Clone returns a clone of DomainTransaction

View File

@ -10,6 +10,9 @@ type BlockBuilder interface {
// TestBlockBuilder adds to the main BlockBuilder methods required by tests // TestBlockBuilder adds to the main BlockBuilder methods required by tests
type TestBlockBuilder interface { type TestBlockBuilder interface {
BlockBuilder BlockBuilder
// BuildBlockWithParents builds a block with provided parents, coinbaseData and transactions,
// and returns the block together with its past UTXO-diff from the virtual.
BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData,
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error) transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, *UTXODiff, error)
} }

View File

@ -11,8 +11,7 @@ type TestConsensus interface {
DatabaseContext() model.DBReader DatabaseContext() model.DBReader
BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, *model.UTXODiff, error)
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error)
// AddBlock builds a block with given information, solves it, and adds to the DAG. // AddBlock builds a block with given information, solves it, and adds to the DAG.
// Returns the hash of the added block // Returns the hash of the added block

View File

@ -27,8 +27,11 @@ func NewTestBlockBuilder(baseBlockBuilder model.BlockBuilder, testConsensus test
} }
} }
func (bb *testBlockBuilder) BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, // BuildBlockWithParents builds a block with provided parents, coinbaseData and transactions,
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error) { // and returns the block together with its past UTXO-diff from the virtual.
func (bb *testBlockBuilder) BuildBlockWithParents(parentHashes []*externalapi.DomainHash,
coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) (
*externalapi.DomainBlock, *model.UTXODiff, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "BuildBlockWithParents") onEnd := logger.LogAndMeasureExecutionTime(log, "BuildBlockWithParents")
defer onEnd() defer onEnd()
@ -69,9 +72,7 @@ func (bb *testBlockBuilder) buildHeaderWithParents(parentHashes []*externalapi.D
}, nil }, nil
} }
func (bb *testBlockBuilder) buildBlockWithParents( func (bb *testBlockBuilder) buildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, *model.UTXODiff, error) {
parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData,
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error) {
defer bb.testConsensus.DiscardAllStores() defer bb.testConsensus.DiscardAllStores()
@ -87,43 +88,43 @@ func (bb *testBlockBuilder) buildBlockWithParents(
err := bb.ghostdagManager.GHOSTDAG(tempBlockHash) err := bb.ghostdagManager.GHOSTDAG(tempBlockHash)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
ghostdagData, err := bb.ghostdagDataStore.Get(bb.databaseContext, tempBlockHash) ghostdagData, err := bb.ghostdagDataStore.Get(bb.databaseContext, tempBlockHash)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent) selectedParentStatus, err := bb.testConsensus.ConsensusStateManager().ResolveBlockStatus(ghostdagData.SelectedParent)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
if selectedParentStatus == externalapi.StatusDisqualifiedFromChain { if selectedParentStatus == externalapi.StatusDisqualifiedFromChain {
return nil, errors.Errorf("Error building block with selectedParent %s with status DisqualifiedFromChain", return nil, nil, errors.Errorf("Error building block with selectedParent %s with status DisqualifiedFromChain",
ghostdagData.SelectedParent) ghostdagData.SelectedParent)
} }
_, acceptanceData, multiset, err := bb.consensusStateManager.CalculatePastUTXOAndAcceptanceData(tempBlockHash) pastUTXO, acceptanceData, multiset, err := bb.consensusStateManager.CalculatePastUTXOAndAcceptanceData(tempBlockHash)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
bb.acceptanceDataStore.Stage(tempBlockHash, acceptanceData) bb.acceptanceDataStore.Stage(tempBlockHash, acceptanceData)
coinbase, err := bb.coinbaseManager.ExpectedCoinbaseTransaction(tempBlockHash, coinbaseData) coinbase, err := bb.coinbaseManager.ExpectedCoinbaseTransaction(tempBlockHash, coinbaseData)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
transactionsWithCoinbase := append([]*externalapi.DomainTransaction{coinbase}, transactions...) transactionsWithCoinbase := append([]*externalapi.DomainTransaction{coinbase}, transactions...)
header, err := bb.buildHeaderWithParents(parentHashes, transactionsWithCoinbase, acceptanceData, multiset) header, err := bb.buildHeaderWithParents(parentHashes, transactionsWithCoinbase, acceptanceData, multiset)
if err != nil { if err != nil {
return nil, err return nil, nil, err
} }
return &externalapi.DomainBlock{ return &externalapi.DomainBlock{
Header: header, Header: header,
Transactions: transactionsWithCoinbase, Transactions: transactionsWithCoinbase,
}, nil }, pastUTXO, nil
} }

View File

@ -2,6 +2,8 @@ package blockvalidator_test
import ( import (
"errors" "errors"
"testing"
"github.com/kaspanet/kaspad/domain/consensus" "github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model" "github.com/kaspanet/kaspad/domain/consensus/model"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
@ -9,7 +11,6 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization" "github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils" "github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig" "github.com/kaspanet/kaspad/domain/dagconfig"
"testing"
) )
func TestValidateMedianTime(t *testing.T) { func TestValidateMedianTime(t *testing.T) {
@ -22,7 +23,7 @@ func TestValidateMedianTime(t *testing.T) {
defer teardown() defer teardown()
addBlock := func(blockTime int64, parents []*externalapi.DomainHash, expectedErr error) (*externalapi.DomainBlock, *externalapi.DomainHash) { addBlock := func(blockTime int64, parents []*externalapi.DomainHash, expectedErr error) (*externalapi.DomainBlock, *externalapi.DomainHash) {
block, err := tc.BuildBlockWithParents(parents, nil, nil) block, _, err := tc.BuildBlockWithParents(parents, nil, nil)
if err != nil { if err != nil {
t.Fatalf("BuildBlockWithParents: %+v", err) t.Fatalf("BuildBlockWithParents: %+v", err)
} }

View File

@ -17,6 +17,8 @@ import (
func TestDoubleSpends(t *testing.T) { func TestDoubleSpends(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) { testutils.ForAllNets(t, true, func(t *testing.T, params *dagconfig.Params) {
params.BlockCoinbaseMaturity = 0
factory := consensus.NewFactory() factory := consensus.NewFactory()
consensus, teardown, err := factory.NewTestConsensus(params, "TestUTXOCommitment") consensus, teardown, err := factory.NewTestConsensus(params, "TestUTXOCommitment")

View File

@ -1,12 +1,13 @@
package pastmediantimemanager_test package pastmediantimemanager_test
import ( import (
"testing"
"github.com/kaspanet/kaspad/domain/consensus" "github.com/kaspanet/kaspad/domain/consensus"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization" "github.com/kaspanet/kaspad/domain/consensus/utils/consensusserialization"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils" "github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/dagconfig" "github.com/kaspanet/kaspad/domain/dagconfig"
"testing"
) )
func TestPastMedianTime(t *testing.T) { func TestPastMedianTime(t *testing.T) {
@ -24,7 +25,7 @@ func TestPastMedianTime(t *testing.T) {
blockTime := params.GenesisBlock.Header.TimeInMilliseconds blockTime := params.GenesisBlock.Header.TimeInMilliseconds
for i := uint32(1); i < numBlocks; i++ { for i := uint32(1); i < numBlocks; i++ {
blockTime += 1000 blockTime += 1000
block, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{blockHashes[i-1]}, nil, nil) block, _, err := tc.BuildBlockWithParents([]*externalapi.DomainHash{blockHashes[i-1]}, nil, nil)
if err != nil { if err != nil {
t.Fatalf("BuildBlockWithParents: %s", err) t.Fatalf("BuildBlockWithParents: %s", err)
} }

View File

@ -18,24 +18,24 @@ func (v *transactionValidator) ValidateTransactionInContextAndPopulateMassAndFee
err := v.checkTransactionCoinbaseMaturity(povBlockHash, tx) err := v.checkTransactionCoinbaseMaturity(povBlockHash, tx)
if err != nil { if err != nil {
return nil return err
} }
totalSompiIn, err := v.checkTransactionInputAmounts(tx) totalSompiIn, err := v.checkTransactionInputAmounts(tx)
if err != nil { if err != nil {
return nil return err
} }
totalSompiOut, err := v.checkTransactionOutputAmounts(tx, totalSompiIn) totalSompiOut, err := v.checkTransactionOutputAmounts(tx, totalSompiIn)
if err != nil { if err != nil {
return nil return err
} }
tx.Fee = totalSompiIn - totalSompiOut tx.Fee = totalSompiIn - totalSompiOut
err = v.checkTransactionSequenceLock(povBlockHash, tx, selectedParentMedianTime) err = v.checkTransactionSequenceLock(povBlockHash, tx, selectedParentMedianTime)
if err != nil { if err != nil {
return nil return err
} }
err = v.validateTransactionScripts(tx) err = v.validateTransactionScripts(tx)

View File

@ -14,8 +14,7 @@ type testConsensus struct {
testConsensusStateManager model.TestConsensusStateManager testConsensusStateManager model.TestConsensusStateManager
} }
func (tc *testConsensus) BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, func (tc *testConsensus) BuildBlockWithParents(parentHashes []*externalapi.DomainHash, coinbaseData *externalapi.DomainCoinbaseData, transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, *model.UTXODiff, error) {
transactions []*externalapi.DomainTransaction) (*externalapi.DomainBlock, error) {
// Require write lock because BuildBlockWithParents stages temporary data // Require write lock because BuildBlockWithParents stages temporary data
tc.lock.Lock() tc.lock.Lock()
@ -31,7 +30,7 @@ func (tc *testConsensus) AddBlock(parentHashes []*externalapi.DomainHash, coinba
tc.lock.Lock() tc.lock.Lock()
defer tc.lock.Unlock() defer tc.lock.Unlock()
block, err := tc.testBlockBuilder.BuildBlockWithParents(parentHashes, coinbaseData, transactions) block, _, err := tc.testBlockBuilder.BuildBlockWithParents(parentHashes, coinbaseData, transactions)
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -65,6 +65,12 @@ func TransactionHash(tx *externalapi.DomainTransaction) *externalapi.DomainHash
// TransactionID generates the Hash for the transaction without the signature script and payload field. // TransactionID generates the Hash for the transaction without the signature script and payload field.
func TransactionID(tx *externalapi.DomainTransaction) *externalapi.DomainTransactionID { func TransactionID(tx *externalapi.DomainTransaction) *externalapi.DomainTransactionID {
// If transaction ID is already cached, return it
if tx.ID != nil {
return tx.ID
}
// Encode the transaction, replace signature script with zeroes, cut off // Encode the transaction, replace signature script with zeroes, cut off
// payload and calculate double sha256 on the result. // payload and calculate double sha256 on the result.
var encodingFlags txEncoding var encodingFlags txEncoding
@ -80,7 +86,9 @@ func TransactionID(tx *externalapi.DomainTransaction) *externalapi.DomainTransac
} }
transactionID := externalapi.DomainTransactionID(*writer.Finalize()) transactionID := externalapi.DomainTransactionID(*writer.Finalize())
return &transactionID tx.ID = &transactionID
return tx.ID
} }
func serializeTransaction(w io.Writer, tx *externalapi.DomainTransaction, encodingFlags txEncoding) error { func serializeTransaction(w io.Writer, tx *externalapi.DomainTransaction, encodingFlags txEncoding) error {