github.com/evdatsion/aphelion-dpos-bft@v0.32.1/mempool/mempool.go (about)

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