fix mempool accessing, rewrite get_mempool_entries_by_addresses

This commit is contained in:
D-Stacks 2022-07-02 11:28:22 +02:00
parent c5aade7e7f
commit 40a10edbb7
12 changed files with 282 additions and 154 deletions

View File

@ -1,14 +1,9 @@
package rpchandlers
import (
"errors"
"github.com/kaspanet/kaspad/app/appmessage"
"github.com/kaspanet/kaspad/app/rpc/rpccontext"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/infrastructure/network/netadapter/router"
"github.com/kaspanet/kaspad/util"
)
@ -20,128 +15,77 @@ func HandleGetMempoolEntriesByAddresses(context *rpccontext.Context, _ *router.R
mempoolEntriesByAddresses := make([]*appmessage.MempoolEntryByAddress, 0)
if !getMempoolEntriesByAddressesRequest.FilterTransactionPool {
transactionPoolTransactions := context.Domain.MiningManager().AllTransactions()
transactionPoolEntriesByAddresses, err := extractMempoolEntriesByAddressesFromTransactions(
context,
getMempoolEntriesByAddressesRequest.Addresses,
transactionPoolTransactions,
false,
)
for _, addressString := range getMempoolEntriesByAddressesRequest.Addresses {
address, err := util.DecodeAddress(addressString, context.Config.NetParams().Prefix)
if err != nil {
rpcError := &appmessage.RPCError{}
if !errors.As(err, &rpcError) {
return nil, err
}
errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{}
errorMessage.Error = rpcError
errorMessage := &appmessage.GetMempoolEntriesByAddressesResponseMessage{}
errorMessage.Error = appmessage.RPCErrorf("Could not decode address '%s': %s", addressString, err)
return errorMessage, nil
}
mempoolEntriesByAddresses = append(mempoolEntriesByAddresses, transactionPoolEntriesByAddresses...)
}
if getMempoolEntriesByAddressesRequest.IncludeOrphanPool {
orphanPoolTransactions := context.Domain.MiningManager().AllOrphanTransactions()
orphanPoolEntriesByAddresse, err := extractMempoolEntriesByAddressesFromTransactions(
context,
getMempoolEntriesByAddressesRequest.Addresses,
orphanPoolTransactions,
true,
)
if err != nil {
rpcError := &appmessage.RPCError{}
if !errors.As(err, &rpcError) {
return nil, err
}
errorMessage := &appmessage.GetUTXOsByAddressesResponseMessage{}
errorMessage.Error = rpcError
return errorMessage, nil
}
mempoolEntriesByAddresses = append(mempoolEntriesByAddresses, orphanPoolEntriesByAddresse...)
}
return appmessage.NewGetMempoolEntriesByAddressesResponseMessage(mempoolEntriesByAddresses), nil
}
//TO DO: optimize extractMempoolEntriesByAddressesFromTransactions
func extractMempoolEntriesByAddressesFromTransactions(context *rpccontext.Context, addresses []string, transactions []*externalapi.DomainTransaction, areOrphans bool) ([]*appmessage.MempoolEntryByAddress, error) {
mempoolEntriesByAddresses := make([]*appmessage.MempoolEntryByAddress, 0)
for _, addressString := range addresses {
_, err := util.DecodeAddress(addressString, context.Config.ActiveNetParams.Prefix)
if err != nil {
return nil, appmessage.RPCErrorf("Could not decode address '%s': %s", addressString, err)
}
sending := make([]*appmessage.MempoolEntry, 0)
receiving := make([]*appmessage.MempoolEntry, 0)
for _, transaction := range transactions {
if !getMempoolEntriesByAddressesRequest.FilterTransactionPool {
for i, input := range transaction.Inputs {
// TODO: Fix this
if input.UTXOEntry == nil {
log.Errorf("Couldn't find UTXO entry for input %d in mempool transaction %s. This is a bug and should be fixed.", i, consensushashing.TransactionID(transaction))
continue
}
_, transactionSendingAddress, err := txscript.ExtractScriptPubKeyAddress(
input.UTXOEntry.ScriptPublicKey(),
context.Config.ActiveNetParams)
if err != nil {
return nil, err
}
if addressString == transactionSendingAddress.String() {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
sending = append(
sending,
&appmessage.MempoolEntry{
Fee: transaction.Fee,
Transaction: rpcTransaction,
IsOrphan: areOrphans,
},
)
break //one input is enough
}
sendingInMempool, receivingInMempool, err := context.Domain.MiningManager().GetTransactionsByAddresses()
if err != nil {
return nil, err
}
for _, output := range transaction.Outputs {
_, transactionReceivingAddress, err := txscript.ExtractScriptPubKeyAddress(
output.ScriptPublicKey,
context.Config.ActiveNetParams,
)
if err != nil {
return nil, err
}
if addressString == transactionReceivingAddress.String() {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
receiving = append(
receiving,
&appmessage.MempoolEntry{
Fee: transaction.Fee,
Transaction: rpcTransaction,
IsOrphan: areOrphans,
},
)
break //one output is enough
}
if transaction, found := sendingInMempool[address]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
sending = append(sending, &appmessage.MempoolEntry{
Fee: transaction.Fee,
Transaction: rpcTransaction,
IsOrphan: false})
}
//Only append mempoolEntriesByAddress, if at least 1 mempoolEntry for the address is found.
//This mimics the behaviour of GetUtxosByAddresses RPC call.
if len(sending) > 0 || len(receiving) > 0 {
mempoolEntriesByAddresses = append(
mempoolEntriesByAddresses,
&appmessage.MempoolEntryByAddress{
Address: addressString,
Sending: sending,
Receiving: receiving,
},
)
if transaction, found := receivingInMempool[address]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
receiving = append(receiving, &appmessage.MempoolEntry{
Fee: transaction.Fee,
Transaction: rpcTransaction,
IsOrphan: false})
}
}
if getMempoolEntriesByAddressesRequest.IncludeOrphanPool {
sendingInOrphanPool, receivingInOrphanPool, err := context.Domain.MiningManager().GetOrphanTransactionsByAddresses()
if err != nil {
return nil, err
}
if transaction, found := sendingInOrphanPool[address]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
sending = append(sending, &appmessage.MempoolEntry{
Fee: transaction.Fee,
Transaction: rpcTransaction,
IsOrphan: true})
}
if transaction, found := receivingInOrphanPool[address]; found {
rpcTransaction := appmessage.DomainTransactionToRPCTransaction(transaction)
receiving = append(receiving, &appmessage.MempoolEntry{
Fee: transaction.Fee,
Transaction: rpcTransaction,
IsOrphan: true})
}
}
if len(sending) > 0 || len(receiving) > 0 {
mempoolEntriesByAddresses = append(
mempoolEntriesByAddresses,
&appmessage.MempoolEntryByAddress{
Address: address.String(),
Sending: sending,
Receiving: receiving,
},
)
}
}
return mempoolEntriesByAddresses, nil
return appmessage.NewGetMempoolEntriesByAddressesResponseMessage(mempoolEntriesByAddresses), nil
}

View File

@ -20,7 +20,7 @@ type factory struct{}
func (f *factory) NewMiningManager(consensusReference consensusreference.ConsensusReference, params *dagconfig.Params,
mempoolConfig *mempoolpkg.Config) MiningManager {
mempool := mempoolpkg.New(mempoolConfig, consensusReference)
mempool := mempoolpkg.New(mempoolConfig, params, consensusReference)
blockTemplateBuilder := blocktemplatebuilder.New(consensusReference, mempool, params.MaxBlockMass, params.CoinbasePayloadScriptPublicKeyMaxLength)
return &miningManager{

View File

@ -95,7 +95,7 @@ func TestCalcMinRequiredTxRelayFee(t *testing.T) {
mempoolConfig.MinimumRelayTransactionFee = test.minimumRelayTransactionFee
tcAsConsensus := tc.(externalapi.Consensus)
tcAsConsensusPointer := &tcAsConsensus
mempool := New(mempoolConfig, consensusreference.NewConsensusReference(&tcAsConsensusPointer)).(*mempool)
mempool := New(mempoolConfig, tc.DAGParams(), consensusreference.NewConsensusReference(&tcAsConsensusPointer)).(*mempool)
got := mempool.minimumRequiredTransactionRelayFee(test.size)
if got != test.want {
@ -184,7 +184,7 @@ func TestIsTransactionOutputDust(t *testing.T) {
mempoolConfig.MinimumRelayTransactionFee = test.minimumRelayTransactionFee
tcAsConsensus := tc.(externalapi.Consensus)
tcAsConsensusPointer := &tcAsConsensus
mempool := New(mempoolConfig, consensusreference.NewConsensusReference(&tcAsConsensusPointer)).(*mempool)
mempool := New(mempoolConfig, tc.DAGParams(), consensusreference.NewConsensusReference(&tcAsConsensusPointer)).(*mempool)
res := mempool.IsTransactionOutputDust(&test.txOut)
if res != test.isDust {
@ -306,7 +306,7 @@ func TestCheckTransactionStandardInIsolation(t *testing.T) {
tcAsConsensus := tc.(externalapi.Consensus)
tcAsConsensusPointer := &tcAsConsensus
consensusReference := consensusreference.NewConsensusReference(&tcAsConsensusPointer)
mempool := New(mempoolConfig, consensusReference).(*mempool)
mempool := New(mempoolConfig, tc.DAGParams(), consensusReference).(*mempool)
// Ensure standardness is as expected.
err := mempool.checkTransactionStandardInIsolation(test.tx)

View File

@ -6,7 +6,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/utils/transactionhelper"
)
func (mp *mempool) handleNewBlockTransactions(blockTransactions []*externalapi.DomainTransaction) (
func (mp *mempool) handleNewBlockTransactions(blockTransactions []*externalapi.DomainTransaction, clone bool) (
[]*externalapi.DomainTransaction, error) {
// Skip the coinbase transaction
@ -30,7 +30,7 @@ func (mp *mempool) handleNewBlockTransactions(blockTransactions []*externalapi.D
return nil, err
}
acceptedOrphansFromThisTransaction, err := mp.orphansPool.processOrphansAfterAcceptedTransaction(transaction)
acceptedOrphansFromThisTransaction, err := mp.orphansPool.processOrphansAfterAcceptedTransaction(transaction, clone)
if err != nil {
return nil, err
}

View File

@ -1,9 +1,12 @@
package mempool
import (
"github.com/kaspanet/kaspad/domain/consensusreference"
"sync"
"github.com/kaspanet/kaspad/domain/consensusreference"
"github.com/kaspanet/kaspad/domain/dagconfig"
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
miningmanagermodel "github.com/kaspanet/kaspad/domain/miningmanager/model"
)
@ -12,6 +15,7 @@ type mempool struct {
mtx sync.RWMutex
config *Config
params *dagconfig.Params
consensusReference consensusreference.ConsensusReference
mempoolUTXOSet *mempoolUTXOSet
@ -20,9 +24,10 @@ type mempool struct {
}
// New constructs a new mempool
func New(config *Config, consensusReference consensusreference.ConsensusReference) miningmanagermodel.Mempool {
func New(config *Config, params *dagconfig.Params, consensusReference consensusreference.ConsensusReference) miningmanagermodel.Mempool {
mp := &mempool{
config: config,
params: params,
consensusReference: consensusReference,
}
@ -39,35 +44,57 @@ func (mp *mempool) ValidateAndInsertTransaction(transaction *externalapi.DomainT
mp.mtx.Lock()
defer mp.mtx.Unlock()
return mp.validateAndInsertTransaction(transaction, isHighPriority, allowOrphan)
return mp.validateAndInsertTransaction(transaction, isHighPriority, allowOrphan, true)
}
func (mp *mempool) GetTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.transactionsPool.getTransaction(transactionID)
return mp.transactionsPool.getTransaction(transactionID, true)
}
func (mp *mempool) GetTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error,
) {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.transactionsPool.getTransactionsByAddresses(true)
}
func (mp *mempool) AllTransactions() []*externalapi.DomainTransaction {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.transactionsPool.getAllTransactions()
return mp.transactionsPool.getAllTransactions(true)
}
func (mp *mempool) GetOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.orphansPool.getOrphanTransaction(transactionID)
return mp.orphansPool.getOrphanTransaction(transactionID, true)
}
func (mp *mempool) GetOrphanTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error,
) {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.orphansPool.getOrphanTransactionsByAddresses(true)
}
func (mp *mempool) AllOrphanTransactions() []*externalapi.DomainTransaction {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.orphansPool.getAllOrphanTransactions()
return mp.orphansPool.getAllOrphanTransactions(true)
}
func (mp *mempool) TransactionCount() int {
@ -83,21 +110,21 @@ func (mp *mempool) HandleNewBlockTransactions(transactions []*externalapi.Domain
mp.mtx.Lock()
defer mp.mtx.Unlock()
return mp.handleNewBlockTransactions(transactions)
return mp.handleNewBlockTransactions(transactions, true)
}
func (mp *mempool) BlockCandidateTransactions() []*externalapi.DomainTransaction {
mp.mtx.RLock()
defer mp.mtx.RUnlock()
return mp.transactionsPool.allReadyTransactions()
return mp.transactionsPool.allReadyTransactions(true)
}
func (mp *mempool) RevalidateHighPriorityTransactions() (validTransactions []*externalapi.DomainTransaction, err error) {
mp.mtx.Lock()
defer mp.mtx.Unlock()
return mp.revalidateHighPriorityTransactions()
return mp.revalidateHighPriorityTransactions(true)
}
func (mp *mempool) RemoveTransactions(transactions []*externalapi.DomainTransaction, removeRedeemers bool) error {

View File

@ -51,7 +51,7 @@ func (mpus *mempoolUTXOSet) addTransaction(transaction *model.MempoolTransaction
func (mpus *mempoolUTXOSet) removeTransaction(transaction *model.MempoolTransaction) {
for _, input := range transaction.Transaction().Inputs {
// If the transaction creating the output spent by this input is in the mempool - restore it's UTXO
if _, ok := mpus.mempool.transactionsPool.getTransaction(&input.PreviousOutpoint.TransactionID); ok {
if _, ok := mpus.mempool.transactionsPool.getTransaction(&input.PreviousOutpoint.TransactionID, false); ok {
mpus.poolUnspentOutputs[input.PreviousOutpoint] = input.UTXOEntry
}
delete(mpus.transactionByPreviousOutpoint, input.PreviousOutpoint)

View File

@ -4,6 +4,8 @@ import (
"fmt"
"github.com/kaspanet/kaspad/domain/consensus/utils/constants"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/util"
"github.com/kaspanet/kaspad/domain/consensus/ruleerrors"
@ -134,7 +136,7 @@ func (op *orphansPool) addOrphan(transaction *externalapi.DomainTransaction, isH
return nil
}
func (op *orphansPool) processOrphansAfterAcceptedTransaction(acceptedTransaction *externalapi.DomainTransaction) (
func (op *orphansPool) processOrphansAfterAcceptedTransaction(acceptedTransaction *externalapi.DomainTransaction, clone bool) (
acceptedOrphans []*externalapi.DomainTransaction, err error) {
acceptedOrphans = []*externalapi.DomainTransaction{}
@ -169,7 +171,11 @@ func (op *orphansPool) processOrphansAfterAcceptedTransaction(acceptedTransactio
}
return nil, err
}
acceptedOrphans = append(acceptedOrphans, orphan.Transaction())
if clone {
acceptedOrphans = append(acceptedOrphans, orphan.Transaction().Clone())
} else {
acceptedOrphans = append(acceptedOrphans, orphan.Transaction())
}
}
}
}
@ -329,17 +335,67 @@ func (op *orphansPool) randomNonHighPriorityOrphan() *model.OrphanTransaction {
return nil
}
func (op *orphansPool) getOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) {
func (op *orphansPool) getOrphanTransaction(transactionID *externalapi.DomainTransactionID, clone bool) (*externalapi.DomainTransaction, bool) {
if orphanTransaction, ok := op.allOrphans[*transactionID]; ok {
if clone {
return orphanTransaction.Transaction().Clone(), true
}
return orphanTransaction.Transaction(), true
}
return nil, false
}
func (op *orphansPool) getAllOrphanTransactions() []*externalapi.DomainTransaction {
allOrphanTransactions := make([]*externalapi.DomainTransaction, 0, len(op.allOrphans))
func (op *orphansPool) getOrphanTransactionsByAddresses(clone bool) (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error) {
sending = make(map[util.Address]*externalapi.DomainTransaction)
receiving = make(map[util.Address]*externalapi.DomainTransaction)
var transaction *externalapi.DomainTransaction
for _, mempoolTransaction := range op.allOrphans {
allOrphanTransactions = append(allOrphanTransactions, mempoolTransaction.Transaction())
if clone {
transaction = mempoolTransaction.Transaction().Clone()
} else {
transaction = mempoolTransaction.Transaction()
}
for _, input := range transaction.Inputs {
if input.UTXOEntry == nil { //this is not a bug, but a valid state of orphan transactions with missing outpoints.
continue
}
_, address, err := txscript.ExtractScriptPubKeyAddress(input.UTXOEntry.ScriptPublicKey(), op.mempool.params)
if err != nil {
return nil, nil, err
}
if address == nil { //none standard tx
continue
}
sending[address] = transaction
for _, output := range transaction.Outputs {
_, address, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, op.mempool.params)
if err != nil {
return nil, nil, err
}
if address == nil { //none standard tx
continue
}
receiving[address] = transaction
}
}
}
return sending, receiving, nil
}
func (op *orphansPool) getAllOrphanTransactions(clone bool) []*externalapi.DomainTransaction {
allOrphanTransactions := make([]*externalapi.DomainTransaction, len(op.allOrphans))
i := 0
for _, mempoolTransaction := range op.allOrphans {
if clone {
allOrphanTransactions[i] = mempoolTransaction.Transaction().Clone()
} else {
allOrphanTransactions[i] = mempoolTransaction.Transaction()
}
}
return allOrphanTransactions
}

View File

@ -6,22 +6,35 @@ import (
"github.com/kaspanet/kaspad/infrastructure/logger"
)
func (mp *mempool) revalidateHighPriorityTransactions() ([]*externalapi.DomainTransaction, error) {
func (mp *mempool) revalidateHighPriorityTransactions(clone bool) ([]*externalapi.DomainTransaction, error) {
onEnd := logger.LogAndMeasureExecutionTime(log, "revalidateHighPriorityTransactions")
defer onEnd()
validTransactions := []*externalapi.DomainTransaction{}
if !clone {
for _, transaction := range mp.transactionsPool.highPriorityTransactions {
isValid, err := mp.revalidateTransaction(transaction)
if err != nil {
return nil, err
}
if !isValid {
continue
}
for _, transaction := range mp.transactionsPool.highPriorityTransactions {
isValid, err := mp.revalidateTransaction(transaction)
if err != nil {
return nil, err
}
if !isValid {
continue
validTransactions = append(validTransactions, transaction.Transaction())
}
} else {
for _, transaction := range mp.transactionsPool.highPriorityTransactions {
isValid, err := mp.revalidateTransaction(transaction)
if err != nil {
return nil, err
}
if !isValid {
continue
}
validTransactions = append(validTransactions, transaction.Transaction())
validTransactions = append(validTransactions, transaction.Transaction().Clone())
}
}
return validTransactions, nil

View File

@ -6,7 +6,9 @@ import (
"github.com/pkg/errors"
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensus/utils/txscript"
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
"github.com/kaspanet/kaspad/util"
)
type transactionsPool struct {
@ -130,12 +132,16 @@ func (tp *transactionsPool) expireOldTransactions() error {
return nil
}
func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransaction {
func (tp *transactionsPool) allReadyTransactions(clone bool) []*externalapi.DomainTransaction {
result := []*externalapi.DomainTransaction{}
for _, mempoolTransaction := range tp.allTransactions {
if len(mempoolTransaction.ParentTransactionsInPool()) == 0 {
result = append(result, mempoolTransaction.Transaction())
if clone {
result = append(result, mempoolTransaction.Transaction().Clone())
} else {
result = append(result, mempoolTransaction.Transaction())
}
}
}
@ -204,17 +210,63 @@ func (tp *transactionsPool) limitTransactionCount() error {
return nil
}
func (tp *transactionsPool) getTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) {
func (tp *transactionsPool) getTransaction(transactionID *externalapi.DomainTransactionID, clone bool) (*externalapi.DomainTransaction, bool) {
if mempoolTransaction, ok := tp.allTransactions[*transactionID]; ok {
if clone {
return mempoolTransaction.Transaction().Clone(), true
}
return mempoolTransaction.Transaction(), true
}
return nil, false
}
func (tp *transactionsPool) getAllTransactions() []*externalapi.DomainTransaction {
allTransactions := make([]*externalapi.DomainTransaction, 0, len(tp.allTransactions))
func (tp *transactionsPool) getTransactionsByAddresses(clone bool) (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error) {
sending = make(map[util.Address]*externalapi.DomainTransaction)
receiving = make(map[util.Address]*externalapi.DomainTransaction)
var transaction *externalapi.DomainTransaction
for _, mempoolTransaction := range tp.allTransactions {
allTransactions = append(allTransactions, mempoolTransaction.Transaction())
if clone {
transaction = mempoolTransaction.Transaction().Clone()
} else {
transaction = mempoolTransaction.Transaction()
}
for _, input := range transaction.Inputs {
_, address, err := txscript.ExtractScriptPubKeyAddress(input.UTXOEntry.ScriptPublicKey(), tp.mempool.params)
if err != nil {
return nil, nil, err
}
if address == nil { //ignore none-standard script
continue
}
sending[address] = transaction
for _, output := range transaction.Outputs {
_, address, err := txscript.ExtractScriptPubKeyAddress(output.ScriptPublicKey, tp.mempool.params)
if err != nil {
return nil, nil, err
}
if address == nil { //ignore none-standard script
continue
}
receiving[address] = transaction
}
}
}
return sending, receiving, nil
}
func (tp *transactionsPool) getAllTransactions(clone bool) []*externalapi.DomainTransaction {
allTransactions := make([]*externalapi.DomainTransaction, len(tp.allTransactions))
i := 0
for _, mempoolTransaction := range tp.allTransactions {
if clone {
allTransactions[i] = mempoolTransaction.Transaction().Clone()
} else {
allTransactions[i] = mempoolTransaction.Transaction()
}
i++
}
return allTransactions
}

View File

@ -10,7 +10,7 @@ import (
)
func (mp *mempool) validateAndInsertTransaction(transaction *externalapi.DomainTransaction, isHighPriority bool,
allowOrphan bool) (acceptedTransactions []*externalapi.DomainTransaction, err error) {
allowOrphan bool, clone bool) (acceptedTransactions []*externalapi.DomainTransaction, err error) {
onEnd := logger.LogAndMeasureExecutionTime(log,
fmt.Sprintf("validateAndInsertTransaction %s", consensushashing.TransactionID(transaction)))
@ -49,12 +49,16 @@ func (mp *mempool) validateAndInsertTransaction(transaction *externalapi.DomainT
return nil, err
}
acceptedOrphans, err := mp.orphansPool.processOrphansAfterAcceptedTransaction(mempoolTransaction.Transaction())
acceptedOrphans, err := mp.orphansPool.processOrphansAfterAcceptedTransaction(mempoolTransaction.Transaction(), clone)
if err != nil {
return nil, err
}
acceptedTransactions = append([]*externalapi.DomainTransaction{transaction}, acceptedOrphans...)
if clone {
acceptedTransactions = append([]*externalapi.DomainTransaction{transaction.Clone()}, acceptedOrphans...)
} else {
acceptedTransactions = append([]*externalapi.DomainTransaction{transaction}, acceptedOrphans...)
}
err = mp.transactionsPool.limitTransactionCount()
if err != nil {

View File

@ -7,6 +7,7 @@ import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/domain/consensusreference"
miningmanagermodel "github.com/kaspanet/kaspad/domain/miningmanager/model"
"github.com/kaspanet/kaspad/util"
)
// MiningManager creates block templates for mining as well as maintaining
@ -16,8 +17,16 @@ type MiningManager interface {
ClearBlockTemplate()
GetBlockTemplateBuilder() miningmanagermodel.BlockTemplateBuilder
GetTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool)
GetTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error)
AllTransactions() []*externalapi.DomainTransaction
GetOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool)
GetOrphanTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error)
AllOrphanTransactions() []*externalapi.DomainTransaction
TransactionCount() int
HandleNewBlockTransactions(txs []*externalapi.DomainTransaction) ([]*externalapi.DomainTransaction, error)
@ -118,12 +127,26 @@ func (mm *miningManager) AllTransactions() []*externalapi.DomainTransaction {
return mm.mempool.AllTransactions()
}
func (mm *miningManager) GetTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error) {
return mm.mempool.GetTransactionsByAddresses()
}
func (mm *miningManager) GetOrphanTransaction(
transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool) {
return mm.mempool.GetOrphanTransaction(transactionID)
}
func (mm *miningManager) GetOrphanTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error) {
return mm.mempool.GetTransactionsByAddresses()
}
func (mm *miningManager) AllOrphanTransactions() []*externalapi.DomainTransaction {
return mm.mempool.AllOrphanTransactions()

View File

@ -2,6 +2,7 @@ package model
import (
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
"github.com/kaspanet/kaspad/util"
)
// Mempool maintains a set of known transactions that
@ -13,8 +14,16 @@ type Mempool interface {
acceptedTransactions []*externalapi.DomainTransaction, err error)
RemoveTransactions(txs []*externalapi.DomainTransaction, removeRedeemers bool) error
GetTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool)
GetTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error)
AllTransactions() []*externalapi.DomainTransaction
GetOrphanTransaction(transactionID *externalapi.DomainTransactionID) (*externalapi.DomainTransaction, bool)
GetOrphanTransactionsByAddresses() (
sending map[util.Address]*externalapi.DomainTransaction,
receiving map[util.Address]*externalapi.DomainTransaction,
err error)
AllOrphanTransactions() []*externalapi.DomainTransaction
TransactionCount() int
RevalidateHighPriorityTransactions() (validTransactions []*externalapi.DomainTransaction, err error)