Пример #1
0
        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));
        }
Пример #2
0
 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);
 }
Пример #3
0
            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);
            }
Пример #4
0
        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);
        }
Пример #5
0
        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);
            }
        }
Пример #6
0
        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");
        }
Пример #7
0
        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
        }
Пример #8
0
        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;
        }
Пример #9
0
        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);
        }
Пример #10
0
        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;
            }
        }
Пример #11
0
        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);
        }
Пример #12
0
        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));
        }
Пример #13
0
        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})");
                }
            }
        }
Пример #15
0
        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);
        }
Пример #16
0
        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);
                }
            }
        }
Пример #17
0
        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);
        }
Пример #18
0
        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);
        }
Пример #19
0
        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));
        }
Пример #20
0
        private ITxSender SetSender(long blockNumber)
        {
            bool posdao           = IsPosdao(blockNumber);
            bool isEip1559Enabled = _specProvider.GetSpec(blockNumber).IsEip1559Enabled;

            return(posdao ? _posdaoTxSender : (isEip1559Enabled ? _nonPosdao1559TxSender: _nonPosdaoTxSender));
        }
Пример #21
0
        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);
        }
Пример #22
0
        /// <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);
        }
Пример #23
0
        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);
        }
Пример #24
0
        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();
        }
Пример #26
0
        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);
        }
Пример #28
0
        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");
            }
        }
Пример #29
0
        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();
            }
        }
Пример #30
0
        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.");
            }
        }