github.com/ledgerwatch/erigon-lib@v1.0.0/txpool/txpoolcfg/txpoolcfg.go (about)

     1  /*
     2     Copyright 2022 The Erigon contributors
     3  
     4     Licensed under the Apache License, Version 2.0 (the "License");
     5     you may not use this file except in compliance with the License.
     6     You may obtain a copy of the License at
     7  
     8         http://www.apache.org/licenses/LICENSE-2.0
     9  
    10     Unless required by applicable law or agreed to in writing, software
    11     distributed under the License is distributed on an "AS IS" BASIS,
    12     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13     See the License for the specific language governing permissions and
    14     limitations under the License.
    15  */
    16  
    17  package txpoolcfg
    18  
    19  import (
    20  	"fmt"
    21  	"math"
    22  	"math/big"
    23  	"time"
    24  
    25  	"github.com/c2h5oh/datasize"
    26  	"github.com/ledgerwatch/erigon-lib/common/fixedgas"
    27  	emath "github.com/ledgerwatch/erigon-lib/common/math"
    28  	"github.com/ledgerwatch/erigon-lib/types"
    29  )
    30  
    31  type Config struct {
    32  	DBDir                 string
    33  	TracedSenders         []string // List of senders for which tx pool should print out debugging info
    34  	SyncToNewPeersEvery   time.Duration
    35  	ProcessRemoteTxsEvery time.Duration
    36  	CommitEvery           time.Duration
    37  	LogEvery              time.Duration
    38  	PendingSubPoolLimit   int
    39  	BaseFeeSubPoolLimit   int
    40  	QueuedSubPoolLimit    int
    41  	MinFeeCap             uint64
    42  	AccountSlots          uint64 // Number of executable transaction slots guaranteed per account
    43  	BlobSlots             uint64 // Total number of blobs (not txs) allowed per account
    44  	PriceBump             uint64 // Price bump percentage to replace an already existing transaction
    45  	BlobPriceBump         uint64 //Price bump percentage to replace an existing 4844 blob tx (type-3)
    46  	OverrideCancunTime    *big.Int
    47  	MdbxPageSize          datasize.ByteSize
    48  	MdbxDBSizeLimit       datasize.ByteSize
    49  	MdbxGrowthStep        datasize.ByteSize
    50  }
    51  
    52  var DefaultConfig = Config{
    53  	SyncToNewPeersEvery:   5 * time.Second,
    54  	ProcessRemoteTxsEvery: 100 * time.Millisecond,
    55  	CommitEvery:           15 * time.Second,
    56  	LogEvery:              30 * time.Second,
    57  
    58  	PendingSubPoolLimit: 10_000,
    59  	BaseFeeSubPoolLimit: 10_000,
    60  	QueuedSubPoolLimit:  10_000,
    61  
    62  	MinFeeCap:     1,
    63  	AccountSlots:  16, //TODO: to choose right value (16 to be compatible with Geth)
    64  	BlobSlots:     48, // Default for a total of 8 txs for 6 blobs each - for hive tests
    65  	PriceBump:     10, // Price bump percentage to replace an already existing transaction
    66  	BlobPriceBump: 100,
    67  }
    68  
    69  type DiscardReason uint8
    70  
    71  const (
    72  	NotSet              DiscardReason = 0 // analog of "nil-value", means it will be set in future
    73  	Success             DiscardReason = 1
    74  	AlreadyKnown        DiscardReason = 2
    75  	Mined               DiscardReason = 3
    76  	ReplacedByHigherTip DiscardReason = 4
    77  	UnderPriced         DiscardReason = 5
    78  	ReplaceUnderpriced  DiscardReason = 6 // if a transaction is attempted to be replaced with a different one without the required price bump.
    79  	FeeTooLow           DiscardReason = 7
    80  	OversizedData       DiscardReason = 8
    81  	InvalidSender       DiscardReason = 9
    82  	NegativeValue       DiscardReason = 10 // ensure no one is able to specify a transaction with a negative value.
    83  	Spammer             DiscardReason = 11
    84  	PendingPoolOverflow DiscardReason = 12
    85  	BaseFeePoolOverflow DiscardReason = 13
    86  	QueuedPoolOverflow  DiscardReason = 14
    87  	GasUintOverflow     DiscardReason = 15
    88  	IntrinsicGas        DiscardReason = 16
    89  	RLPTooLong          DiscardReason = 17
    90  	NonceTooLow         DiscardReason = 18
    91  	InsufficientFunds   DiscardReason = 19
    92  	NotReplaced         DiscardReason = 20 // There was an existing transaction with the same sender and nonce, not enough price bump to replace
    93  	DuplicateHash       DiscardReason = 21 // There was an existing transaction with the same hash
    94  	InitCodeTooLarge    DiscardReason = 22 // EIP-3860 - transaction init code is too large
    95  	TypeNotActivated    DiscardReason = 23 // For example, an EIP-4844 transaction is submitted before Cancun activation
    96  	CreateBlobTxn       DiscardReason = 24 // Blob transactions cannot have the form of a create transaction
    97  	NoBlobs             DiscardReason = 25 // Blob transactions must have at least one blob
    98  	TooManyBlobs        DiscardReason = 26 // There's a limit on how many blobs a block (and thus any transaction) may have
    99  	UnequalBlobTxExt    DiscardReason = 27 // blob_versioned_hashes, blobs, commitments and proofs must have equal number
   100  	BlobHashCheckFail   DiscardReason = 28 // KZGcommitment's versioned hash has to be equal to blob_versioned_hash at the same index
   101  	UnmatchedBlobTxExt  DiscardReason = 29 // KZGcommitments must match the corresponding blobs and proofs
   102  	BlobTxReplace       DiscardReason = 30 // Cannot replace type-3 blob txn with another type of txn
   103  )
   104  
   105  func (r DiscardReason) String() string {
   106  	switch r {
   107  	case NotSet:
   108  		return "not set"
   109  	case Success:
   110  		return "success"
   111  	case AlreadyKnown:
   112  		return "already known"
   113  	case Mined:
   114  		return "mined"
   115  	case ReplacedByHigherTip:
   116  		return "replaced by transaction with higher tip"
   117  	case UnderPriced:
   118  		return "underpriced"
   119  	case ReplaceUnderpriced:
   120  		return "replacement transaction underpriced"
   121  	case FeeTooLow:
   122  		return "fee too low"
   123  	case OversizedData:
   124  		return "oversized data"
   125  	case InvalidSender:
   126  		return "invalid sender"
   127  	case NegativeValue:
   128  		return "negative value"
   129  	case Spammer:
   130  		return "spammer"
   131  	case PendingPoolOverflow:
   132  		return "pending sub-pool is full"
   133  	case BaseFeePoolOverflow:
   134  		return "baseFee sub-pool is full"
   135  	case QueuedPoolOverflow:
   136  		return "queued sub-pool is full"
   137  	case GasUintOverflow:
   138  		return "GasUintOverflow"
   139  	case IntrinsicGas:
   140  		return "IntrinsicGas"
   141  	case RLPTooLong:
   142  		return "RLPTooLong"
   143  	case NonceTooLow:
   144  		return "nonce too low"
   145  	case InsufficientFunds:
   146  		return "insufficient funds"
   147  	case NotReplaced:
   148  		return "could not replace existing tx"
   149  	case DuplicateHash:
   150  		return "existing tx with same hash"
   151  	case InitCodeTooLarge:
   152  		return "initcode too large"
   153  	case TypeNotActivated:
   154  		return "fork supporting this transaction type is not activated yet"
   155  	case CreateBlobTxn:
   156  		return "blob transactions cannot have the form of a create transaction"
   157  	case NoBlobs:
   158  		return "blob transactions must have at least one blob"
   159  	case TooManyBlobs:
   160  		return "max number of blobs exceeded"
   161  	case BlobTxReplace:
   162  		return "can't replace blob-txn with a non-blob-txn"
   163  	default:
   164  		panic(fmt.Sprintf("discard reason: %d", r))
   165  	}
   166  }
   167  
   168  // CalcIntrinsicGas computes the 'intrinsic gas' for a message with the given data.
   169  func CalcIntrinsicGas(dataLen, dataNonZeroLen uint64, accessList types.AccessList, isContractCreation, isHomestead, isEIP2028, isShanghai bool) (uint64, DiscardReason) {
   170  	// Set the starting gas for the raw transaction
   171  	var gas uint64
   172  	if isContractCreation && isHomestead {
   173  		gas = fixedgas.TxGasContractCreation
   174  	} else {
   175  		gas = fixedgas.TxGas
   176  	}
   177  	// Bump the required gas by the amount of transactional data
   178  	if dataLen > 0 {
   179  		// Zero and non-zero bytes are priced differently
   180  		nz := dataNonZeroLen
   181  		// Make sure we don't exceed uint64 for all data combinations
   182  		nonZeroGas := fixedgas.TxDataNonZeroGasFrontier
   183  		if isEIP2028 {
   184  			nonZeroGas = fixedgas.TxDataNonZeroGasEIP2028
   185  		}
   186  
   187  		product, overflow := emath.SafeMul(nz, nonZeroGas)
   188  		if overflow {
   189  			return 0, GasUintOverflow
   190  		}
   191  		gas, overflow = emath.SafeAdd(gas, product)
   192  		if overflow {
   193  			return 0, GasUintOverflow
   194  		}
   195  
   196  		z := dataLen - nz
   197  
   198  		product, overflow = emath.SafeMul(z, fixedgas.TxDataZeroGas)
   199  		if overflow {
   200  			return 0, GasUintOverflow
   201  		}
   202  		gas, overflow = emath.SafeAdd(gas, product)
   203  		if overflow {
   204  			return 0, GasUintOverflow
   205  		}
   206  
   207  		if isContractCreation && isShanghai {
   208  			numWords := toWordSize(dataLen)
   209  			product, overflow = emath.SafeMul(numWords, fixedgas.InitCodeWordGas)
   210  			if overflow {
   211  				return 0, GasUintOverflow
   212  			}
   213  			gas, overflow = emath.SafeAdd(gas, product)
   214  			if overflow {
   215  				return 0, GasUintOverflow
   216  			}
   217  		}
   218  	}
   219  	if accessList != nil {
   220  		product, overflow := emath.SafeMul(uint64(len(accessList)), fixedgas.TxAccessListAddressGas)
   221  		if overflow {
   222  			return 0, GasUintOverflow
   223  		}
   224  		gas, overflow = emath.SafeAdd(gas, product)
   225  		if overflow {
   226  			return 0, GasUintOverflow
   227  		}
   228  
   229  		product, overflow = emath.SafeMul(uint64(accessList.StorageKeys()), fixedgas.TxAccessListStorageKeyGas)
   230  		if overflow {
   231  			return 0, GasUintOverflow
   232  		}
   233  		gas, overflow = emath.SafeAdd(gas, product)
   234  		if overflow {
   235  			return 0, GasUintOverflow
   236  		}
   237  	}
   238  	return gas, Success
   239  }
   240  
   241  // toWordSize returns the ceiled word size required for memory expansion.
   242  func toWordSize(size uint64) uint64 {
   243  	if size > math.MaxUint64-31 {
   244  		return math.MaxUint64/32 + 1
   245  	}
   246  	return (size + 31) / 32
   247  }