kaspad/domain/domain_test.go
Svarog c13a4d90ed
Mempool redesign (#1752)
* Added model and stubs for all main methods

* Add constructors to all main objects

* Implement BlockCandidateTransactions

* implement expireOldTransactions and expireOrphanTransactions

* Rename isHighPriority to neverExpires

* Add stub for checkDoubleSpends

* Revert "Rename isHighPriority to neverExpires"

This reverts commit b2da9a4a00c02fb380d2518cf54fa16257bd8423.

* Imeplement transactionsOrderedByFeeRate

* Orphan maps should be idToOrphan

* Add error.go to mempool

* Invert the condition for banning when mempool rejects a transaction

* Move all model objects to model package

* Implement getParentsInPool

* Implemented mempoolUTXOSet.addTransaction

* Implement removeTransaction, remove sanity checks

* Implemented mempoolUTXOSet.checkDoubleSpends

* Implemented removeOrphan

* Implement removeOrphan

* Implement maybeAddOrphan and AddOrphan

* Implemented processOrphansAfterAcceptedTransaction

* Implement transactionsPool.addTransaction

* Implement RemoveTransaction

* If a transaction was removed from the mempool - update it's redeemers in orphan pool as well

* Use maximumOrphanTransactionCount

* Add allowOrphans to ValidateAndInsertTransaction stub

* Implement validateTransaction functions

* Implement fillInputs

* Implement ValidateAndInsertTransaction

* Implement HandleNewBlockTransactions

* Implement missing mempool interface methods

* Add comments to exported functions

* Call ValidateTransactionInIsolation where needed

* Implement RevalidateHighPriorityTransactions

* Rewire kaspad to use new mempool, and fix compilation errors

* Update rebroadcast logic to use new structure

* Handle non-standard transaction errors properly

* Add mutex to mempool

* bugfix: GetTransaction panics when ok is false

* properly calculate targetBlocksPerSecond in config.go

* Fix various lint errors and tests

* Fix expected text in test for duplicate transactions

* Skip the coinbase transaction in HandleNewBlockTransactions

* Unorphan the correct transactions

* Call ValidateTransactionAndPopulateWithConsensusData on unorphanTransaction

* Re-apply policy_test as check_transactions_standard_test

* removeTransaction: Remove redeemers in orphan pool as well

* Remove redundant check for uint64 < 0

* Export and rename isDust -> IsTransactionOutputDust to allow usage by rothschild

* Add allowOrphan to SubmitTransaction RPC request

* Remove all implementation from mempool.go

* tidy go mod

* Don't pass acceptedOrphans to handleNewBlockTransactions

* Use t.Errorf in stead of t.Fatalf

* Remove minimum relay fee from TestDust, as it's no longer configurable

* Add separate VirtualDAASCore method for faster retrieval where it's repeated multiple times

* Broadcast all transactions that were accepted

* Don't re-use GetVirtualDAAScore in GetVirtualInfo - this causes a deadlock

* Use real transaction count, and not Orphan

* Get mempool config from outside, incorporating values received from cli

* Use MinRelayFee and MaxOrphanTxs from global kaspad config

* Add explanation for the seemingly redundant check for transaction version in checkTransactionStandard

* Update some comment

* Convert creation of acceptedTransactions to a single line

* Move mempoolUTXOSet out of checkDoubleSpends

* Add test for attempt to insert double spend into mempool

* fillInputs: Skip check for coinbase - it's always false in mempool

* Clarify comment about removeRedeemers when removing random orphan

* Don't remove high-priority transactions in limitTransactionCount

* Use mempool.removeTransaction in limitTransactionCount

* Add mutex comment to handleNewBlockTransactions

* Return error from limitTransactionCount

* Pluralize the map types

* mempoolUTXOSet.removeTransaction: Don't restore utxo if it was not created in mempool

* Don't evacuate from orphanPool high-priority transactions

* Disallow double-spends in orphan pool

* Don't use exported (and locking) methods from inside mempool

* Check for double spends in mempool during revalidateTransaction

* Add checkOrphanDuplicate

* Add orphan to acceptedOrphans, not current

* Add TestHighPriorityTransactions

* Fix off-by-one error in limitTransactionCount

* Add TestRevalidateHighPriorityTransactions

* Remove checkDoubleSpends from revalidateTransaction

* Fix TestRevalidateHighPriorityTransactions

* Move check for MaximumOrphanCount to beggining of maybeAddOrphan

* Rename all map type to singulateToSingularMap

* limitOrphanPool only after the orphan was added

* TestDoubleSpendInMempool: use createChildTxWhenParentTxWasAddedByConsensus instead of createTransactionWithUTXOEntry

* Fix some comments

* Have separate min/max transaction versions for mempool

* Add comment on defaultMaximumOrphanTransactionCount to keep it small as long as we have recursion

* Fix comment

* Rename: createChildTxWhenParentTxWasAddedByConsensus -> createChildTxWhereParentTxWasAddedByConsensus

* Handle error from createChildTxWhereParentTxWasAddedByConsensus

* Rename createChildTxWhereParentTxWasAddedByConsensus -> createChildAndParentTxsAndAddParentToConsensus

* Convert all MaximumXXX constants to uint64

* Add comment

* remove mutex comments
2021-06-23 15:49:20 +03:00

135 lines
3.8 KiB
Go

package domain_test
import (
"fmt"
"io/ioutil"
"os"
"strings"
"testing"
"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/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/testutils"
"github.com/kaspanet/kaspad/domain/miningmanager/mempool"
"github.com/kaspanet/kaspad/infrastructure/db/database/ldb"
)
func TestCreateStagingConsensus(t *testing.T) {
testutils.ForAllNets(t, true, func(t *testing.T, consensusConfig *consensus.Config) {
dataDir, err := ioutil.TempDir("", fmt.Sprintf("TestCreateStagingConsensus-%s", consensusConfig.Name))
if err != nil {
t.Fatalf("ioutil.TempDir: %+v", err)
}
defer os.RemoveAll(dataDir)
db, err := ldb.NewLevelDB(dataDir, 8)
if err != nil {
t.Fatalf("NewLevelDB: %+v", err)
}
domainInstance, err := domain.New(consensusConfig, mempool.DefaultConfig(&consensusConfig.Params), db)
if err != nil {
t.Fatalf("New: %+v", err)
}
err = domainInstance.InitStagingConsensus()
if err != nil {
t.Fatalf("InitStagingConsensus: %+v", err)
}
err = domainInstance.InitStagingConsensus()
if !strings.Contains(err.Error(), "cannot create staging consensus when a staging consensus already exists") {
t.Fatalf("unexpected error: %+v", err)
}
coinbaseData := &externalapi.DomainCoinbaseData{
ScriptPublicKey: &externalapi.ScriptPublicKey{},
ExtraData: []byte{},
}
block, err := domainInstance.StagingConsensus().BuildBlock(coinbaseData, nil)
if err != nil {
t.Fatalf("BuildBlock: %+v", err)
}
_, err = domainInstance.StagingConsensus().ValidateAndInsertBlock(block)
if err != nil {
t.Fatalf("ValidateAndInsertBlock: %+v", err)
}
blockHash := consensushashing.BlockHash(block)
blockInfo, err := domainInstance.StagingConsensus().GetBlockInfo(blockHash)
if err != nil {
t.Fatalf("GetBlockInfo: %+v", err)
}
if !blockInfo.Exists {
t.Fatalf("block not found on staging consensus")
}
blockInfo, err = domainInstance.Consensus().GetBlockInfo(blockHash)
if err != nil {
t.Fatalf("GetBlockInfo: %+v", err)
}
if blockInfo.Exists {
t.Fatalf("a block from staging consensus was found on consensus")
}
err = domainInstance.CommitStagingConsensus()
if err != nil {
t.Fatalf("CommitStagingConsensus: %+v", err)
}
blockInfo, err = domainInstance.Consensus().GetBlockInfo(blockHash)
if err != nil {
t.Fatalf("GetBlockInfo: %+v", err)
}
if !blockInfo.Exists {
t.Fatalf("a block from staging consensus was not found on consensus after commit")
}
// Now we create a new staging consensus and check that it's deleted once we init a new domain. We also
// validate that the main consensus persisted the data from the committed temp consensus.
err = domainInstance.InitStagingConsensus()
if err != nil {
t.Fatalf("InitStagingConsensus: %+v", err)
}
_, err = domainInstance.StagingConsensus().ValidateAndInsertBlock(block)
if err != nil {
t.Fatalf("ValidateAndInsertBlock: %+v", err)
}
domainInstance2, err := domain.New(consensusConfig, mempool.DefaultConfig(&consensusConfig.Params), db)
if err != nil {
t.Fatalf("New: %+v", err)
}
blockInfo, err = domainInstance2.Consensus().GetBlockInfo(blockHash)
if err != nil {
t.Fatalf("GetBlockInfo: %+v", err)
}
if !blockInfo.Exists {
t.Fatalf("a block from committed staging consensus was not persisted to the active consensus")
}
err = domainInstance2.InitStagingConsensus()
if err != nil {
t.Fatalf("InitStagingConsensus: %+v", err)
}
blockInfo, err = domainInstance2.StagingConsensus().GetBlockInfo(blockHash)
if err != nil {
t.Fatalf("GetBlockInfo: %+v", err)
}
if blockInfo.Exists {
t.Fatalf("block from previous temp consensus shouldn't be found on a fresh temp consensus")
}
})
}