diff --git a/domain/miningmanager/mempool/model/ordered_transactions_by_fee_rate.go b/domain/miningmanager/mempool/model/ordered_transactions_by_fee_rate.go index 7550e0ea5..c631b88c6 100644 --- a/domain/miningmanager/mempool/model/ordered_transactions_by_fee_rate.go +++ b/domain/miningmanager/mempool/model/ordered_transactions_by_fee_rate.go @@ -38,8 +38,7 @@ func (tobf *TransactionsOrderedByFeeRate) Remove(transaction *MempoolTransaction return errors.Errorf("Couldn't find %s in mp.orderedTransactionsByFeeRate", txID) } - tobf.RemoveAtIndex(index) - return nil + return tobf.RemoveAtIndex(index) } // RemoveAtIndex removes the transaction at the given index. diff --git a/domain/miningmanager/mempool/model/orphan_transaction.go b/domain/miningmanager/mempool/model/orphan_transaction.go index 5169c09e7..f762d4c2a 100644 --- a/domain/miningmanager/mempool/model/orphan_transaction.go +++ b/domain/miningmanager/mempool/model/orphan_transaction.go @@ -7,12 +7,12 @@ import ( // OrphanTransaction represents a transaction in the OrphanPool type OrphanTransaction struct { - transaction *externalapi.DomainTransaction + Transaction *externalapi.DomainTransaction IsHighPriority bool AddedAtDAAScore uint64 } // TransactionID returns the ID of this OrphanTransaction func (ot *OrphanTransaction) TransactionID() *externalapi.DomainTransactionID { - return consensushashing.TransactionID(ot.transaction) + return consensushashing.TransactionID(ot.Transaction) } diff --git a/domain/miningmanager/mempool/orphan_pool.go b/domain/miningmanager/mempool/orphan_pool.go index a8d68ad3a..07aafeeef 100644 --- a/domain/miningmanager/mempool/orphan_pool.go +++ b/domain/miningmanager/mempool/orphan_pool.go @@ -3,24 +3,25 @@ package mempool import ( "github.com/kaspanet/kaspad/domain/consensus/model/externalapi" "github.com/kaspanet/kaspad/domain/miningmanager/mempool/model" + "github.com/pkg/errors" ) type idToOrphan map[externalapi.DomainTransactionID]*model.OrphanTransaction type previousOutpointToOrphans map[externalapi.DomainOutpoint]idToOrphan type orphansPool struct { - mempool *mempool - allOrphans idToOrphan - orphanByPreviousOutpoint previousOutpointToOrphans - lastExpireScan uint64 + mempool *mempool + allOrphans idToOrphan + orphansByPreviousOutpoint previousOutpointToOrphans + lastExpireScan uint64 } func newOrphansPool(mp *mempool) *orphansPool { return &orphansPool{ - mempool: mp, - allOrphans: idToOrphan{}, - orphanByPreviousOutpoint: previousOutpointToOrphans{}, - lastExpireScan: 0, + mempool: mp, + allOrphans: idToOrphan{}, + orphansByPreviousOutpoint: previousOutpointToOrphans{}, + lastExpireScan: 0, } } @@ -40,8 +41,41 @@ func (op *orphansPool) unorphanTransaction(orphanTransactionID *externalapi.Doma panic("orphansPool.unorphanTransaction not implemented") // TODO (Mike) } -func (op *orphansPool) removeOrphan(orphanTransactionID *externalapi.DomainTransactionID) error { - panic("orphansPool.removeOrphan not implemented") // TODO (Mike) +func (op *orphansPool) removeOrphan(orphanTransactionID *externalapi.DomainTransactionID, removeRedeemers bool) error { + orphanTransaction, ok := op.allOrphans[*orphanTransactionID] + if !ok { + return nil + } + + delete(op.allOrphans, orphanTransactionID) + + for i, input := range orphanTransaction.Transaction.Inputs { + orphans, ok := op.orphansByPreviousOutpoint[input.PreviousOutpoint] + if !ok { + return errors.Errorf("Input No. %d of %s (%s) doesn't exist in orphansByPreviousOutpoint", + i, orphanTransactionID, input.PreviousOutpoint) + } + delete(orphans, *orphanTransactionID) + if len(orphans) == 0 { + delete(op.orphansByPreviousOutpoint, input.PreviousOutpoint) + } + } + + if removeRedeemers { + outpoint := externalapi.DomainOutpoint{TransactionID: *orphanTransactionID} + for i := range orphanTransaction.Transaction.Outputs { + outpoint.Index = uint32(i) + for _, orphan := range op.orphansByPreviousOutpoint[outpoint] { + // Recursive call is bound by size of orphan pool (which is very small) + err := op.removeOrphan(orphan.TransactionID(), true) + if err != nil { + return err + } + } + } + } + + return nil } func (op *orphansPool) expireOrphanTransactions() error {