core: add policy check to mempool

After block was stored it's possible to have new FeePerByte constraint,
so we should remove all transactions which do not meet this requirement.
Also caching of FeePerByte was added in order not to re-verify
transactions each time mempool needs to be updated.
This commit is contained in:
Anna Shaleva 2020-06-17 15:29:56 +03:00
parent ce402a70d2
commit 9f11a55bd6

View file

@ -46,7 +46,8 @@ type Pool struct {
verifiedTxes items
fees map[util.Uint160]utilityBalanceAndFees
capacity int
capacity int
feePerByte util.Fixed8
}
func (p items) Len() int { return len(p) }
@ -218,12 +219,13 @@ func (mp *Pool) Remove(hash util.Uint256) {
// drop part of the mempool that is now invalid after the block acceptance.
func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer) {
mp.lock.Lock()
policyChanged := mp.loadPolicy(feer)
// We can reuse already allocated slice
// because items are iterated one-by-one in increasing order.
newVerifiedTxes := mp.verifiedTxes[:0]
mp.fees = make(map[util.Uint160]utilityBalanceAndFees) // it'd be nice to reuse existing map, but we can't easily clear it
for _, itm := range mp.verifiedTxes {
if isOK(itm.txn) && mp.tryAddSendersFee(itm.txn, feer) {
if isOK(itm.txn) && mp.checkPolicy(itm.txn, policyChanged) && mp.tryAddSendersFee(itm.txn, feer) {
newVerifiedTxes = append(newVerifiedTxes, itm)
} else {
delete(mp.verifiedMap, itm.txn.Hash())
@ -233,6 +235,25 @@ func (mp *Pool) RemoveStale(isOK func(*transaction.Transaction) bool, feer Feer)
mp.lock.Unlock()
}
// loadPolicy updates feePerByte field and returns whether policy has been
// changed.
func (mp *Pool) loadPolicy(feer Feer) bool {
newFeePerByte := feer.FeePerByte()
if newFeePerByte.GreaterThan(mp.feePerByte) {
mp.feePerByte = newFeePerByte
return true
}
return false
}
// checkPolicy checks whether transaction fits policy.
func (mp *Pool) checkPolicy(tx *transaction.Transaction, policyChanged bool) bool {
if !policyChanged || tx.FeePerByte() >= mp.feePerByte {
return true
}
return false
}
// NewMemPool returns a new Pool struct.
func NewMemPool(capacity int) Pool {
return Pool{