Beispiel #1
0
        public ResultWrapper <TransactionForRpc> eth_getTransactionByBlockNumberAndIndex(BlockParameter blockParameter, UInt256 positionIndex)
        {
            SearchResult <Block> searchResult = _blockFinder.SearchForBlock(blockParameter);

            if (searchResult.IsError)
            {
                return(ResultWrapper <TransactionForRpc> .Fail(searchResult));
            }

            Block block = searchResult.Object;

            if (positionIndex < 0 || positionIndex > block.Transactions.Length - 1)
            {
                return(ResultWrapper <TransactionForRpc> .Fail("Position Index is incorrect", ErrorCodes.InvalidParams));
            }

            Transaction transaction = block.Transactions[(int)positionIndex];

            RecoverTxSenderIfNeeded(transaction);

            TransactionForRpc transactionModel = new TransactionForRpc(block.Hash, block.Number, (int)positionIndex, transaction);

            if (_logger.IsDebug)
            {
                _logger.Debug($"eth_getTransactionByBlockNumberAndIndex request {blockParameter}, index: {positionIndex}, result: {transactionModel.Hash}");
            }
            return(ResultWrapper <TransactionForRpc> .Success(transactionModel));
        }
Beispiel #2
0
    public ResultWrapper <TransactionForRpc> eth_getTransactionByBlockHashAndIndex(Keccak blockHash,
                                                                                   UInt256 positionIndex)
    {
        SearchResult <Block> searchResult = _blockFinder.SearchForBlock(new BlockParameter(blockHash));

        if (searchResult.IsError)
        {
            return(ResultWrapper <TransactionForRpc> .Fail(searchResult));
        }

        Block block = searchResult.Object;

        if (positionIndex < 0 || positionIndex > block.Transactions.Length - 1)
        {
            return(ResultWrapper <TransactionForRpc> .Fail("Position Index is incorrect", ErrorCodes.InvalidParams));
        }

        Transaction transaction = block.Transactions[(int)positionIndex];

        RecoverTxSenderIfNeeded(transaction);

        TransactionForRpc transactionModel = new(block.Hash, block.Number, (int)positionIndex, transaction, block.BaseFeePerGas);

        return(ResultWrapper <TransactionForRpc> .Success(transactionModel));
    }
Beispiel #3
0
 public void RecoverTxSenders(Block block)
 {
     for (int i = 0; i < block.Transactions.Length; i++)
     {
         RecoverTxSender(block.Transactions[i], block.Number);
     }
 }
Beispiel #4
0
        private static void LoadGenesisBlock(
            ChainSpec chainSpec,
            Keccak expectedGenesisHash,
            IBlockTree blockTree,
            IStateProvider stateProvider,
            ISpecProvider specProvider)
        {
            // if we already have a database with blocks then we do not need to load genesis from spec
            if (blockTree.Genesis != null)
            {
                return;
            }

            foreach ((Address address, (UInt256 balance, byte[] code)) in chainSpec.Allocations)
            {
                stateProvider.CreateAccount(address, balance);
                if (code != null)
                {
                    Keccak codeHash = stateProvider.UpdateCode(code);
                    stateProvider.UpdateCodeHash(address, codeHash, specProvider.GenesisSpec);
                }
            }

            stateProvider.Commit(specProvider.GenesisSpec);

            Block genesis = chainSpec.Genesis;

            genesis.StateRoot = stateProvider.StateRoot;
            genesis.Hash      = BlockHeader.CalculateHash(genesis.Header);

            ManualResetEventSlim genesisProcessedEvent = new ManualResetEventSlim(false);

            bool genesisLoaded = false;

            void GenesisProcessed(object sender, BlockEventArgs args)
            {
                genesisLoaded           = true;
                blockTree.NewHeadBlock -= GenesisProcessed;
                genesisProcessedEvent.Set();
            }

            blockTree.NewHeadBlock += GenesisProcessed;
            blockTree.SuggestBlock(genesis);
            genesisProcessedEvent.Wait(TimeSpan.FromSeconds(5));
            if (!genesisLoaded)
            {
                throw new BlockchainException("Genesis block processing failure");
            }

            // if expectedGenesisHash is null here then it means that we do not care about the exact value in advance (e.g. in test scenarios)
            if (expectedGenesisHash != null && blockTree.Genesis.Hash != expectedGenesisHash)
            {
                throw new Exception($"Unexpected genesis hash, expected {expectedGenesisHash}, but was {blockTree.Genesis.Hash}");
            }
        }
 public void RecoverTxSenders(Block block)
 {
     for (int i = 0; i < block.Transactions.Length; i++)
     {
         var transaction = block.Transactions[i];
         if (transaction.SenderAddress == null)
         {
             RecoverTxSender(transaction, block.Number);
         }
     }
 }
Beispiel #6
0
        public (TxReceipt Receipt, Transaction Transaction) GetTransaction(Keccak transactionHash)
        {
            TxReceipt txReceipt = _receiptStorage.Find(transactionHash);

            if (txReceipt?.BlockHash == null)
            {
                return(null, null);
            }

            Block block = _blockTree.FindBlock(txReceipt.BlockHash, BlockTreeLookupOptions.RequireCanonical);

            return(txReceipt, block?.Transactions[txReceipt.Index]);
        }
        public (TransactionReceipt Receipt, Transaction Transaction) GetTransaction(Keccak transactionHash)
        {
            TransactionReceipt receipt = _receiptStorage.Get(transactionHash);

            if (receipt.BlockHash == null)
            {
                return(null, null);
            }

            Block block = _blockTree.FindBlock(receipt.BlockHash, true);

            return(receipt, block.Transactions[receipt.Index]);
        }
        public long EstimateGas(Block block, Transaction transaction)
        {
            _stateProvider.StateRoot = _blockTree.Head.StateRoot;
            BlockHeader header = new BlockHeader(block.Hash, Keccak.OfAnEmptySequenceRlp, block.Beneficiary,
                                                 block.Difficulty, block.Number + 1, block.GasLimit, block.Timestamp + 1, Bytes.Empty);

            transaction.Nonce = _stateProvider.GetNonce(transaction.SenderAddress);
            transaction.Hash  = Nethermind.Core.Transaction.CalculateHash(transaction);
            CallOutputTracer callOutputTracer = new CallOutputTracer();

            _transactionProcessor.CallAndRestore(transaction, header, callOutputTracer);
            _stateProvider.Reset();
            return(callOutputTracer.GasSpent);
        }
        public void Can_serialize_reward()
        {
            Block        block       = Build.A.Block.WithNumber(long.Parse("4563918244f40000".AsSpan(), NumberStyles.AllowHexSpecifier)).TestObject;
            IBlockTracer blockTracer = new ParityLikeBlockTracer(ParityTraceTypes.Trace | ParityTraceTypes.StateDiff);

            blockTracer.StartNewBlockTrace(block);
            ITxTracer txTracer = blockTracer.StartNewTxTrace(null);

            txTracer.ReportBalanceChange(TestItem.AddressA, 0, 3.Ether());
            blockTracer.EndTxTrace();
            blockTracer.ReportReward(TestItem.AddressA, "block", UInt256.One);

            ParityLikeTxTrace trace = ((ParityLikeBlockTracer)blockTracer).BuildResult().SingleOrDefault();

            TestOneWaySerialization(trace, "{\"trace\":[{\"action\":{\"callType\":\"reward\",\"from\":null,\"gas\":\"0x0\",\"input\":null,\"to\":null,\"value\":\"0x1\"},\"blockHash\":\"0xfed4f714d3626e046786ef043cbb30a4b87cdc288469d0b70e4529bbd4e15396\",\"blockNumber\":\"0x4563918244f40000\",\"result\":{\"gasUsed\":\"0x0\",\"output\":null},\"subtraces\":0,\"traceAddress\":\"[]\",\"transactionHash\":null,\"transactionPosition\":null,\"type\":\"reward\"}],\"stateDiff\":{\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\":{\"balance\":{\"*\":{\"from\":\"0x0\",\"to\":\"0x29a2241af62c0000\"}},\"code\":\"=\",\"nonce\":\"=\",\"storage\":{}}}}");
        }
        public void Can_serialize_reward_state_only()
        {
            Block        block       = Build.A.Block.WithNumber(long.Parse("4563918244f40000".AsSpan(), NumberStyles.AllowHexSpecifier)).TestObject;
            IBlockTracer blockTracer = new ParityLikeBlockTracer(ParityTraceTypes.StateDiff);

            blockTracer.StartNewBlockTrace(block);
            ITxTracer txTracer = blockTracer.StartNewTxTrace(null);

            txTracer.ReportBalanceChange(TestItem.AddressA, 0, 3.Ether());
            blockTracer.EndTxTrace();
            blockTracer.ReportReward(TestItem.AddressA, "block", UInt256.One);

            ParityLikeTxTrace trace = ((ParityLikeBlockTracer)blockTracer).BuildResult().SingleOrDefault();

            TestOneWaySerialization(trace, "{\"trace\":null,\"stateDiff\":{\"0xb7705ae4c6f81b66cdb323c65f4e8133690fc099\":{\"balance\":{\"*\":{\"from\":\"0x0\",\"to\":\"0x29a2241af62c0000\"}},\"code\":\"=\",\"nonce\":\"=\",\"storage\":{}}}}");
        }
Beispiel #11
0
        public (TxReceipt Receipt, UInt256?EffectiveGasPrice) GetReceiptAndEffectiveGasPrice(Keccak txHash)
        {
            Keccak blockHash = _receiptFinder.FindBlockHash(txHash);

            if (blockHash != null)
            {
                Block       block             = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                TxReceipt   txReceipt         = _receiptFinder.Get(block).ForTransaction(txHash);
                Transaction tx                = block?.Transactions[txReceipt.Index];
                bool        is1559Enabled     = _specProvider.GetSpec(block.Number).IsEip1559Enabled;
                UInt256     effectiveGasPrice = tx.CalculateEffectiveGasPrice(is1559Enabled, block.Header.BaseFeePerGas);

                return(txReceipt, effectiveGasPrice);
            }

            return(null, null);
        }
Beispiel #12
0
        public (TxReceipt Receipt, Transaction Transaction) GetTransaction(Keccak transactionHash)
        {
            TxReceipt txReceipt = _receiptStorage.Find(transactionHash);

            if (txReceipt?.BlockHash != null)
            {
                Block block = _blockTree.FindBlock(txReceipt.BlockHash, BlockTreeLookupOptions.RequireCanonical);
                return(txReceipt, block?.Transactions[txReceipt.Index]);
            }
            else if (_txPool.TryGetPendingTransaction(transactionHash, out var transaction))
            {
                return(null, transaction);
            }
            else
            {
                return(null, null);
            }
        }
Beispiel #13
0
        public (TxReceipt Receipt, Transaction Transaction, UInt256?baseFee) GetTransaction(Keccak txHash)
        {
            Keccak blockHash = _receiptFinder.FindBlockHash(txHash);

            if (blockHash is not null)
            {
                Block     block     = _processingEnv.BlockTree.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                TxReceipt txReceipt = _receiptFinder.Get(block).ForTransaction(txHash);
                return(txReceipt, block?.Transactions[txReceipt.Index], block?.BaseFeePerGas);
            }

            if (_txPool.TryGetPendingTransaction(txHash, out Transaction? transaction))
            {
                return(null, transaction, null);
            }

            return(null, null, null);
        }
Beispiel #14
0
        public (TxReceipt Receipt, Transaction Transaction) GetTransaction(Keccak txHash)
        {
            Keccak blockHash = _receiptFinder.FindBlockHash(txHash);

            if (blockHash != null)
            {
                Block     block     = _blockTree.FindBlock(blockHash, BlockTreeLookupOptions.TotalDifficultyNotNeeded);
                TxReceipt txReceipt = _receiptFinder.Get(block).ForTransaction(txHash);
                return(txReceipt, block?.Transactions[txReceipt.Index]);
            }

            if (_txPool.TryGetPendingTransaction(txHash, out var transaction))
            {
                return(null, transaction);
            }

            return(null, null);
        }
Beispiel #15
0
        private ResultWrapper <BlockForRpc> GetBlock(BlockParameter blockParameter, bool returnFullTransactionObjects)
        {
            SearchResult <Block> searchResult = _blockFinder.SearchForBlock(blockParameter, true);

            if (searchResult.IsError)
            {
                return(ResultWrapper <BlockForRpc> .Fail(searchResult));
            }

            Block block = searchResult.Object;

            if (block != null)
            {
                _blockchainBridge.RecoverTxSenders(block);
            }

            return(ResultWrapper <BlockForRpc> .Success(block == null?null : new BlockForRpc(block, returnFullTransactionObjects)));
        }
Beispiel #16
0
    private ResultWrapper <BlockForRpc> GetUncle(BlockParameter blockParameter, UInt256 positionIndex)
    {
        SearchResult <Block> searchResult = _blockFinder.SearchForBlock(blockParameter);

        if (searchResult.IsError)
        {
            return(ResultWrapper <BlockForRpc> .Fail(searchResult));
        }

        Block block = searchResult.Object;

        if (positionIndex < 0 || positionIndex > block.Uncles.Length - 1)
        {
            return(ResultWrapper <BlockForRpc> .Fail("Position Index is incorrect", ErrorCodes.InvalidParams));
        }

        BlockHeader uncleHeader = block.Uncles[(int)positionIndex];

        return(ResultWrapper <BlockForRpc> .Success(new BlockForRpc(new Block(uncleHeader, BlockBody.Empty), false, _specProvider)));
    }
 public byte[] Call(Block block, Transaction transaction)
 {
     try
     {
         _readerWriterLockSlim.EnterWriteLock();
         _stateProvider.StateRoot = _blockTree.Head.StateRoot;
         BlockHeader header = new BlockHeader(block.Hash, Keccak.OfAnEmptySequenceRlp, block.Beneficiary,
                                              block.Difficulty, block.Number + 1, (long)transaction.GasLimit, block.Timestamp + 1, Bytes.Empty);
         transaction.Nonce = _stateProvider.GetNonce(transaction.SenderAddress);
         transaction.Hash  = Transaction.CalculateHash(transaction);
         CallOutputTracer callOutputTracer = new CallOutputTracer();
         _transactionProcessor.CallAndRestore(transaction, header, callOutputTracer);
         _stateProvider.Reset();
         return(callOutputTracer.ReturnValue);
     }
     finally
     {
         _readerWriterLockSlim.ExitWriteLock();
     }
 }
Beispiel #18
0
        private void LoadGenesisBlock(Keccak expectedGenesisHash)
        {
            // if we already have a database with blocks then we do not need to load genesis from spec
            if (_blockTree.Genesis != null)
            {
                ValidateGenesisHash(expectedGenesisHash);
                return;
            }

            Block genesis = _chainSpec.Genesis;

            CreateSystemAccounts();

            foreach ((Address address, ChainSpecAllocation allocation) in _chainSpec.Allocations)
            {
                _stateProvider.CreateAccount(address, allocation.Balance);
                if (allocation.Code != null)
                {
                    Keccak codeHash = _stateProvider.UpdateCode(allocation.Code);
                    _stateProvider.UpdateCodeHash(address, codeHash, _specProvider.GenesisSpec);
                }

                if (allocation.Constructor != null)
                {
                    Transaction constructorTransaction = new Transaction(true)
                    {
                        SenderAddress = address,
                        Init          = allocation.Constructor,
                        GasLimit      = genesis.GasLimit
                    };
                    _transactionProcessor.Execute(constructorTransaction, genesis.Header, NullTxTracer.Instance);
                }
            }

            _storageProvider.Commit();
            _stateProvider.Commit(_specProvider.GenesisSpec);

            _storageProvider.CommitTrees();
            _stateProvider.CommitTree();

            _dbProvider.StateDb.Commit();
            _dbProvider.CodeDb.Commit();

            genesis.StateRoot = _stateProvider.StateRoot;
            genesis.Hash      = BlockHeader.CalculateHash(genesis.Header);

            ManualResetEventSlim genesisProcessedEvent = new ManualResetEventSlim(false);

            bool genesisLoaded = false;

            void GenesisProcessed(object sender, BlockEventArgs args)
            {
                genesisLoaded            = true;
                _blockTree.NewHeadBlock -= GenesisProcessed;
                genesisProcessedEvent.Set();
            }

            _blockTree.NewHeadBlock += GenesisProcessed;
            _blockTree.SuggestBlock(genesis);
            genesisProcessedEvent.Wait(TimeSpan.FromSeconds(5));
            if (!genesisLoaded)
            {
                throw new BlockchainException("Genesis block processing failure");
            }

            ValidateGenesisHash(expectedGenesisHash);
        }
Beispiel #19
0
 public TxReceipt[] GetReceipts(Block block) => _receiptStorage.FindForBlock(block);