mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-07 06:36:46 +00:00
Fix bookkeeping of chained transactions in mempool (#1946)
* Fix bookkeeping of chained transactions in mempool * Fix golint error
This commit is contained in:
parent
13a09da848
commit
f452531df0
@ -9,7 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (mp *mempool) fillInputsAndGetMissingParents(transaction *externalapi.DomainTransaction) (
|
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)
|
parentsInPool := mp.transactionsPool.getParentTransactionsInPool(transaction)
|
||||||
|
|
||||||
@ -34,9 +34,9 @@ func (mp *mempool) fillInputsAndGetMissingParents(transaction *externalapi.Domai
|
|||||||
return parentsInPool, nil, nil
|
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 {
|
for _, input := range transaction.Inputs {
|
||||||
parent, ok := parentsInPool[input.PreviousOutpoint]
|
parent, ok := parentsInPool[input.PreviousOutpoint.TransactionID]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -7,6 +7,9 @@ import (
|
|||||||
// IDToTransactionMap maps transactionID to a MempoolTransaction
|
// IDToTransactionMap maps transactionID to a MempoolTransaction
|
||||||
type IDToTransactionMap map[externalapi.DomainTransactionID]*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
|
// OutpointToUTXOEntryMap maps an outpoint to a UTXOEntry
|
||||||
type OutpointToUTXOEntryMap map[externalapi.DomainOutpoint]externalapi.UTXOEntry
|
type OutpointToUTXOEntryMap map[externalapi.DomainOutpoint]externalapi.UTXOEntry
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import (
|
|||||||
// MempoolTransaction represents a transaction inside the main TransactionPool
|
// MempoolTransaction represents a transaction inside the main TransactionPool
|
||||||
type MempoolTransaction struct {
|
type MempoolTransaction struct {
|
||||||
transaction *externalapi.DomainTransaction
|
transaction *externalapi.DomainTransaction
|
||||||
parentTransactionsInPool OutpointToTransactionMap
|
parentTransactionsInPool IDToTransactionMap
|
||||||
isHighPriority bool
|
isHighPriority bool
|
||||||
addedAtDAAScore uint64
|
addedAtDAAScore uint64
|
||||||
}
|
}
|
||||||
@ -16,7 +16,7 @@ type MempoolTransaction struct {
|
|||||||
// NewMempoolTransaction constructs a new MempoolTransaction
|
// NewMempoolTransaction constructs a new MempoolTransaction
|
||||||
func NewMempoolTransaction(
|
func NewMempoolTransaction(
|
||||||
transaction *externalapi.DomainTransaction,
|
transaction *externalapi.DomainTransaction,
|
||||||
parentTransactionsInPool OutpointToTransactionMap,
|
parentTransactionsInPool IDToTransactionMap,
|
||||||
isHighPriority bool,
|
isHighPriority bool,
|
||||||
addedAtDAAScore uint64,
|
addedAtDAAScore uint64,
|
||||||
) *MempoolTransaction {
|
) *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
|
// 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
|
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
|
// IsHighPriority returns whether this MempoolTransaction is a high-priority one
|
||||||
func (mt *MempoolTransaction) IsHighPriority() bool {
|
func (mt *MempoolTransaction) IsHighPriority() bool {
|
||||||
return mt.isHighPriority
|
return mt.isHighPriority
|
||||||
|
@ -27,9 +27,13 @@ func (mp *mempool) removeTransaction(transactionID *externalapi.DomainTransactio
|
|||||||
}
|
}
|
||||||
|
|
||||||
transactionsToRemove := []*model.MempoolTransaction{mempoolTransaction}
|
transactionsToRemove := []*model.MempoolTransaction{mempoolTransaction}
|
||||||
|
redeemers := mp.transactionsPool.getRedeemers(mempoolTransaction)
|
||||||
if removeRedeemers {
|
if removeRedeemers {
|
||||||
redeemers := mp.transactionsPool.getRedeemers(mempoolTransaction)
|
|
||||||
transactionsToRemove = append(transactionsToRemove, redeemers...)
|
transactionsToRemove = append(transactionsToRemove, redeemers...)
|
||||||
|
} else {
|
||||||
|
for _, redeemer := range redeemers {
|
||||||
|
redeemer.RemoveParentTransactionInPool(transactionID)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, transactionToRemove := range transactionsToRemove {
|
for _, transactionToRemove := range transactionsToRemove {
|
||||||
|
@ -1,35 +1,36 @@
|
|||||||
package mempool
|
package mempool
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
||||||
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
|
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
|
||||||
"time"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type transactionsPool struct {
|
type transactionsPool struct {
|
||||||
mempool *mempool
|
mempool *mempool
|
||||||
allTransactions model.IDToTransactionMap
|
allTransactions model.IDToTransactionMap
|
||||||
highPriorityTransactions model.IDToTransactionMap
|
highPriorityTransactions model.IDToTransactionMap
|
||||||
chainedTransactionsByPreviousOutpoint model.OutpointToTransactionMap
|
chainedTransactionsByParentID model.IDToTransactionsSliceMap
|
||||||
transactionsOrderedByFeeRate model.TransactionsOrderedByFeeRate
|
transactionsOrderedByFeeRate model.TransactionsOrderedByFeeRate
|
||||||
lastExpireScanDAAScore uint64
|
lastExpireScanDAAScore uint64
|
||||||
lastExpireScanTime time.Time
|
lastExpireScanTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func newTransactionsPool(mp *mempool) *transactionsPool {
|
func newTransactionsPool(mp *mempool) *transactionsPool {
|
||||||
return &transactionsPool{
|
return &transactionsPool{
|
||||||
mempool: mp,
|
mempool: mp,
|
||||||
allTransactions: model.IDToTransactionMap{},
|
allTransactions: model.IDToTransactionMap{},
|
||||||
highPriorityTransactions: model.IDToTransactionMap{},
|
highPriorityTransactions: model.IDToTransactionMap{},
|
||||||
chainedTransactionsByPreviousOutpoint: model.OutpointToTransactionMap{},
|
chainedTransactionsByParentID: model.IDToTransactionsSliceMap{},
|
||||||
transactionsOrderedByFeeRate: model.TransactionsOrderedByFeeRate{},
|
transactionsOrderedByFeeRate: model.TransactionsOrderedByFeeRate{},
|
||||||
lastExpireScanDAAScore: 0,
|
lastExpireScanDAAScore: 0,
|
||||||
lastExpireScanTime: time.Now(),
|
lastExpireScanTime: time.Now(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransaction,
|
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()
|
virtualDAAScore, err := tp.mempool.consensusReference.Consensus().GetVirtualDAAScore()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -50,8 +51,13 @@ func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransa
|
|||||||
func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error {
|
func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error {
|
||||||
tp.allTransactions[*transaction.TransactionID()] = transaction
|
tp.allTransactions[*transaction.TransactionID()] = transaction
|
||||||
|
|
||||||
for outpoint, parentTransactionInPool := range transaction.ParentTransactionsInPool() {
|
for _, parentTransactionInPool := range transaction.ParentTransactionsInPool() {
|
||||||
tp.chainedTransactionsByPreviousOutpoint[outpoint] = parentTransactionInPool
|
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)
|
tp.mempool.mempoolUTXOSet.addTransaction(transaction)
|
||||||
@ -78,9 +84,7 @@ func (tp *transactionsPool) removeTransaction(transaction *model.MempoolTransact
|
|||||||
|
|
||||||
delete(tp.highPriorityTransactions, *transaction.TransactionID())
|
delete(tp.highPriorityTransactions, *transaction.TransactionID())
|
||||||
|
|
||||||
for outpoint := range transaction.ParentTransactionsInPool() {
|
delete(tp.chainedTransactionsByParentID, *transaction.TransactionID())
|
||||||
delete(tp.chainedTransactionsByPreviousOutpoint, outpoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@ -132,13 +136,13 @@ func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransact
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tp *transactionsPool) getParentTransactionsInPool(
|
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 {
|
for _, input := range transaction.Inputs {
|
||||||
if transaction, ok := tp.allTransactions[input.PreviousOutpoint.TransactionID]; ok {
|
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
|
last := len(stack) - 1
|
||||||
current, stack = stack[last], stack[:last]
|
current, stack = stack[last], stack[:last]
|
||||||
|
|
||||||
outpoint := externalapi.DomainOutpoint{TransactionID: *current.TransactionID()}
|
for _, redeemerTransaction := range tp.chainedTransactionsByParentID[*current.TransactionID()] {
|
||||||
for i := range current.Transaction().Outputs {
|
stack = append(stack, redeemerTransaction)
|
||||||
outpoint.Index = uint32(i)
|
redeemers = append(redeemers, redeemerTransaction)
|
||||||
if redeemerTransaction, ok := tp.chainedTransactionsByPreviousOutpoint[outpoint]; ok {
|
|
||||||
stack = append(stack, redeemerTransaction)
|
|
||||||
redeemers = append(redeemers, redeemerTransaction)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return redeemers
|
return redeemers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user