forked from kaspanet/kaspad
-
Notifications
You must be signed in to change notification settings - Fork 1
/
ordered_transactions_by_fee_rate.go
91 lines (73 loc) · 3.18 KB
/
ordered_transactions_by_fee_rate.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
package model
import (
"sort"
"github.com/pkg/errors"
)
// TransactionsOrderedByFeeRate represents a set of MempoolTransactions ordered by their fee / mass rate
type TransactionsOrderedByFeeRate struct {
slice []*MempoolTransaction
}
// GetByIndex returns the transaction in the given index
func (tobf *TransactionsOrderedByFeeRate) GetByIndex(index int) *MempoolTransaction {
return tobf.slice[index]
}
// Push inserts a transaction into the set, placing it in the correct place to preserve order
func (tobf *TransactionsOrderedByFeeRate) Push(transaction *MempoolTransaction) error {
index, _, err := tobf.findTransactionIndex(transaction)
if err != nil {
return err
}
tobf.slice = append(tobf.slice[:index],
append([]*MempoolTransaction{transaction}, tobf.slice[index:]...)...)
return nil
}
// ErrTransactionNotFound is returned bt tobf.TransactionsOrderedByFeeRate
var ErrTransactionNotFound = errors.New("Couldn't find transaction in mp.orderedTransactionsByFeeRate")
// Remove removes the given transaction from the set.
// Returns an error if transaction does not exist in the set, or if the given transaction does not have mass
// and fee filled in.
func (tobf *TransactionsOrderedByFeeRate) Remove(transaction *MempoolTransaction) error {
index, wasFound, err := tobf.findTransactionIndex(transaction)
if err != nil {
return err
}
if !wasFound {
return errors.Wrapf(ErrTransactionNotFound,
"Couldn't find %s in mp.orderedTransactionsByFeeRate", transaction.TransactionID())
}
return tobf.RemoveAtIndex(index)
}
// RemoveAtIndex removes the transaction at the given index.
// Returns an error in case of out-of-bounds index.
func (tobf *TransactionsOrderedByFeeRate) RemoveAtIndex(index int) error {
if index < 0 || index > len(tobf.slice)-1 {
return errors.Errorf("Index %d is out of bound of this TransactionsOrderedByFeeRate", index)
}
tobf.slice = append(tobf.slice[:index], tobf.slice[index+1:]...)
return nil
}
// findTransactionIndex finds the given transaction inside the list of transactions ordered by fee rate.
// If the transaction was not found, will return wasFound=false and index=the index at which transaction can be inserted
// while preserving the order.
func (tobf *TransactionsOrderedByFeeRate) findTransactionIndex(transaction *MempoolTransaction) (index int, wasFound bool, err error) {
if transaction.Transaction().Fee == 0 || transaction.Transaction().Mass == 0 {
return 0, false, errors.Errorf("findTransactionIndex expects a transaction with " +
"populated fee and mass")
}
txID := transaction.TransactionID()
txFeeRate := float64(transaction.Transaction().Fee) / float64(transaction.Transaction().Mass)
index = sort.Search(len(tobf.slice), func(i int) bool {
iElement := tobf.slice[i]
elementFeeRate := float64(iElement.Transaction().Fee) / float64(iElement.Transaction().Mass)
if elementFeeRate > txFeeRate {
return true
}
if elementFeeRate == txFeeRate && txID.LessOrEqual(iElement.TransactionID()) {
return true
}
return false
})
wasFound = index != len(tobf.slice) && // sort.Search returns len(tobf.slice) if nothing was found
tobf.slice[index].TransactionID().Equal(transaction.TransactionID())
return index, wasFound, nil
}