From ff10ce145a97352154d028034fafd6a9ac83eead Mon Sep 17 00:00:00 2001 From: Mike Zak Date: Sun, 6 Jun 2021 13:43:23 +0300 Subject: [PATCH] implement expireOldTransactions and expireOrphanTransactions --- domain/miningmanager/mempool/config.go | 32 ++++++++++++++++++ .../miningmanager/mempool/helper_functions.go | 9 +++++ domain/miningmanager/mempool/mempool.go | 15 +++++++-- domain/miningmanager/mempool/model.go | 15 +++++++-- domain/miningmanager/mempool/orphan_pool.go | 31 +++++++++++++++-- .../mempool/transactions_pool.go | 33 +++++++++++++++++-- 6 files changed, 125 insertions(+), 10 deletions(-) create mode 100644 domain/miningmanager/mempool/config.go create mode 100644 domain/miningmanager/mempool/helper_functions.go diff --git a/domain/miningmanager/mempool/config.go b/domain/miningmanager/mempool/config.go new file mode 100644 index 000000000..9a34611fa --- /dev/null +++ b/domain/miningmanager/mempool/config.go @@ -0,0 +1,32 @@ +package mempool + +import ( + "time" + + "github.com/kaspanet/kaspad/domain/dagconfig" +) + +const ( + defaultTransactionExpireIntervalSeconds uint64 = 60 + defaultTransactionExpireScanIntervalSeconds uint64 = 10 + defaultOrphanExpireIntervalSeconds uint64 = 60 + defaultOrphanExpireScanIntervalSeconds uint64 = 10 +) + +type config struct { + transactionExpireIntervalDAAScore uint64 + transactionExpireScanIntervalDAAScore uint64 + orphanExpireIntervalDAAScore uint64 + orphanExpireScanIntervalDAAScore uint64 +} + +func defaultConfig(dagParams *dagconfig.Params) *config { + targetBlocksPerSecond := uint64(dagParams.TargetTimePerBlock / time.Second) + + return &config{ + transactionExpireIntervalDAAScore: defaultTransactionExpireIntervalSeconds / targetBlocksPerSecond, + transactionExpireScanIntervalDAAScore: defaultTransactionExpireScanIntervalSeconds / targetBlocksPerSecond, + orphanExpireIntervalDAAScore: defaultOrphanExpireIntervalSeconds / targetBlocksPerSecond, + orphanExpireScanIntervalDAAScore: defaultOrphanExpireScanIntervalSeconds / targetBlocksPerSecond, + } +} diff --git a/domain/miningmanager/mempool/helper_functions.go b/domain/miningmanager/mempool/helper_functions.go new file mode 100644 index 000000000..ec20bc443 --- /dev/null +++ b/domain/miningmanager/mempool/helper_functions.go @@ -0,0 +1,9 @@ +package mempool + +func (mp *mempool) virtualDAAScore() (uint64, error) { + virtualInfo, err := mp.consensus.GetVirtualInfo() + if err != nil { + return 0, err + } + return virtualInfo.DAAScore, nil +} diff --git a/domain/miningmanager/mempool/mempool.go b/domain/miningmanager/mempool/mempool.go index 2fa483b00..6566719cb 100644 --- a/domain/miningmanager/mempool/mempool.go +++ b/domain/miningmanager/mempool/mempool.go @@ -1,15 +1,24 @@ package mempool -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +import ( + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + "github.com/kaspanet/kaspad/domain/dagconfig" +) type mempool struct { + config *config + consensus externalapi.Consensus + mempoolUTXOSet *mempoolUTXOSet transactionsPool *transactionsPool orphansPool *orphansPool } -func newMempool() *mempool { - mp := &mempool{} +func newMempool(consensus externalapi.Consensus, dagParams *dagconfig.Params) *mempool { + mp := &mempool{ + config: defaultConfig(dagParams), + consensus: consensus, + } mp.mempoolUTXOSet = newMempoolUTXOSet(mp) mp.transactionsPool = newTransactionsPool(mp) diff --git a/domain/miningmanager/mempool/model.go b/domain/miningmanager/mempool/model.go index 381c91083..8235efb03 100644 --- a/domain/miningmanager/mempool/model.go +++ b/domain/miningmanager/mempool/model.go @@ -1,6 +1,9 @@ package mempool -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +import ( + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" + "github.com/kaspanet/kaspad/domain/consensus/utils/consensushashing" +) type idToTransaction map[externalapi.DomainTransactionID]*mempoolTransaction @@ -11,8 +14,16 @@ type mempoolTransaction struct { addAtDAAScore uint64 } +func (mt *mempoolTransaction) transactionID() *externalapi.DomainTransactionID { + return consensushashing.TransactionID(mt.transaction) +} + type orphanTransaction struct { - transaction externalapi.DomainTransaction + transaction *externalapi.DomainTransaction isHighPriority bool addedAtDAAScore uint64 } + +func (ot *orphanTransaction) transactionID() *externalapi.DomainTransactionID { + return consensushashing.TransactionID(ot.transaction) +} diff --git a/domain/miningmanager/mempool/orphan_pool.go b/domain/miningmanager/mempool/orphan_pool.go index 64b7471b1..2c83ca6dc 100644 --- a/domain/miningmanager/mempool/orphan_pool.go +++ b/domain/miningmanager/mempool/orphan_pool.go @@ -8,7 +8,7 @@ type orphansPool struct { mempool *mempool allOrphans idToTransaction orphanByPreviousOutpoint previousOutpointToOrphans - previousExpireScan uint64 + lastExpireScan uint64 } func newOrphansPool(mp *mempool) *orphansPool { @@ -16,7 +16,7 @@ func newOrphansPool(mp *mempool) *orphansPool { mempool: mp, allOrphans: idToTransaction{}, orphanByPreviousOutpoint: previousOutpointToOrphans{}, - previousExpireScan: 0, + lastExpireScan: 0, } } @@ -41,5 +41,30 @@ func (op *orphansPool) removeOrphan(orphanTransactionID *externalapi.DomainTrans } func (op *orphansPool) expireOrphanTransactions() error { - panic("orphansPool.expireOrphanTransactions not implemented") // TODO (Mike) + virtualDAAScore, err := op.mempool.virtualDAAScore() + if err != nil { + return err + } + + if virtualDAAScore-op.lastExpireScan < op.mempool.config.orphanExpireScanIntervalDAAScore { + return nil + } + + for _, orphanTransaction := range op.allOrphans { + // Never expire high priority transactions + if orphanTransaction.isHighPriority { + continue + } + + // Remove all transactions whose addedAtDAAScore is older then transactionExpireIntervalDAAScore + if virtualDAAScore-orphanTransaction.addAtDAAScore > op.mempool.config.orphanExpireIntervalDAAScore { + err = op.removeOrphan(orphanTransaction.transactionID()) + if err != nil { + return err + } + } + } + + op.lastExpireScan = virtualDAAScore + return nil } diff --git a/domain/miningmanager/mempool/transactions_pool.go b/domain/miningmanager/mempool/transactions_pool.go index d21f41326..6bca3c671 100644 --- a/domain/miningmanager/mempool/transactions_pool.go +++ b/domain/miningmanager/mempool/transactions_pool.go @@ -1,6 +1,8 @@ package mempool -import "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +import ( + "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" +) type outpointToTransaction map[externalapi.DomainOutpoint]*mempoolTransaction @@ -12,6 +14,7 @@ type transactionsPool struct { highPriorityTransactions idToTransaction chainedTransactionsByPreviousOutpoint outpointToTransaction transactionsByFeeRate transactionsByFeeHeap + lastExpireScan uint64 } func newTransactionsPool(mp *mempool) *transactionsPool { @@ -21,6 +24,7 @@ func newTransactionsPool(mp *mempool) *transactionsPool { highPriorityTransactions: idToTransaction{}, chainedTransactionsByPreviousOutpoint: outpointToTransaction{}, transactionsByFeeRate: transactionsByFeeHeap{}, + lastExpireScan: 0, } } @@ -33,7 +37,32 @@ func (tp *transactionsPool) addMempoolTransaction(transaction mempoolTransaction } func (tp *transactionsPool) expireOldTransactions() error { - panic("transactionsPool.expireOldTransactions not implemented") // TODO (Mike) + 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.addAtDAAScore > tp.mempool.config.transactionExpireIntervalDAAScore { + err = tp.mempool.RemoveTransaction(mempoolTransaction.transactionID()) + if err != nil { + return err + } + } + } + + tp.lastExpireScan = virtualDAAScore + return nil } func (tp *transactionsPool) allReadyTransactions() []*externalapi.DomainTransaction {