diff --git a/domain/miningmanager/mempool/fill_inputs_and_get_missing_parents.go b/domain/miningmanager/mempool/fill_inputs_and_get_missing_parents.go index 9b002df41..e269a079a 100644 --- a/domain/miningmanager/mempool/fill_inputs_and_get_missing_parents.go +++ b/domain/miningmanager/mempool/fill_inputs_and_get_missing_parents.go @@ -9,7 +9,7 @@ import ( ) func (mp *mempool) fillInputsAndGetMissingParents(transaction *externalapi.DomainTransaction) ( - parents model.OutpointToTransactionMap, missingOutpoints []*externalapi.DomainOutpoint, err error) { + parents model.IDToTransactionMap, missingOutpoints []*externalapi.DomainOutpoint, err error) { parentsInPool := mp.transactionsPool.getParentTransactionsInPool(transaction) @@ -34,9 +34,9 @@ func (mp *mempool) fillInputsAndGetMissingParents(transaction *externalapi.Domai return parentsInPool, nil, nil } -func fillInputs(transaction *externalapi.DomainTransaction, parentsInPool model.OutpointToTransactionMap) { +func fillInputs(transaction *externalapi.DomainTransaction, parentsInPool model.IDToTransactionMap) { for _, input := range transaction.Inputs { - parent, ok := parentsInPool[input.PreviousOutpoint] + parent, ok := parentsInPool[input.PreviousOutpoint.TransactionID] if !ok { continue } diff --git a/domain/miningmanager/mempool/model/map_types.go b/domain/miningmanager/mempool/model/map_types.go index c5ca09968..d6ca685de 100644 --- a/domain/miningmanager/mempool/model/map_types.go +++ b/domain/miningmanager/mempool/model/map_types.go @@ -7,6 +7,9 @@ import ( // IDToTransactionMap maps transactionID to a MempoolTransaction type IDToTransactionMap map[externalapi.DomainTransactionID]*MempoolTransaction +// IDToTransactionsSliceMap maps transactionID to a slice MempoolTransaction +type IDToTransactionsSliceMap map[externalapi.DomainTransactionID][]*MempoolTransaction + // OutpointToUTXOEntryMap maps an outpoint to a UTXOEntry type OutpointToUTXOEntryMap map[externalapi.DomainOutpoint]externalapi.UTXOEntry diff --git a/domain/miningmanager/mempool/model/mempool_transaction.go b/domain/miningmanager/mempool/model/mempool_transaction.go index 9240486b6..017e13c1f 100644 --- a/domain/miningmanager/mempool/model/mempool_transaction.go +++ b/domain/miningmanager/mempool/model/mempool_transaction.go @@ -8,7 +8,7 @@ import ( // MempoolTransaction represents a transaction inside the main TransactionPool type MempoolTransaction struct { transaction *externalapi.DomainTransaction - parentTransactionsInPool OutpointToTransactionMap + parentTransactionsInPool IDToTransactionMap isHighPriority bool addedAtDAAScore uint64 } @@ -16,7 +16,7 @@ type MempoolTransaction struct { // NewMempoolTransaction constructs a new MempoolTransaction func NewMempoolTransaction( transaction *externalapi.DomainTransaction, - parentTransactionsInPool OutpointToTransactionMap, + parentTransactionsInPool IDToTransactionMap, isHighPriority bool, addedAtDAAScore uint64, ) *MempoolTransaction { @@ -39,10 +39,15 @@ func (mt *MempoolTransaction) Transaction() *externalapi.DomainTransaction { } // ParentTransactionsInPool a list of parent transactions that exist in the mempool, indexed by outpoint -func (mt *MempoolTransaction) ParentTransactionsInPool() OutpointToTransactionMap { +func (mt *MempoolTransaction) ParentTransactionsInPool() IDToTransactionMap { return mt.parentTransactionsInPool } +// RemoveParentTransactionInPool deletes a transaction from the parentTransactionsInPool set +func (mt *MempoolTransaction) RemoveParentTransactionInPool(transactionID *externalapi.DomainTransactionID) { + delete(mt.parentTransactionsInPool, *transactionID) +} + // IsHighPriority returns whether this MempoolTransaction is a high-priority one func (mt *MempoolTransaction) IsHighPriority() bool { return mt.isHighPriority diff --git a/domain/miningmanager/mempool/remove_transaction.go b/domain/miningmanager/mempool/remove_transaction.go index 38e7efb9f..da812d872 100644 --- a/domain/miningmanager/mempool/remove_transaction.go +++ b/domain/miningmanager/mempool/remove_transaction.go @@ -27,9 +27,13 @@ func (mp *mempool) removeTransaction(transactionID *externalapi.DomainTransactio } transactionsToRemove := []*model.MempoolTransaction{mempoolTransaction} + redeemers := mp.transactionsPool.getRedeemers(mempoolTransaction) if removeRedeemers { - redeemers := mp.transactionsPool.getRedeemers(mempoolTransaction) transactionsToRemove = append(transactionsToRemove, redeemers...) + } else { + for _, redeemer := range redeemers { + redeemer.RemoveParentTransactionInPool(transactionID) + } } for _, transactionToRemove := range transactionsToRemove { diff --git a/domain/miningmanager/mempool/transactions_pool.go b/domain/miningmanager/mempool/transactions_pool.go index ebbd49dc8..e13a448b6 100644 --- a/domain/miningmanager/mempool/transactions_pool.go +++ b/domain/miningmanager/mempool/transactions_pool.go @@ -1,35 +1,36 @@ package mempool import ( + "time" + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/miningmanager/mempool/model" - "time" ) type transactionsPool struct { - mempool *mempool - allTransactions model.IDToTransactionMap - highPriorityTransactions model.IDToTransactionMap - chainedTransactionsByPreviousOutpoint model.OutpointToTransactionMap - transactionsOrderedByFeeRate model.TransactionsOrderedByFeeRate - lastExpireScanDAAScore uint64 - lastExpireScanTime time.Time + mempool *mempool + allTransactions model.IDToTransactionMap + highPriorityTransactions model.IDToTransactionMap + chainedTransactionsByParentID model.IDToTransactionsSliceMap + transactionsOrderedByFeeRate model.TransactionsOrderedByFeeRate + lastExpireScanDAAScore uint64 + lastExpireScanTime time.Time } func newTransactionsPool(mp *mempool) *transactionsPool { return &transactionsPool{ - mempool: mp, - allTransactions: model.IDToTransactionMap{}, - highPriorityTransactions: model.IDToTransactionMap{}, - chainedTransactionsByPreviousOutpoint: model.OutpointToTransactionMap{}, - transactionsOrderedByFeeRate: model.TransactionsOrderedByFeeRate{}, - lastExpireScanDAAScore: 0, - lastExpireScanTime: time.Now(), + mempool: mp, + allTransactions: model.IDToTransactionMap{}, + highPriorityTransactions: model.IDToTransactionMap{}, + chainedTransactionsByParentID: model.IDToTransactionsSliceMap{}, + transactionsOrderedByFeeRate: model.TransactionsOrderedByFeeRate{}, + lastExpireScanDAAScore: 0, + lastExpireScanTime: time.Now(), } } func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransaction, - parentTransactionsInPool model.OutpointToTransactionMap, isHighPriority bool) (*model.MempoolTransaction, error) { + parentTransactionsInPool model.IDToTransactionMap, isHighPriority bool) (*model.MempoolTransaction, error) { virtualDAAScore, err := tp.mempool.consensusReference.Consensus().GetVirtualDAAScore() if err != nil { @@ -50,8 +51,13 @@ func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransa func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error { tp.allTransactions[*transaction.TransactionID()] = transaction - for outpoint, parentTransactionInPool := range transaction.ParentTransactionsInPool() { - tp.chainedTransactionsByPreviousOutpoint[outpoint] = parentTransactionInPool + for _, parentTransactionInPool := range transaction.ParentTransactionsInPool() { + parentTransactionID := *parentTransactionInPool.TransactionID() + if tp.chainedTransactionsByParentID[parentTransactionID] == nil { + tp.chainedTransactionsByParentID[parentTransactionID] = []*model.MempoolTransaction{} + } + tp.chainedTransactionsByParentID[parentTransactionID] = + append(tp.chainedTransactionsByParentID[parentTransactionID], transaction) } tp.mempool.mempoolUTXOSet.addTransaction(transaction) @@ -78,9 +84,7 @@ func (tp *transactionsPool) removeTransaction(transaction *model.MempoolTransact delete(tp.highPriorityTransactions, *transaction.TransactionID()) - for outpoint := range transaction.ParentTransactionsInPool() { - delete(tp.chainedTransactionsByPreviousOutpoint, outpoint) - } + delete(tp.chainedTransactionsByParentID, *transaction.TransactionID()) return nil } @@ -132,13 +136,13 @@ func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransact } func (tp *transactionsPool) getParentTransactionsInPool( - transaction *externalapi.DomainTransaction) model.OutpointToTransactionMap { + transaction *externalapi.DomainTransaction) model.IDToTransactionMap { - parentsTransactionsInPool := model.OutpointToTransactionMap{} + parentsTransactionsInPool := model.IDToTransactionMap{} for _, input := range transaction.Inputs { if transaction, ok := tp.allTransactions[input.PreviousOutpoint.TransactionID]; ok { - parentsTransactionsInPool[input.PreviousOutpoint] = transaction + parentsTransactionsInPool[*transaction.TransactionID()] = transaction } } @@ -153,13 +157,9 @@ func (tp *transactionsPool) getRedeemers(transaction *model.MempoolTransaction) last := len(stack) - 1 current, stack = stack[last], stack[:last] - outpoint := externalapi.DomainOutpoint{TransactionID: *current.TransactionID()} - for i := range current.Transaction().Outputs { - outpoint.Index = uint32(i) - if redeemerTransaction, ok := tp.chainedTransactionsByPreviousOutpoint[outpoint]; ok { - stack = append(stack, redeemerTransaction) - redeemers = append(redeemers, redeemerTransaction) - } + for _, redeemerTransaction := range tp.chainedTransactionsByParentID[*current.TransactionID()] { + stack = append(stack, redeemerTransaction) + redeemers = append(redeemers, redeemerTransaction) } } return redeemers