github.com/franono/tendermint@v0.32.2-0.20200527150959-749313264ce9/mempool/mempool.go (about)

     1  package mempool
     2  
     3  import (
     4  	"fmt"
     5  
     6  	abci "github.com/franono/tendermint/abci/types"
     7  	"github.com/franono/tendermint/p2p"
     8  	"github.com/franono/tendermint/types"
     9  )
    10  
    11  // Mempool defines the mempool interface.
    12  //
    13  // Updates to the mempool need to be synchronized with committing a block so
    14  // apps can reset their transient state on Commit.
    15  type Mempool interface {
    16  	// CheckTx executes a new transaction against the application to determine
    17  	// its validity and whether it should be added to the mempool.
    18  	CheckTx(tx types.Tx, callback func(*abci.Response), txInfo TxInfo) error
    19  
    20  	// ReapMaxBytesMaxGas reaps transactions from the mempool up to maxBytes
    21  	// bytes total with the condition that the total gasWanted must be less than
    22  	// maxGas.
    23  	// If both maxes are negative, there is no cap on the size of all returned
    24  	// transactions (~ all available transactions).
    25  	ReapMaxBytesMaxGas(maxBytes, maxGas int64) types.Txs
    26  
    27  	// ReapMaxTxs reaps up to max transactions from the mempool.
    28  	// If max is negative, there is no cap on the size of all returned
    29  	// transactions (~ all available transactions).
    30  	ReapMaxTxs(max int) types.Txs
    31  
    32  	// Lock locks the mempool. The consensus must be able to hold lock to safely update.
    33  	Lock()
    34  
    35  	// Unlock unlocks the mempool.
    36  	Unlock()
    37  
    38  	// Update informs the mempool that the given txs were committed and can be discarded.
    39  	// NOTE: this should be called *after* block is committed by consensus.
    40  	// NOTE: Lock/Unlock must be managed by caller
    41  	Update(
    42  		blockHeight int64,
    43  		blockTxs types.Txs,
    44  		deliverTxResponses []*abci.ResponseDeliverTx,
    45  		newPreFn PreCheckFunc,
    46  		newPostFn PostCheckFunc,
    47  	) error
    48  
    49  	// FlushAppConn flushes the mempool connection to ensure async reqResCb calls are
    50  	// done. E.g. from CheckTx.
    51  	// NOTE: Lock/Unlock must be managed by caller
    52  	FlushAppConn() error
    53  
    54  	// Flush removes all transactions from the mempool and cache
    55  	Flush()
    56  
    57  	// TxsAvailable returns a channel which fires once for every height,
    58  	// and only when transactions are available in the mempool.
    59  	// NOTE: the returned channel may be nil if EnableTxsAvailable was not called.
    60  	TxsAvailable() <-chan struct{}
    61  
    62  	// EnableTxsAvailable initializes the TxsAvailable channel, ensuring it will
    63  	// trigger once every height when transactions are available.
    64  	EnableTxsAvailable()
    65  
    66  	// Size returns the number of transactions in the mempool.
    67  	Size() int
    68  
    69  	// TxsBytes returns the total size of all txs in the mempool.
    70  	TxsBytes() int64
    71  
    72  	// InitWAL creates a directory for the WAL file and opens a file itself. If
    73  	// there is an error, it will be of type *PathError.
    74  	InitWAL() error
    75  
    76  	// CloseWAL closes and discards the underlying WAL file.
    77  	// Any further writes will not be relayed to disk.
    78  	CloseWAL()
    79  }
    80  
    81  //--------------------------------------------------------------------------------
    82  
    83  // PreCheckFunc is an optional filter executed before CheckTx and rejects
    84  // transaction if false is returned. An example would be to ensure that a
    85  // transaction doesn't exceeded the block size.
    86  type PreCheckFunc func(types.Tx) error
    87  
    88  // PostCheckFunc is an optional filter executed after CheckTx and rejects
    89  // transaction if false is returned. An example would be to ensure a
    90  // transaction doesn't require more gas than available for the block.
    91  type PostCheckFunc func(types.Tx, *abci.ResponseCheckTx) error
    92  
    93  // TxInfo are parameters that get passed when attempting to add a tx to the
    94  // mempool.
    95  type TxInfo struct {
    96  	// SenderID is the internal peer ID used in the mempool to identify the
    97  	// sender, storing 2 bytes with each tx instead of 20 bytes for the p2p.ID.
    98  	SenderID uint16
    99  	// SenderP2PID is the actual p2p.ID of the sender, used e.g. for logging.
   100  	SenderP2PID p2p.ID
   101  }
   102  
   103  //--------------------------------------------------------------------------------
   104  
   105  // PreCheckAminoMaxBytes checks that the size of the transaction plus the amino
   106  // overhead is smaller or equal to the expected maxBytes.
   107  func PreCheckAminoMaxBytes(maxBytes int64) PreCheckFunc {
   108  	return func(tx types.Tx) error {
   109  		// We have to account for the amino overhead in the tx size as well
   110  		// NOTE: fieldNum = 1 as types.Block.Data contains Txs []Tx as first field.
   111  		// If this field order ever changes this needs to updated here accordingly.
   112  		// NOTE: if some []Tx are encoded without a parenting struct, the
   113  		// fieldNum is also equal to 1.
   114  		aminoOverhead := types.ComputeAminoOverhead(tx, 1)
   115  		txSize := int64(len(tx)) + aminoOverhead
   116  		if txSize > maxBytes {
   117  			return fmt.Errorf("tx size (including amino overhead) is too big: %d, max: %d",
   118  				txSize, maxBytes)
   119  		}
   120  		return nil
   121  	}
   122  }
   123  
   124  // PostCheckMaxGas checks that the wanted gas is smaller or equal to the passed
   125  // maxGas. Returns nil if maxGas is -1.
   126  func PostCheckMaxGas(maxGas int64) PostCheckFunc {
   127  	return func(tx types.Tx, res *abci.ResponseCheckTx) error {
   128  		if maxGas == -1 {
   129  			return nil
   130  		}
   131  		if res.GasWanted < 0 {
   132  			return fmt.Errorf("gas wanted %d is negative",
   133  				res.GasWanted)
   134  		}
   135  		if res.GasWanted > maxGas {
   136  			return fmt.Errorf("gas wanted %d is greater than max gas %d",
   137  				res.GasWanted, maxGas)
   138  		}
   139  		return nil
   140  	}
   141  }