public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { IReleaseSpec spec = _specProvider.GetCurrentHeadSpec(); Account account = _accounts.GetAccount(tx.SenderAddress !); UInt256 balance = account.Balance; UInt256 cumulativeCost = UInt256.Zero; bool overflow = false; Transaction[] transactions = _txs.GetBucketSnapshot(tx.SenderAddress); for (int i = 0; i < transactions.Length; i++) { if (transactions[i].Nonce < account.Nonce) { continue; } if (transactions[i].Nonce < tx.Nonce) { overflow |= UInt256.MultiplyOverflow( transactions[i].CalculateEffectiveGasPrice(spec.IsEip1559Enabled, _headInfo.CurrentBaseFee), (UInt256)transactions[i].GasLimit, out UInt256 txCost); overflow |= UInt256.AddOverflow(cumulativeCost, txCost, out cumulativeCost); overflow |= UInt256.AddOverflow(cumulativeCost, tx.Value, out cumulativeCost); } else { break; } } UInt256 affordableGasPrice = tx.CalculateAffordableGasPrice(spec.IsEip1559Enabled, _headInfo.CurrentBaseFee, balance > cumulativeCost ? balance - cumulativeCost : 0); overflow |= spec.IsEip1559Enabled && UInt256.AddOverflow(tx.MaxPriorityFeePerGas, tx.MaxFeePerGas, out _); overflow |= UInt256.MultiplyOverflow(affordableGasPrice, (UInt256)tx.GasLimit, out UInt256 cost); overflow |= UInt256.AddOverflow(cost, tx.Value, out cost); overflow |= UInt256.AddOverflow(cost, cumulativeCost, out cumulativeCost); if (overflow) { if (_logger.IsTrace) { _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, cost overflow."); } return(AcceptTxResult.Int256Overflow); } if (balance < cumulativeCost) { if (_logger.IsTrace) { _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, insufficient funds."); } return(AcceptTxResult.InsufficientFunds.WithMessage($"Account balance: {balance}, cumulative cost: {cumulativeCost}")); } return(AcceptTxResult.Accepted); }
public AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions) { IReleaseSpec spec = _specProvider.GetCurrentHeadSpec(); if (!_txValidator.IsWellFormed(tx, spec)) { // It may happen that other nodes send us transactions that were signed for another chain or don't have enough gas. if (_logger.IsTrace) { _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, invalid transaction."); } return(AcceptTxResult.Invalid); } return(AcceptTxResult.Accepted); }
public AcceptTxResult Accept(Transaction tx, TxHandlingOptions handlingOptions) { IReleaseSpec spec = _specProvider.GetCurrentHeadSpec(); Account account = _accounts.GetAccount(tx.SenderAddress !); UInt256 balance = account.Balance; UInt256 affordableGasPrice = tx.CalculateAffordableGasPrice(spec.IsEip1559Enabled, _headInfo.CurrentBaseFee, balance); bool isNotLocal = (handlingOptions & TxHandlingOptions.PersistentBroadcast) != TxHandlingOptions.PersistentBroadcast; if (_txs.IsFull() && _txs.TryGetLast(out Transaction? lastTx) && affordableGasPrice <= lastTx?.GasBottleneck && isNotLocal) { Metrics.PendingTransactionsTooLowFee++; if (_logger.IsTrace) { _logger.Trace($"Skipped adding transaction {tx.ToString(" ")}, too low payable gas price."); } return(AcceptTxResult.FeeTooLow.WithMessage($"FeePerGas needs to be higher than {lastTx.GasBottleneck.Value} to be added to the TxPool. Affordable FeePerGas of rejected tx: {affordableGasPrice}.")); } return(AcceptTxResult.Accepted); }
public AcceptTxResult Accept(Transaction tx, TxHandlingOptions txHandlingOptions) => _stateProvider.IsInvalidContractSender(_specProvider.GetCurrentHeadSpec(), tx.SenderAddress !) ? AcceptTxResult.SenderIsContract : AcceptTxResult.Accepted;