github.com/theQRL/go-zond@v0.2.1/core/txpool/validation.go (about) 1 // Copyright 2023 The go-ethereum Authors 2 // This file is part of the go-ethereum library. 3 // 4 // The go-ethereum library is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU Lesser General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // The go-ethereum library is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU Lesser General Public License for more details. 13 // 14 // You should have received a copy of the GNU Lesser General Public License 15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. 16 17 package txpool 18 19 import ( 20 "fmt" 21 "math/big" 22 23 "github.com/theQRL/go-zond/common" 24 "github.com/theQRL/go-zond/core" 25 "github.com/theQRL/go-zond/core/state" 26 "github.com/theQRL/go-zond/core/types" 27 "github.com/theQRL/go-zond/log" 28 "github.com/theQRL/go-zond/params" 29 ) 30 31 // ValidationOptions define certain differences between transaction validation 32 // across the different pools without having to duplicate those checks. 33 type ValidationOptions struct { 34 Config *params.ChainConfig // Chain configuration to selectively validate based on current fork rules 35 36 Accept uint8 // Bitmap of transaction types that should be accepted for the calling pool 37 MaxSize uint64 // Maximum size of a transaction that the caller can meaningfully handle 38 MinTip *big.Int // Minimum gas tip needed to allow a transaction into the caller pool 39 } 40 41 // ValidateTransaction is a helper method to check whether a transaction is valid 42 // according to the consensus rules, but does not check state-dependent validation 43 // (balance, nonce, etc). 44 // 45 // This check is public to allow different transaction pools to check the basic 46 // rules without duplicating code and running the risk of missed updates. 47 func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types.Signer, opts *ValidationOptions) error { 48 // Ensure transactions not implemented by the calling pool are rejected 49 if opts.Accept&(1<<tx.Type()) == 0 { 50 return fmt.Errorf("%w: tx type %v not supported by this pool", core.ErrTxTypeNotSupported, tx.Type()) 51 } 52 // Before performing any expensive validations, sanity check that the tx is 53 // smaller than the maximum limit the pool can meaningfully handle 54 if tx.Size() > opts.MaxSize { 55 return fmt.Errorf("%w: transaction size %v, limit %v", ErrOversizedData, tx.Size(), opts.MaxSize) 56 } 57 // Check whether the init code size has been exceeded 58 if tx.To() == nil && len(tx.Data()) > params.MaxInitCodeSize { 59 return fmt.Errorf("%w: code size %v, limit %v", core.ErrMaxInitCodeSizeExceeded, len(tx.Data()), params.MaxInitCodeSize) 60 } 61 // Transactions can't be negative. This may never happen using RLP decoded 62 // transactions but may occur for transactions created using the RPC. 63 if tx.Value().Sign() < 0 { 64 return ErrNegativeValue 65 } 66 // Ensure the transaction doesn't exceed the current block limit gas 67 if head.GasLimit < tx.Gas() { 68 return ErrGasLimit 69 } 70 // Sanity check for extremely large numbers (supported by RLP or RPC) 71 if tx.GasFeeCap().BitLen() > 256 { 72 return core.ErrFeeCapVeryHigh 73 } 74 if tx.GasTipCap().BitLen() > 256 { 75 return core.ErrTipVeryHigh 76 } 77 // Ensure gasFeeCap is greater than or equal to gasTipCap 78 if tx.GasFeeCapIntCmp(tx.GasTipCap()) < 0 { 79 return core.ErrTipAboveFeeCap 80 } 81 // Make sure the transaction is signed properly 82 if _, err := types.Sender(signer, tx); err != nil { 83 return ErrInvalidSender 84 } 85 // Ensure the transaction has more gas than the bare minimum needed to cover 86 // the transaction metadata 87 intrGas, err := core.IntrinsicGas(tx.Data(), tx.AccessList(), tx.To() == nil) 88 if err != nil { 89 return err 90 } 91 if tx.Gas() < intrGas { 92 return fmt.Errorf("%w: gas %v, minimum needed %v", core.ErrIntrinsicGas, tx.Gas(), intrGas) 93 } 94 // Ensure the gasprice is high enough to cover the requirement of the calling pool 95 if tx.GasTipCapIntCmp(opts.MinTip) < 0 { 96 return fmt.Errorf("%w: gas tip cap %v, minimum needed %v", ErrUnderpriced, tx.GasTipCap(), opts.MinTip) 97 } 98 99 return nil 100 } 101 102 // ValidationOptionsWithState define certain differences between stateful transaction 103 // validation across the different pools without having to duplicate those checks. 104 type ValidationOptionsWithState struct { 105 State *state.StateDB // State database to check nonces and balances against 106 107 // FirstNonceGap is an optional callback to retrieve the first nonce gap in 108 // the list of pooled transactions of a specific account. If this method is 109 // set, nonce gaps will be checked and forbidden. If this method is not set, 110 // nonce gaps will be ignored and permitted. 111 FirstNonceGap func(addr common.Address) uint64 112 113 // UsedAndLeftSlots is a mandatory callback to retrieve the number of tx slots 114 // used and the number still permitted for an account. New transactions will 115 // be rejected once the number of remaining slots reaches zero. 116 UsedAndLeftSlots func(addr common.Address) (int, int) 117 118 // ExistingExpenditure is a mandatory callback to retrieve the cumulative 119 // cost of the already pooled transactions to check for overdrafts. 120 ExistingExpenditure func(addr common.Address) *big.Int 121 122 // ExistingCost is a mandatory callback to retrieve an already pooled 123 // transaction's cost with the given nonce to check for overdrafts. 124 ExistingCost func(addr common.Address, nonce uint64) *big.Int 125 } 126 127 // ValidateTransactionWithState is a helper method to check whether a transaction 128 // is valid according to the pool's internal state checks (balance, nonce, gaps). 129 // 130 // This check is public to allow different transaction pools to check the stateful 131 // rules without duplicating code and running the risk of missed updates. 132 func ValidateTransactionWithState(tx *types.Transaction, signer types.Signer, opts *ValidationOptionsWithState) error { 133 // Ensure the transaction adheres to nonce ordering 134 from, err := signer.Sender(tx) // already validated (and cached), but cleaner to check 135 if err != nil { 136 log.Error("Transaction sender recovery failed", "err", err) 137 return err 138 } 139 next := opts.State.GetNonce(from) 140 if next > tx.Nonce() { 141 return fmt.Errorf("%w: next nonce %v, tx nonce %v", core.ErrNonceTooLow, next, tx.Nonce()) 142 } 143 // Ensure the transaction doesn't produce a nonce gap in pools that do not 144 // support arbitrary orderings 145 if opts.FirstNonceGap != nil { 146 if gap := opts.FirstNonceGap(from); gap < tx.Nonce() { 147 return fmt.Errorf("%w: tx nonce %v, gapped nonce %v", core.ErrNonceTooHigh, tx.Nonce(), gap) 148 } 149 } 150 // Ensure the transactor has enough funds to cover the transaction costs 151 var ( 152 balance = opts.State.GetBalance(from) 153 cost = tx.Cost() 154 ) 155 if balance.Cmp(cost) < 0 { 156 return fmt.Errorf("%w: balance %v, tx cost %v, overshot %v", core.ErrInsufficientFunds, balance, cost, new(big.Int).Sub(cost, balance)) 157 } 158 // Ensure the transactor has enough funds to cover for replacements or nonce 159 // expansions without overdrafts 160 spent := opts.ExistingExpenditure(from) 161 if prev := opts.ExistingCost(from, tx.Nonce()); prev != nil { 162 bump := new(big.Int).Sub(cost, prev) 163 need := new(big.Int).Add(spent, bump) 164 if balance.Cmp(need) < 0 { 165 return fmt.Errorf("%w: balance %v, queued cost %v, tx bumped %v, overshot %v", core.ErrInsufficientFunds, balance, spent, bump, new(big.Int).Sub(need, balance)) 166 } 167 } else { 168 need := new(big.Int).Add(spent, cost) 169 if balance.Cmp(need) < 0 { 170 return fmt.Errorf("%w: balance %v, queued cost %v, tx cost %v, overshot %v", core.ErrInsufficientFunds, balance, spent, cost, new(big.Int).Sub(need, balance)) 171 } 172 // Transaction takes a new nonce value out of the pool. Ensure it doesn't 173 // overflow the number of permitted transactions from a single account 174 // (i.e. max cancellable via out-of-bound transaction). 175 if used, left := opts.UsedAndLeftSlots(from); left <= 0 { 176 return fmt.Errorf("%w: pooled %d txs", ErrAccountLimitExceeded, used) 177 } 178 } 179 return nil 180 }