public ResultWrapper <TransactionWithProof> proof_getTransactionByHash(Keccak txHash, bool includeHeader) { Keccak blockHash = _receiptFinder.FindBlockHash(txHash); if (blockHash == null) { return(ResultWrapper <TransactionWithProof> .Fail($"{txHash} receipt (transaction) could not be found", ErrorCodes.ResourceNotFound)); } SearchResult <Block> searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash)); if (searchResult.IsError) { return(ResultWrapper <TransactionWithProof> .Fail(searchResult)); } Block block = searchResult.Object; TxReceipt receipt = _receiptFinder.Get(block).ForTransaction(txHash); Transaction[] txs = block.Transactions; Transaction transaction = txs[receipt.Index]; TransactionWithProof txWithProof = new TransactionWithProof(); txWithProof.Transaction = new TransactionForRpc(block.Hash, block.Number, receipt.Index, transaction); txWithProof.TxProof = BuildTxProofs(txs, _specProvider.GetSpec(block.Number), receipt.Index); if (includeHeader) { txWithProof.BlockHeader = _headerDecoder.Encode(block.Header).Bytes; } return(ResultWrapper <TransactionWithProof> .Success(txWithProof)); }
public void Berlin_eips(long blockNumber, bool isEnabled) { _specProvider.GetSpec(blockNumber).IsEip2315Enabled.Should().Be(false); _specProvider.GetSpec(blockNumber).IsEip2537Enabled.Should().Be(false); _specProvider.GetSpec(blockNumber).IsEip2565Enabled.Should().Be(isEnabled); _specProvider.GetSpec(blockNumber).IsEip2929Enabled.Should().Be(isEnabled); _specProvider.GetSpec(blockNumber).IsEip2930Enabled.Should().Be(isEnabled); }
public TestingContext(bool isEip1559Enabled = false, long eip1559TransitionBlock = 0) { ReleaseSpec releaseSpec = new(); ReleaseSpec eip1559ReleaseSpec = new() { IsEip1559Enabled = isEip1559Enabled, Eip1559TransitionBlock = eip1559TransitionBlock }; ISpecProvider specProvider = Substitute.For <ISpecProvider>(); specProvider.GetSpec(Arg.Is <long>(x => x >= eip1559TransitionBlock)).Returns(eip1559ReleaseSpec); specProvider.GetSpec(Arg.Is <long>(x => x < eip1559TransitionBlock)).Returns(releaseSpec); _blockTree = Substitute.For <IBlockTree>(); UpdateBlockTreeHead(); _transactionComparerProvider = new TransactionComparerProvider(specProvider, _blockTree); }
protected virtual TxReceipt[] ProcessBlock(Block block, IBlockTracer blockTracer, ProcessingOptions options) { TxReceipt[] receipts = ProcessTransactions(block, options, blockTracer); SetReceiptsRoot(block, receipts); ApplyMinerRewards(block, blockTracer); _stateProvider.Commit(_specProvider.GetSpec(block.Number)); _stateProvider.RecalculateStateRoot(); block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = block.Header.CalculateHash(); return(receipts); }
private void QuickFail(Transaction tx, BlockHeader block, ITxTracer txTracer, string reason) { block.GasUsed += tx.GasLimit; Address recipient = tx.To ?? ContractAddress.From(tx.SenderAddress, _stateProvider.GetNonce(tx.SenderAddress)); _stateProvider.RecalculateStateRoot(); Keccak stateRoot = _specProvider.GetSpec(block.Number).IsEip658Enabled ? null : _stateProvider.StateRoot; if (txTracer.IsTracingReceipt) { txTracer.MarkAsFailed(recipient, tx.GasLimit, Array.Empty <byte>(), reason ?? "invalid", stateRoot); } }
public void Sign(PrivateKey privateKey, Transaction transaction, UInt256 blockNumber) { _logger?.Debug($"Signing transaction: {transaction.Value} to {transaction.To} with data {transaction.Data}"); bool isEip155Enabled = _specProvider.GetSpec(blockNumber).IsEip155Enabled; Keccak hash = Keccak.Compute(Rlp.Encode(transaction, true, isEip155Enabled, _chainIdValue)); transaction.Signature = Sign(privateKey, hash); if (isEip155Enabled) { transaction.Signature.V = transaction.Signature.V + 8 + 2 * _chainIdValue; } _logger?.Debug("Transaction signed"); }
private void SetReceipts(Block block, TransactionReceipt[] receipts) { PatriciaTree receiptTree = receipts.Length > 0 ? new PatriciaTree(NullDb.Instance, Keccak.EmptyTreeHash, false) : null; for (int i = 0; i < receipts.Length; i++) { Rlp receiptRlp = Rlp.Encode(receipts[i], _specProvider.GetSpec(block.Header.Number).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None); receiptTree?.Set(Rlp.Encode(i).Bytes, receiptRlp); } receiptTree?.UpdateRootHash(); block.Header.ReceiptsRoot = receiptTree?.RootHash ?? PatriciaTree.EmptyTreeHash; block.Header.Bloom = receipts.Length > 0 ? TransactionProcessor.BuildBloom(receipts.SelectMany(r => r.Logs).ToArray()) : Bloom.Empty; // TODO not tested anywhere at the time of writing }
private void SetReceiptsRootAndBloom(Block block, TransactionReceipt[] transactionReceipts) { PatriciaTree receiptTree = transactionReceipts.Length > 0 ? new PatriciaTree(NullDb.Instance, Keccak.EmptyTreeHash, false) : null; for (int i = 0; i < transactionReceipts.Length; i++) { Rlp receiptRlp = Rlp.Encode(transactionReceipts[i], _specProvider.GetSpec(block.Header.Number).IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None); receiptTree?.Set(Rlp.Encode(i).Bytes, receiptRlp); } receiptTree?.UpdateRootHash(); block.Header.ReceiptsRoot = receiptTree?.RootHash ?? PatriciaTree.EmptyTreeHash; block.Header.Bloom = transactionReceipts.Length > 0 ? BuildBloom(transactionReceipts) : Bloom.Empty; }
private Block ProcessOne(Block suggestedBlock, ProcessingOptions options, IBlockTracer blockTracer) { if (suggestedBlock.IsGenesis) { return(suggestedBlock); } if (_specProvider.DaoBlockNumber.HasValue && _specProvider.DaoBlockNumber.Value == suggestedBlock.Header.Number) { if (_logger.IsInfo) { _logger.Info("Applying DAO transition"); } ApplyDaoTransition(); } Block block = PrepareBlockForProcessing(suggestedBlock); var receipts = ProcessTransactions(block, options, blockTracer); SetReceiptsRootAndBloom(block, receipts); ApplyMinerRewards(block, blockTracer); _stateProvider.Commit(_specProvider.GetSpec(block.Number)); block.Header.StateRoot = _stateProvider.StateRoot; block.Header.Hash = BlockHeader.CalculateHash(block.Header); if ((options & ProcessingOptions.NoValidation) == 0 && !_blockValidator.ValidateProcessedBlock(block, receipts, suggestedBlock)) { if (_logger.IsError) { _logger.Error($"Processed block is not valid {suggestedBlock.ToString(Block.Format.FullHashAndNumber)}"); } throw new InvalidBlockException(suggestedBlock.Hash); } if ((options & ProcessingOptions.StoreReceipts) != 0) { StoreTxReceipts(block, receipts); } if ((options & ProcessingOptions.StoreTraces) != 0) { StoreTraces(blockTracer as ParityLikeBlockTracer); } BlockProcessed?.Invoke(this, new BlockProcessedEventArgs(block)); return(block); }
public void Insert(Block block, params TxReceipt[] txReceipts) { txReceipts ??= Array.Empty <TxReceipt>(); if (block.Transactions.Length != txReceipts.Length) { throw new ArgumentException($"Block {block.ToString(Block.Format.FullHashAndNumber)} has different number of transactions than receipts."); } _receiptsRecovery.TryRecover(block, txReceipts); var blockNumber = block.Number; var spec = _specProvider.GetSpec(blockNumber); RlpBehaviors behaviors = spec.IsEip658Enabled ? RlpBehaviors.Eip658Receipts | RlpBehaviors.Storage : RlpBehaviors.Storage; _blocksDb.Set(block.Hash, StorageDecoder.Encode(txReceipts, behaviors).Bytes); for (int i = 0; i < txReceipts.Length; i++) { var txHash = block.Transactions[i].Hash; _transactionDb.Set(txHash, block.Hash.Bytes); } if (blockNumber < (LowestInsertedReceiptBlock ?? long.MaxValue)) { LowestInsertedReceiptBlock = blockNumber; } if (blockNumber < MigratedBlockNumber) { MigratedBlockNumber = blockNumber; } }
public bool TryRecover(Block block, TxReceipt[] receipts) { var canRecover = block.Transactions.Length == receipts?.Length; if (canRecover) { var needRecover = NeedRecover(receipts); if (needRecover) { var releaseSpec = _specProvider.GetSpec(block.Number); long gasUsedBefore = 0; for (int receiptIndex = 0; receiptIndex < block.Transactions.Length; receiptIndex++) { Transaction transaction = block.Transactions[receiptIndex]; if (receipts.Length > receiptIndex) { TxReceipt receipt = receipts[receiptIndex]; RecoverReceiptData(releaseSpec, receipt, block, transaction, receiptIndex, gasUsedBefore); gasUsedBefore = receipt.GasUsedTotal; } } } return(true); } return(false); }
public long Estimate(Transaction tx, BlockHeader header, EstimateGasTracer gasTracer) { IReleaseSpec releaseSpec = _specProvider.GetSpec(header.Number + 1); long intrinsicGas = tx.GasLimit - gasTracer.IntrinsicGasAt; if (tx.GasLimit > header.GasLimit) { return(Math.Max(intrinsicGas, gasTracer.GasSpent + gasTracer.CalculateAdditionalGasRequired(tx, releaseSpec))); } tx.SenderAddress ??= Address.Zero; //If sender is not specified, use zero address. // Setting boundaries for binary search - determine lowest and highest gas can be used during the estimation: long leftBound = (gasTracer.GasSpent != 0 && gasTracer.GasSpent >= Transaction.BaseTxGasCost) ? gasTracer.GasSpent - 1 : Transaction.BaseTxGasCost - 1; long rightBound = (tx.GasLimit != 0 && tx.GasPrice >= Transaction.BaseTxGasCost) ? tx.GasLimit : header.GasLimit; UInt256 senderBalance = _stateProvider.GetBalance(tx.SenderAddress); // Calculate and return additional gas required in case of insufficient funds. if (tx.Value != UInt256.Zero && tx.Value >= senderBalance) { return(gasTracer.CalculateAdditionalGasRequired(tx, releaseSpec)); } // Execute binary search to find the optimal gas estimation. return(BinarySearchEstimate(leftBound, rightBound, rightBound, tx, header)); }
private bool TryPrepareReceipts(BlockInfo blockInfo, TxReceipt[] receipts, out TxReceipt[]?preparedReceipts) { BlockHeader?header = _blockTree.FindHeader(blockInfo.BlockHash); if (header == null) { if (_logger.IsWarn) { _logger.Warn("Could not find header for requested blockhash."); } preparedReceipts = null; } else { if (header.ReceiptsRoot == Keccak.EmptyTreeHash) { preparedReceipts = receipts.Length == 0 ? receipts : null; } else { IReleaseSpec releaseSpec = _specProvider.GetSpec(blockInfo.BlockNumber); preparedReceipts = receipts.GetReceiptsRoot(releaseSpec, header.ReceiptsRoot) != header.ReceiptsRoot ? null : receipts; } } return(preparedReceipts != null); }
public void RecoverData(Block block) { if (block.Transactions.Length == 0 || block.Transactions[0].SenderAddress != null) { return; } var releaseSpec = _specProvider.GetSpec(block.Number); for (int i = 0; i < block.Transactions.Length; i++) { Transaction blockTransaction = block.Transactions[i]; _txPool.TryGetPendingTransaction(blockTransaction.Hash, out var transaction); Address sender = transaction?.SenderAddress; Address blockTransactionAddress = blockTransaction.SenderAddress; blockTransaction.SenderAddress = sender ?? _ecdsa.RecoverAddress(blockTransaction, !releaseSpec.ValidateChainId); if (_logger.IsTrace) { _logger.Trace($"Recovered {blockTransaction.SenderAddress} sender for {blockTransaction.Hash} (tx pool cached value: {sender}, block transaction address: {blockTransactionAddress})"); } } }
private TransactionReceipt GetNullReceipt(BlockHeader block, long gasUsed) { block.GasUsed += gasUsed; TransactionReceipt transactionReceipt = new TransactionReceipt(); transactionReceipt.Logs = LogEntry.EmptyLogs; transactionReceipt.Bloom = Bloom.Empty; transactionReceipt.GasUsed = block.GasUsed; if (!_specProvider.GetSpec(block.Number).IsEip658Enabled) { transactionReceipt.PostTransactionState = _stateProvider.StateRoot; // TODO: do not call it in Byzantium - no longer needed to calculate root hash } transactionReceipt.StatusCode = StatusCode.Failure; return(transactionReceipt); }
private void ProcessBlock(Block block, Block?previousBlock) { _txPool.BlockGasLimit = block.GasLimit; long transactionsInBlock = block.Transactions.Length; long discoveredForPendingTxs = 0; long discoveredForHashCache = 0; for (int i = 0; i < transactionsInBlock; i++) { Keccak txHash = block.Transactions[i].Hash; if (!_txPool.IsInHashCache(txHash)) { discoveredForHashCache++; } if (!_txPool.RemoveTransaction(txHash, true)) { discoveredForPendingTxs++; } } TxPool.Metrics.DarkPoolRatioLevel1 = transactionsInBlock == 0 ? 0 : (float)discoveredForHashCache / transactionsInBlock; TxPool.Metrics.DarkPoolRatioLevel2 = transactionsInBlock == 0 ? 0 : (float)discoveredForPendingTxs / transactionsInBlock; // the hash will only be the same during perf test runs / modified DB states if (previousBlock is not null) { bool isEip155Enabled = _specProvider.GetSpec(previousBlock.Number).IsEip155Enabled; for (int i = 0; i < previousBlock.Transactions.Length; i++) { Transaction tx = previousBlock.Transactions[i]; _txPool.AddTransaction(tx, (isEip155Enabled ? TxHandlingOptions.None : TxHandlingOptions.PreEip155Signing) | TxHandlingOptions.Reorganisation); } } }
public bool ValidateSuggestedBlock(Block suggestedBlock) { if (!_ommersValidator.Validate(suggestedBlock.Header, suggestedBlock.Ommers)) { _logger?.Info($"Invalid block ({suggestedBlock.Hash}) - invalid ommers"); return(false); } foreach (Transaction transaction in suggestedBlock.Transactions) { if (!_transactionValidator.IsWellFormed(transaction, _specProvider.GetSpec(suggestedBlock.Number))) { _logger?.Info($"Invalid block ({suggestedBlock.Hash}) - invalid transaction ({transaction.Hash})"); return(false); } } // TODO it may not be needed here (computing twice?) if (suggestedBlock.Header.OmmersHash != Keccak.Compute(Rlp.Encode(suggestedBlock.Ommers))) { _logger?.Info($"Invalid block ({suggestedBlock.Hash}) - invalid ommers hash"); return(false); } bool blockHeaderValid = _headerValidator.Validate(suggestedBlock.Header); if (!blockHeaderValid) { _logger?.Info($"Invalid block ({suggestedBlock.Hash}) - invalid header"); return(false); } return(true); }
private TxReceipt BuildReceipt(Address recipient, long spentGas, byte statusCode, LogEntry[] logEntries) { Transaction transaction = _block.Transactions[_currentIndex]; TxReceipt txReceipt = new TxReceipt(); txReceipt.Logs = logEntries; txReceipt.Bloom = logEntries.Length == 0 ? Bloom.Empty : new Bloom(logEntries); txReceipt.GasUsedTotal = _block.GasUsed; if (!_specProvider.GetSpec(_block.Number).IsEip658Enabled) { txReceipt.PostTransactionState = _stateProvider.StateRoot; } txReceipt.StatusCode = statusCode; txReceipt.Recipient = transaction.IsContractCreation ? null : recipient; txReceipt.BlockHash = _block.Hash; txReceipt.BlockNumber = _block.Number; txReceipt.Index = _currentIndex; txReceipt.GasUsed = spentGas; txReceipt.Sender = transaction.SenderAddress; txReceipt.ContractAddress = transaction.IsContractCreation ? recipient : null; txReceipt.TxHash = transaction.Hash; return(txReceipt); }
public int Compare(Transaction?x, Transaction?y) { if (ReferenceEquals(x, y)) { return(0); } if (ReferenceEquals(null, y)) { return(1); } if (ReferenceEquals(null, x)) { return(-1); } // if gas bottleneck was calculated, it's highest priority for sorting // if not, different method of sorting by gas price is needed if (x.GasBottleneck != null && y.GasBottleneck != null) { return(y !.GasBottleneck.Value.CompareTo(x !.GasBottleneck)); } // When we're adding Tx to TxPool we don't know the base fee of the block in which transaction will be added. // We can get a base fee from the current head. Block block = _blockFinder.Head; bool isEip1559Enabled = _specProvider.GetSpec(block?.Number ?? 0L).IsEip1559Enabled; return(GasPriceTxComparerHelper.Compare(x, y, block?.Header.BaseFeePerGas ?? UInt256.Zero, isEip1559Enabled)); }
private ITxSender SetSender(long blockNumber) { bool posdao = IsPosdao(blockNumber); bool isEip1559Enabled = _specProvider.GetSpec(blockNumber).IsEip1559Enabled; return(posdao ? _posdaoTxSender : (isEip1559Enabled ? _nonPosdao1559TxSender: _nonPosdaoTxSender)); }
public ReceiptsRecoveryResult TryRecover(Block block, TxReceipt[] receipts, bool forceRecoverSender = true) { var canRecover = block.Transactions.Length == receipts?.Length; if (canRecover) { var needRecover = NeedRecover(receipts, forceRecoverSender); if (needRecover) { var releaseSpec = _specProvider.GetSpec(block.Number); long gasUsedBefore = 0; for (int receiptIndex = 0; receiptIndex < block.Transactions.Length; receiptIndex++) { Transaction transaction = block.Transactions[receiptIndex]; if (receipts.Length > receiptIndex) { TxReceipt receipt = receipts[receiptIndex]; RecoverReceiptData(releaseSpec, receipt, block, transaction, receiptIndex, gasUsedBefore, forceRecoverSender); gasUsedBefore = receipt.GasUsedTotal; } } return(ReceiptsRecoveryResult.Success); } return(ReceiptsRecoveryResult.Skipped); } return(ReceiptsRecoveryResult.Fail); }
/// <summary> /// Suggested block validation runs basic checks that can be executed before going through the expensive EVM processing. /// </summary> /// <param name="block">A block to validate</param> /// <returns><value>True</value> if the <paramref name="block"/> is valid, otherwise <value>False</value></returns> public bool ValidateSuggestedBlock(Block block) { Transaction[] txs = block.Transactions; IReleaseSpec spec = _specProvider.GetSpec(block.Number); for (int i = 0; i < txs.Length; i++) { if (!_txValidator.IsWellFormed(txs[i], spec)) { if (_logger.IsDebug) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid transaction ({txs[i].Hash})"); } return(false); } } if (spec.MaximumUncleCount < block.Ommers.Length) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - uncle count is {block.Ommers.Length} (MAX: {spec.MaximumUncleCount})"); return(false); } if (block.Header.OmmersHash != OmmersHash.Calculate(block)) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid uncles hash"); return(false); } if (!_ommersValidator.Validate(block.Header, block.Ommers)) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid uncles"); return(false); } bool blockHeaderValid = _headerValidator.Validate(block.Header); if (!blockHeaderValid) { if (_logger.IsDebug) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) - invalid header"); } return(false); } Keccak txRoot = new TxTrie(block.Transactions).RootHash; if (txRoot != block.Header.TxRoot) { if (_logger.IsDebug) { _logger.Debug($"Invalid block ({block.ToString(Block.Format.FullHashAndNumber)}) tx root {txRoot} != stated tx root {block.Header.TxRoot}"); } return(false); } return(true); }
public void Add(TxReceipt txReceipt, bool isProcessed) { if (txReceipt == null) { throw new ArgumentNullException(nameof(txReceipt)); } var spec = _specProvider.GetSpec(txReceipt.BlockNumber); RlpBehaviors behaviors = spec.IsEip658Enabled ? RlpBehaviors.Eip658Receipts : RlpBehaviors.None; if (isProcessed) { behaviors = behaviors | RlpBehaviors.Storage; } _database.Set(txReceipt.TxHash, Rlp.Encode(txReceipt, behaviors).Bytes); }
public long GetGasLimit(BlockHeader parentHeader) { long gasLimit = parentHeader.GasLimit; long newBlockNumber = parentHeader.Number + 1; IReleaseSpec spec = _specProvider.GetSpec(newBlockNumber); gasLimit = Eip1559GasLimitAdjuster.AdjustGasLimit(spec, gasLimit, newBlockNumber); return(gasLimit); }
public void Disables_Eip158_for_system_transactions() { _stateProvider.CreateAccount(TestItem.PrivateKeyA.Address, 0.Ether()); _stateProvider.Commit(_specProvider.GetSpec(1)); var blockNumber = MainNetSpecProvider.SpuriousDragonBlockNumber + 1; Transaction tx = Build.A.SystemTransaction.SignedAndResolved(_ethereumEcdsa, TestItem.PrivateKeyA, blockNumber) .WithGasPrice(0) .WithValue(0) .TestObject; Block block = Build.A.Block.WithNumber(blockNumber).WithTransactions(tx).TestObject; BlockReceiptsTracer tracer = BuildTracer(block, tx, false, false); Execute(tracer, tx, block); _stateProvider.AccountExists(tx.SenderAddress).Should().BeTrue(); }
public int Compare(Transaction?x, Transaction?y) { // When we're adding Tx to TxPool we don't know the base fee of the block in which transaction will be added. // We can get a base fee from the current head. Block block = _blockFinder.Head; bool isEip1559Enabled = _specProvider.GetSpec(block?.Number ?? 0).IsEip1559Enabled; return(GasPriceTxComparerHelper.Compare(x, y, block?.Header.BaseFee ?? 0, isEip1559Enabled)); }
public void CalculateBerlin_should_returns_expected_results() { ISpecProvider specProvider = Substitute.For <ISpecProvider>(); specProvider.GetSpec(Arg.Any <long>()).Returns(Berlin.Instance); DifficultyCalculator difficultyCalculator = new(specProvider); UInt256 result = difficultyCalculator.Calculate(0x55f78f7, 1613570258, 0x602d20d2, 200000, false); Assert.AreEqual((UInt256)90186982, result); }
public void Sign(PrivateKey privateKey, Transaction tx, long blockNumber) { if (_logger.IsDebug) { _logger.Debug($"Signing transaction {tx.SenderAddress} -> {tx.To} ({tx.Value}) with data {tx.Data}"); } bool isEip155Enabled = _specProvider.GetSpec(blockNumber).IsEip155Enabled; Keccak hash = Keccak.Compute(Rlp.Encode(tx, true, isEip155Enabled, _chainIdValue).Bytes); tx.Signature = Sign(privateKey, hash); if (isEip155Enabled) { tx.Signature.V = tx.Signature.V + 8 + 2 * _chainIdValue; } if (_logger.IsDebug) { _logger.Debug($"Transaction {tx.SenderAddress} -> {tx.To} ({tx.Value}) signed"); } }
private void Execute(Delta delta, ITxTracer txTracer, bool readOnly) { var stateUpdate = ToStateUpdate(delta); // revert state if any fails (take snapshot) foreach (var publicEntry in delta.PublicEntries) { Execute(publicEntry, stateUpdate, txTracer); } var spec = _specProvider.GetSpec(stateUpdate.Number); _storageProvider.Commit(txTracer.IsTracingState ? txTracer : null); _stateProvider.Commit(spec, txTracer.IsTracingState ? txTracer : null); _stateProvider.RecalculateStateRoot(); if (!readOnly) { if (new Keccak(delta.StateRoot.ToByteArray()) != _stateProvider.StateRoot) { if (_logger.IsEnabled(LogEventLevel.Error)) { _logger.Error("Invalid delta state root - found {found} and should be {shouldBe}", _stateProvider.StateRoot, new Keccak(delta.StateRoot.ToByteArray())); } } // compare state roots _storageProvider.CommitTrees(); _stateProvider.CommitTree(); } else { delta.StateRoot = _stateProvider.StateRoot.ToByteString(); if (_logger.IsEnabled(LogEventLevel.Debug)) { _logger.Debug($"Setting candidate delta {delta.DeltaNumber} root to {delta.StateRoot.ToKeccak()}"); } _stateProvider.Reset(); _storageProvider.Reset(); } }
public IEnumerable <Transaction> GetTransactions(BlockHeader parent, long gasLimit) { long blockNumber = parent.Number + 1; IReleaseSpec releaseSpec = _specProvider.GetSpec(blockNumber); UInt256 baseFee = BaseFeeCalculator.Calculate(parent, releaseSpec); IDictionary <Address, Transaction[]> pendingTransactions = _transactionPool.GetPendingTransactionsBySender(); IComparer <Transaction> comparer = GetComparer(parent, new BlockPreparationContext(baseFee, blockNumber)) .ThenBy(ByHashTxComparer.Instance); // in order to sort properly and not loose transactions we need to differentiate on their identity which provided comparer might not be doing IEnumerable <Transaction> transactions = GetOrderedTransactions(pendingTransactions, comparer); if (_logger.IsDebug) { _logger.Debug($"Collecting pending transactions at block gas limit {gasLimit}."); } int selectedTransactions = 0; int i = 0; // TODO: removing transactions from TX pool here seems to be a bad practice since they will // not come back if the block is ignored? foreach (Transaction tx in transactions) { i++; if (tx.SenderAddress is null) { _transactionPool.RemoveTransaction(tx.Hash !); if (_logger.IsDebug) { _logger.Debug($"Rejecting (null sender) {tx.ToShortString()}"); } continue; } bool success = _txFilterPipeline.Execute(tx, parent); if (success) { if (_logger.IsTrace) { _logger.Trace($"Selected {tx.ToShortString()} to be potentially included in block."); } selectedTransactions++; yield return(tx); } } if (_logger.IsDebug) { _logger.Debug($"Potentially selected {selectedTransactions} out of {i} pending transactions checked."); } }