mirror of
https://github.com/tendermint/tendermint.git
synced 2025-12-23 06:15:19 +00:00
* Updated mocks * add reactor tests * add v1 reactor tests * Fix fuzz test for priority mempool * e2e adapted to mempool v1; prio pool is default now * Reverted default mempool to be fifo * Changed buf version * Added priority mempool to ci testnet * Fixed linter * Updated makefile * Aligned makefile changes to v0.34.x * Added go install for proto * Add log message to warn about prioritized mempool bug Signed-off-by: Thane Thomson <connect@thanethomson.com> * Changelog message Co-authored-by: Jasmina Malicevic <jasmina.dustinac@gmail.com> Co-authored-by: Callum Waters <cmwaters19@gmail.com> Co-authored-by: Sam Kleinman <garen@tychoish.com> Co-authored-by: Thane Thomson <connect@thanethomson.com>
194 lines
5.5 KiB
Go
194 lines
5.5 KiB
Go
package mempool
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"errors"
|
|
"fmt"
|
|
"math"
|
|
|
|
abci "github.com/tendermint/tendermint/abci/types"
|
|
"github.com/tendermint/tendermint/types"
|
|
)
|
|
|
|
const (
|
|
MempoolChannel = byte(0x30)
|
|
|
|
// PeerCatchupSleepIntervalMS defines how much time to sleep if a peer is behind
|
|
PeerCatchupSleepIntervalMS = 100
|
|
|
|
// UnknownPeerID is the peer ID to use when running CheckTx when there is
|
|
// no peer (e.g. RPC)
|
|
UnknownPeerID uint16 = 0
|
|
|
|
MaxActiveIDs = math.MaxUint16
|
|
)
|
|
|
|
// Mempool defines the mempool interface.
|
|
//
|
|
// Updates to the mempool need to be synchronized with committing a block so
|
|
// applications can reset their transient state on Commit.
|
|
type Mempool interface {
|
|
// CheckTx executes a new transaction against the application to determine
|
|
// its validity and whether it should be added to the mempool.
|
|
CheckTx(tx types.Tx, callback func(*abci.Response), txInfo TxInfo) error
|
|
|
|
// RemoveTxByKey removes a transaction, identified by its key,
|
|
// from the mempool.
|
|
RemoveTxByKey(txKey types.TxKey) error
|
|
|
|
// ReapMaxBytesMaxGas reaps transactions from the mempool up to maxBytes
|
|
// bytes total with the condition that the total gasWanted must be less than
|
|
// maxGas.
|
|
//
|
|
// If both maxes are negative, there is no cap on the size of all returned
|
|
// transactions (~ all available transactions).
|
|
ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs
|
|
|
|
// ReapMaxTxs reaps up to max transactions from the mempool. If max is
|
|
// negative, there is no cap on the size of all returned transactions
|
|
// (~ all available transactions).
|
|
ReapMaxTxs(max int) types.Txs
|
|
|
|
// Lock locks the mempool. The consensus must be able to hold lock to safely
|
|
// update.
|
|
Lock()
|
|
|
|
// Unlock unlocks the mempool.
|
|
Unlock()
|
|
|
|
// Update informs the mempool that the given txs were committed and can be
|
|
// discarded.
|
|
//
|
|
// NOTE:
|
|
// 1. This should be called *after* block is committed by consensus.
|
|
// 2. Lock/Unlock must be managed by the caller.
|
|
Update(
|
|
blockHeight int64,
|
|
blockTxs types.Txs,
|
|
deliverTxResponses []*abci.ResponseDeliverTx,
|
|
newPreFn PreCheckFunc,
|
|
newPostFn PostCheckFunc,
|
|
) error
|
|
|
|
// FlushAppConn flushes the mempool connection to ensure async callback calls
|
|
// are done, e.g. from CheckTx.
|
|
//
|
|
// NOTE:
|
|
// 1. Lock/Unlock must be managed by caller.
|
|
FlushAppConn() error
|
|
|
|
// Flush removes all transactions from the mempool and caches.
|
|
Flush()
|
|
|
|
// TxsAvailable returns a channel which fires once for every height, and only
|
|
// when transactions are available in the mempool.
|
|
//
|
|
// NOTE:
|
|
// 1. The returned channel may be nil if EnableTxsAvailable was not called.
|
|
TxsAvailable() <-chan struct{}
|
|
|
|
// EnableTxsAvailable initializes the TxsAvailable channel, ensuring it will
|
|
// trigger once every height when transactions are available.
|
|
EnableTxsAvailable()
|
|
|
|
// Size returns the number of transactions in the mempool.
|
|
Size() int
|
|
|
|
// SizeBytes returns the total size of all txs in the mempool.
|
|
SizeBytes() int64
|
|
}
|
|
|
|
// PreCheckFunc is an optional filter executed before CheckTx and rejects
|
|
// transaction if false is returned. An example would be to ensure that a
|
|
// transaction doesn't exceeded the block size.
|
|
type PreCheckFunc func(types.Tx) error
|
|
|
|
// PostCheckFunc is an optional filter executed after CheckTx and rejects
|
|
// transaction if false is returned. An example would be to ensure a
|
|
// transaction doesn't require more gas than available for the block.
|
|
type PostCheckFunc func(types.Tx, *abci.ResponseCheckTx) error
|
|
|
|
// PreCheckMaxBytes checks that the size of the transaction is smaller or equal
|
|
// to the expected maxBytes.
|
|
func PreCheckMaxBytes(maxBytes int64) PreCheckFunc {
|
|
return func(tx types.Tx) error {
|
|
txSize := types.ComputeProtoSizeForTxs([]types.Tx{tx})
|
|
|
|
if txSize > maxBytes {
|
|
return fmt.Errorf("tx size is too big: %d, max: %d", txSize, maxBytes)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// PostCheckMaxGas checks that the wanted gas is smaller or equal to the passed
|
|
// maxGas. Returns nil if maxGas is -1.
|
|
func PostCheckMaxGas(maxGas int64) PostCheckFunc {
|
|
return func(tx types.Tx, res *abci.ResponseCheckTx) error {
|
|
if maxGas == -1 {
|
|
return nil
|
|
}
|
|
if res.GasWanted < 0 {
|
|
return fmt.Errorf("gas wanted %d is negative",
|
|
res.GasWanted)
|
|
}
|
|
if res.GasWanted > maxGas {
|
|
return fmt.Errorf("gas wanted %d is greater than max gas %d",
|
|
res.GasWanted, maxGas)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
}
|
|
|
|
// ErrTxInCache is returned to the client if we saw tx earlier
|
|
var ErrTxInCache = errors.New("tx already exists in cache")
|
|
|
|
// TxKey is the fixed length array key used as an index.
|
|
type TxKey [sha256.Size]byte
|
|
|
|
// ErrTxTooLarge defines an error when a transaction is too big to be sent in a
|
|
// message to other peers.
|
|
type ErrTxTooLarge struct {
|
|
Max int
|
|
Actual int
|
|
}
|
|
|
|
func (e ErrTxTooLarge) Error() string {
|
|
return fmt.Sprintf("Tx too large. Max size is %d, but got %d", e.Max, e.Actual)
|
|
}
|
|
|
|
// ErrMempoolIsFull defines an error where Tendermint and the application cannot
|
|
// handle that much load.
|
|
type ErrMempoolIsFull struct {
|
|
NumTxs int
|
|
MaxTxs int
|
|
TxsBytes int64
|
|
MaxTxsBytes int64
|
|
}
|
|
|
|
func (e ErrMempoolIsFull) Error() string {
|
|
return fmt.Sprintf(
|
|
"mempool is full: number of txs %d (max: %d), total txs bytes %d (max: %d)",
|
|
e.NumTxs,
|
|
e.MaxTxs,
|
|
e.TxsBytes,
|
|
e.MaxTxsBytes,
|
|
)
|
|
}
|
|
|
|
// ErrPreCheck defines an error where a transaction fails a pre-check.
|
|
type ErrPreCheck struct {
|
|
Reason error
|
|
}
|
|
|
|
func (e ErrPreCheck) Error() string {
|
|
return e.Reason.Error()
|
|
}
|
|
|
|
// IsPreCheckError returns true if err is due to pre check failure.
|
|
func IsPreCheckError(err error) bool {
|
|
return errors.As(err, &ErrPreCheck{})
|
|
}
|