refactor: mempool use context.Context (#14266)
This commit is contained in:
parent
876e1f9442
commit
f13afd12ed
@ -1,6 +1,7 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
@ -9,12 +10,12 @@ import (
|
||||
type Mempool interface {
|
||||
// Insert attempts to insert a Tx into the app-side mempool returning
|
||||
// an error upon failure.
|
||||
Insert(sdk.Context, sdk.Tx) error
|
||||
Insert(context.Context, sdk.Tx) error
|
||||
|
||||
// Select returns an Iterator over the app-side mempool. If txs are specified,
|
||||
// then they shall be incorporated into the Iterator. The Iterator must
|
||||
// closed by the caller.
|
||||
Select(sdk.Context, [][]byte) Iterator
|
||||
Select(context.Context, [][]byte) Iterator
|
||||
|
||||
// CountTx returns the number of transactions currently in the mempool.
|
||||
CountTx() int
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
package mempool
|
||||
|
||||
import (
|
||||
"context"
|
||||
crand "crypto/rand" // #nosec // crypto/rand is used for seed generation
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
@ -19,14 +20,16 @@ var (
|
||||
|
||||
var DefaultMaxTx = 0
|
||||
|
||||
// senderNonceMempool is a mempool that prioritizes transactions within a sender by nonce, the lowest first,
|
||||
// but selects a random sender on each iteration. The mempool is iterated by:
|
||||
// senderNonceMempool is a mempool that prioritizes transactions within a sender
|
||||
// by nonce, the lowest first, but selects a random sender on each iteration.
|
||||
// The mempool is iterated by:
|
||||
//
|
||||
// 1) Maintaining a separate list of nonce ordered txs per sender
|
||||
// 2) For each select iteration, randomly choose a sender and pick the next nonce ordered tx from their list
|
||||
// 3) Repeat 1,2 until the mempool is exhausted
|
||||
//
|
||||
// Note that PrepareProposal could choose to stop iteration before reaching the end if maxBytes is reached.
|
||||
// Note that PrepareProposal could choose to stop iteration before reaching the
|
||||
// end if maxBytes is reached.
|
||||
type senderNonceMempool struct {
|
||||
senders map[string]*skiplist.SkipList
|
||||
rnd *rand.Rand
|
||||
@ -41,7 +44,8 @@ type txKey struct {
|
||||
nonce uint64
|
||||
}
|
||||
|
||||
// NewSenderNonceMempool creates a new mempool that prioritizes transactions by nonce, the lowest first.
|
||||
// NewSenderNonceMempool creates a new mempool that prioritizes transactions by
|
||||
// nonce, the lowest first, picking a random sender on each iteration.
|
||||
func NewSenderNonceMempool(opts ...SenderNonceOptions) Mempool {
|
||||
senderMap := make(map[string]*skiplist.SkipList)
|
||||
existingTx := make(map[txKey]bool)
|
||||
@ -56,6 +60,7 @@ func NewSenderNonceMempool(opts ...SenderNonceOptions) Mempool {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
snp.setSeed(seed)
|
||||
|
||||
for _, opt := range opts {
|
||||
@ -65,19 +70,25 @@ func NewSenderNonceMempool(opts ...SenderNonceOptions) Mempool {
|
||||
return snp
|
||||
}
|
||||
|
||||
// SenderNonceSeedOpt Option To add a Seed for random type when calling the constructor NewSenderNonceMempool
|
||||
// SenderNonceSeedOpt Option To add a Seed for random type when calling the
|
||||
// constructor NewSenderNonceMempool.
|
||||
//
|
||||
// Example:
|
||||
// > random_seed := int64(1000)
|
||||
// > NewSenderNonceMempool(SenderNonceSeedTxOpt(random_seed))
|
||||
//
|
||||
// random_seed := int64(1000)
|
||||
// NewSenderNonceMempool(SenderNonceSeedTxOpt(random_seed))
|
||||
func SenderNonceSeedOpt(seed int64) SenderNonceOptions {
|
||||
return func(snp *senderNonceMempool) {
|
||||
snp.setSeed(seed)
|
||||
}
|
||||
}
|
||||
|
||||
// SenderNonceMaxTxOpt Option To set limit of max tx when calling the constructor NewSenderNonceMempool
|
||||
// SenderNonceMaxTxOpt Option To set limit of max tx when calling the constructor
|
||||
// NewSenderNonceMempool.
|
||||
//
|
||||
// Example:
|
||||
// > NewSenderNonceMempool(SenderNonceMaxTxOpt(100))
|
||||
//
|
||||
// NewSenderNonceMempool(SenderNonceMaxTxOpt(100))
|
||||
func SenderNonceMaxTxOpt(maxTx int) SenderNonceOptions {
|
||||
return func(snp *senderNonceMempool) {
|
||||
snp.maxTx = maxTx
|
||||
@ -89,15 +100,16 @@ func (snm *senderNonceMempool) setSeed(seed int64) {
|
||||
snm.rnd = rand.New(s1) //#nosec // math/rand is seeded from crypto/rand by default
|
||||
}
|
||||
|
||||
// Insert adds a tx to the mempool. It returns an error if the tx does not have at least one signer.
|
||||
// priority is ignored.
|
||||
func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error {
|
||||
// Insert adds a tx to the mempool. It returns an error if the tx does not have
|
||||
// at least one signer. Note, priority is ignored.
|
||||
func (snm *senderNonceMempool) Insert(_ context.Context, tx sdk.Tx) error {
|
||||
if snm.maxTx > 0 && snm.CountTx() >= snm.maxTx {
|
||||
return ErrMempoolTxMaxCapacity
|
||||
}
|
||||
if snm.maxTx < 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
|
||||
if err != nil {
|
||||
return err
|
||||
@ -109,22 +121,27 @@ func (snm *senderNonceMempool) Insert(_ sdk.Context, tx sdk.Tx) error {
|
||||
sig := sigs[0]
|
||||
sender := sig.PubKey.Address().String()
|
||||
nonce := sig.Sequence
|
||||
|
||||
senderTxs, found := snm.senders[sender]
|
||||
if !found {
|
||||
senderTxs = skiplist.New(skiplist.Uint64)
|
||||
snm.senders[sender] = senderTxs
|
||||
}
|
||||
|
||||
senderTxs.Set(nonce, tx)
|
||||
|
||||
key := txKey{nonce: nonce, address: sender}
|
||||
snm.existingTx[key] = true
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Select returns an iterator ordering transactions the mempool with the lowest nonce of a random selected sender first.
|
||||
func (snm *senderNonceMempool) Select(_ sdk.Context, _ [][]byte) Iterator {
|
||||
// Select returns an iterator ordering transactions the mempool with the lowest
|
||||
// nonce of a random selected sender first.
|
||||
func (snm *senderNonceMempool) Select(_ context.Context, _ [][]byte) Iterator {
|
||||
var senders []string
|
||||
senderCursors := make(map[string]*skiplist.Element)
|
||||
|
||||
senderCursors := make(map[string]*skiplist.Element)
|
||||
orderedSenders := skiplist.New(skiplist.String)
|
||||
|
||||
// #nosec
|
||||
@ -154,8 +171,8 @@ func (snm *senderNonceMempool) CountTx() int {
|
||||
return len(snm.existingTx)
|
||||
}
|
||||
|
||||
// Remove removes a tx from the mempool. It returns an error if the tx does not have at least one signer or the tx
|
||||
// was not found in the pool.
|
||||
// Remove removes a tx from the mempool. It returns an error if the tx does not
|
||||
// have at least one signer or the tx was not found in the pool.
|
||||
func (snm *senderNonceMempool) Remove(tx sdk.Tx) error {
|
||||
sigs, err := tx.(signing.SigVerifiableTx).GetSignaturesV2()
|
||||
if err != nil {
|
||||
@ -168,6 +185,7 @@ func (snm *senderNonceMempool) Remove(tx sdk.Tx) error {
|
||||
sig := sigs[0]
|
||||
sender := sig.PubKey.Address().String()
|
||||
nonce := sig.Sequence
|
||||
|
||||
senderTxs, found := snm.senders[sender]
|
||||
if !found {
|
||||
return ErrTxNotFound
|
||||
@ -195,8 +213,8 @@ type senderNonceMepoolIterator struct {
|
||||
senderCursors map[string]*skiplist.Element
|
||||
}
|
||||
|
||||
// Next returns the next iterator state which will contain a tx with the next smallest nonce of a randomly
|
||||
// selected sender.
|
||||
// Next returns the next iterator state which will contain a tx with the next
|
||||
// smallest nonce of a randomly selected sender.
|
||||
func (i *senderNonceMepoolIterator) Next() Iterator {
|
||||
for len(i.senders) > 0 {
|
||||
senderIndex := i.rnd.Intn(len(i.senders))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user