Fix bookkeeping of chained transactions in mempool (#1946)

* Fix bookkeeping of chained transactions in mempool

* Fix golint error
This commit is contained in:
Svarog 2022-02-18 13:21:45 +02:00 committed by GitHub
parent 13a09da848
commit f452531df0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 50 additions and 38 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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