mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-09-13 21:10:12 +00:00
152 lines
4.7 KiB
Go
152 lines
4.7 KiB
Go
package mempool
|
|
|
|
import (
|
|
"github.com/kaspanet/kaspad/domain/consensus/model/externalapi"
|
|
"github.com/kaspanet/kaspad/domain/miningmanager/mempool/model"
|
|
)
|
|
|
|
type transactionsPool struct {
|
|
mempool *mempool
|
|
allTransactions model.IDToTransaction
|
|
highPriorityTransactions model.IDToTransaction
|
|
chainedTransactionsByPreviousOutpoint model.OutpointToTransaction
|
|
transactionsOrderedByFeeRate model.TransactionsOrderedByFeeRate
|
|
lastExpireScan uint64
|
|
}
|
|
|
|
func newTransactionsPool(mp *mempool) *transactionsPool {
|
|
return &transactionsPool{
|
|
mempool: mp,
|
|
allTransactions: model.IDToTransaction{},
|
|
highPriorityTransactions: model.IDToTransaction{},
|
|
chainedTransactionsByPreviousOutpoint: model.OutpointToTransaction{},
|
|
transactionsOrderedByFeeRate: model.TransactionsOrderedByFeeRate{},
|
|
lastExpireScan: 0,
|
|
}
|
|
}
|
|
|
|
func (tp *transactionsPool) addTransaction(transaction *externalapi.DomainTransaction,
|
|
parentTransactionsInPool model.OutpointToTransaction, isHighPriority bool) error {
|
|
|
|
virtualDAAScore, err := tp.mempool.virtualDAAScore()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
mempoolTransaction := model.NewMempoolTransaction(
|
|
transaction, parentTransactionsInPool, isHighPriority, virtualDAAScore)
|
|
|
|
return tp.addMempoolTransaction(mempoolTransaction)
|
|
}
|
|
|
|
func (tp *transactionsPool) addMempoolTransaction(transaction *model.MempoolTransaction) error {
|
|
tp.allTransactions[*transaction.TransactionID()] = transaction
|
|
|
|
for outpoint, parentTransactionInPool := range transaction.ParentTransactionsInPool() {
|
|
tp.chainedTransactionsByPreviousOutpoint[outpoint] = parentTransactionInPool
|
|
}
|
|
|
|
tp.mempool.mempoolUTXOSet.addTransaction(transaction)
|
|
|
|
err := tp.transactionsOrderedByFeeRate.Push(transaction)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if transaction.IsHighPriority() {
|
|
tp.highPriorityTransactions[*transaction.TransactionID()] = transaction
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (tp *transactionsPool) removeTransaction(transaction *model.MempoolTransaction) error {
|
|
delete(tp.allTransactions, *transaction.TransactionID())
|
|
|
|
err := tp.transactionsOrderedByFeeRate.Remove(transaction)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
delete(tp.highPriorityTransactions, *transaction.TransactionID())
|
|
|
|
for outpoint := range transaction.ParentTransactionsInPool() {
|
|
delete(tp.chainedTransactionsByPreviousOutpoint, outpoint)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (tp *transactionsPool) expireOldTransactions() error {
|
|
virtualDAAScore, err := tp.mempool.virtualDAAScore()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
if virtualDAAScore-tp.lastExpireScan < tp.mempool.config.transactionExpireScanIntervalDAAScore {
|
|
return nil
|
|
}
|
|
|
|
for _, mempoolTransaction := range tp.allTransactions {
|
|
// Never expire high priority transactions
|
|
if mempoolTransaction.IsHighPriority() {
|
|
continue
|
|
}
|
|
|
|
// Remove all transactions whose addedAtDAAScore is older then transactionExpireIntervalDAAScore
|
|
if virtualDAAScore-mempoolTransaction.AddedAtDAAScore() > tp.mempool.config.transactionExpireIntervalDAAScore {
|
|
err = tp.mempool.RemoveTransaction(mempoolTransaction.TransactionID(), true)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
}
|
|
}
|
|
|
|
tp.lastExpireScan = virtualDAAScore
|
|
return nil
|
|
}
|
|
|
|
func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransaction {
|
|
result := []*externalapi.DomainTransaction{}
|
|
|
|
for _, mempoolTransaction := range tp.allTransactions {
|
|
if len(mempoolTransaction.ParentTransactionsInPool()) == 0 {
|
|
result = append(result, mempoolTransaction.Transaction())
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
func (tp *transactionsPool) getParentTransactionsInPool(
|
|
transaction *externalapi.DomainTransaction) model.OutpointToTransaction {
|
|
|
|
parentsTransactionsInPool := model.OutpointToTransaction{}
|
|
|
|
for _, input := range transaction.Inputs {
|
|
transaction := tp.allTransactions[input.PreviousOutpoint.TransactionID]
|
|
parentsTransactionsInPool[input.PreviousOutpoint] = transaction
|
|
}
|
|
|
|
return parentsTransactionsInPool
|
|
}
|
|
|
|
func (tp *transactionsPool) getRedeemers(transaction *model.MempoolTransaction) []*model.MempoolTransaction {
|
|
queue := []*model.MempoolTransaction{transaction}
|
|
redeemers := []*model.MempoolTransaction{}
|
|
for len(queue) > 0 {
|
|
var current *model.MempoolTransaction
|
|
current, queue = queue[0], queue[1:]
|
|
|
|
outpoint := externalapi.DomainOutpoint{TransactionID: *current.TransactionID()}
|
|
for i := range current.Transaction().Outputs {
|
|
outpoint.Index = uint32(i)
|
|
if redeemerTransaction, ok := tp.chainedTransactionsByPreviousOutpoint[outpoint]; ok {
|
|
queue = append(queue, redeemerTransaction)
|
|
redeemers = append(redeemers, redeemerTransaction)
|
|
}
|
|
}
|
|
}
|
|
return redeemers
|
|
}
|