private bool AddTransaction(Transaction tx) { if (Blockchain.Default == null) { return(false); } lock (MemoryPool) { if (MemoryPool.ContainsKey(tx.Hash)) { return(false); } if (Blockchain.Default.ContainsTransaction(tx.Hash)) { return(false); } if (!tx.Verify(MemoryPool.Values)) { return(false); } AddingTransactionEventArgs args = new AddingTransactionEventArgs(tx); AddingTransaction?.Invoke(this, args); if (!args.Cancel) { MemoryPool.Add(tx.Hash, tx); } return(!args.Cancel); } }
private bool AddTransaction(Transaction tx) { if (Blockchain.Default == null) { return(false); } lock (MemoryPool) { if (MemoryPool.ContainsKey(tx.Hash)) { return(false); } if (MemoryPool.Values.SelectMany(p => p.GetAllInputs()).Intersect(tx.GetAllInputs()).Count() > 0) { return(false); } if (Blockchain.Default.ContainsTransaction(tx.Hash)) { return(false); } if (!tx.Verify()) { return(false); } AddingTransactionEventArgs args = new AddingTransactionEventArgs(tx); AddingTransaction?.Invoke(this, args); if (!args.Cancel) { MemoryPool.Add(tx.Hash, tx); } return(!args.Cancel); } }
public AddingTxEventArgs CanAddTransaction(Block block, Transaction currentTx, IReadOnlySet <Transaction> transactionsInBlock, IStateProvider stateProvider) { AddingTxEventArgs args = new(transactionsInBlock.Count, currentTx, block, transactionsInBlock); long gasRemaining = block.Header.GasLimit - block.GasUsed; // No more gas available in block for any transactions, // the only case we have to really stop if (GasCostOf.Transaction > gasRemaining) { return(args.Set(TxAction.Stop, "Block full")); } if (currentTx.SenderAddress is null) { return(args.Set(TxAction.Skip, "Null sender")); } if (currentTx.GasLimit > gasRemaining) { return(args.Set(TxAction.Skip, $"Not enough gas in block, gas limit {currentTx.GasLimit} > {gasRemaining}")); } if (transactionsInBlock.Contains(currentTx)) { return(args.Set(TxAction.Skip, "Transaction already in block")); } IReleaseSpec spec = _specProvider.GetSpec(block.Number); if (stateProvider.IsInvalidContractSender(spec, currentTx.SenderAddress)) { return(args.Set(TxAction.Skip, $"Sender is contract")); } UInt256 expectedNonce = stateProvider.GetNonce(currentTx.SenderAddress); if (expectedNonce != currentTx.Nonce) { return(args.Set(TxAction.Skip, $"Invalid nonce - expected {expectedNonce}")); } UInt256 balance = stateProvider.GetBalance(currentTx.SenderAddress); if (!HasEnoughFounds(currentTx, balance, args, block, spec)) { return(args); } AddingTransaction?.Invoke(this, args); return(args); }