Beispiel #1
0
        /// <summary>
        /// Helper method that actually does the actual call to <see cref="ITransactionProcessor"/>.
        /// </summary>
        /// <param name="transactionProcessor">Actual transaction processor to be called upon.</param>
        /// <param name="header">Header in which context the call is done.</param>
        /// <param name="transaction">Transaction to be executed.</param>
        /// <param name="callAndRestore">Is it restore call.</param>
        /// <returns>Bytes with result.</returns>
        /// <exception cref="AbiException">Thrown when there is an exception during execution or <see cref="CallOutputTracer.StatusCode"/> is <see cref="StatusCode.Failure"/>.</exception>
        protected static byte[] CallCore(ITransactionProcessor transactionProcessor, BlockHeader header, Transaction transaction, bool callAndRestore = false)
        {
            bool failure;

            CallOutputTracer tracer = new CallOutputTracer();

            try
            {
                if (callAndRestore)
                {
                    transactionProcessor.CallAndRestore(transaction, header, tracer);
                }
                else
                {
                    transactionProcessor.Execute(transaction, header, tracer);
                }

                failure = tracer.StatusCode != StatusCode.Success;
            }
            catch (Exception e)
            {
                throw new AbiException($"System call returned an exception '{e.Message}' at block {header.Number}.", e);
            }

            if (failure)
            {
                throw new AbiException($"System call returned error '{tracer.Error}' at block {header.Number}.");
            }
            else
            {
                return(tracer.ReturnValue);
            }
        }
Beispiel #2
0
            public Facade.BlockchainBridge.CallOutput Call(BlockHeader blockHeader, Transaction transaction)
            {
                CallOutputTracer tracer = new CallOutputTracer();

                _processor.Execute(transaction, Head, tracer);
                return(new Facade.BlockchainBridge.CallOutput(tracer.ReturnValue, tracer.GasSpent, tracer.Error));
            }
        public void Keccak_gas_cost_assumption_is_correct()
        {
            Rlp rlp = BuildHeader();

            Transaction            tx         = Build.A.Transaction.WithData(rlp.Bytes).TestObject;
            IntrinsicGasCalculator calculator = new IntrinsicGasCalculator();
            long gasCost = calculator.Calculate(tx, Spec);

            gasCost.Should().BeLessThan(21000 + 9600);

            var bytecode =
                Prepare.EvmCode
                .PushData("0x0200")
                .PushData(0)
                .PushData(0)
                .Op(Instruction.CALLDATACOPY)
                .PushData("0x0200")
                .PushData(0)
                .Op(Instruction.SHA3)
                .Done;

            (Block block, Transaction transaction) = PrepareTx(
                BlockNumber, 1000000, bytecode, rlp.Bytes, 0);

            CallOutputTracer callOutputTracer = new CallOutputTracer();

            _processor.Execute(transaction, block.Header, callOutputTracer);
            long minorCostsEstimate = 100;
            long keccakCostEstimate = 30 + 512 / 6;

            callOutputTracer.GasSpent.Should().BeLessThan(21000 + 9600 + minorCostsEstimate + keccakCostEstimate);
        }
        private void ConfirmEnoughEstimate(Transaction tx, Block block, long estimate)
        {
            CallOutputTracer outputTracer = new CallOutputTracer();

            tx.GasLimit = estimate;
            TestContext.WriteLine(tx.GasLimit);

            GethLikeTxTracer gethTracer = new GethLikeTxTracer(GethTraceOptions.Default);

            _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer);
            string traceEnoughGas = new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true);

            _transactionProcessor.CallAndRestore(tx, block.Header, outputTracer);
            traceEnoughGas.Should().NotContain("OutOfGas");

            outputTracer = new CallOutputTracer();
            tx.GasLimit  = Math.Min(estimate - 1, estimate * 63 / 64);
            TestContext.WriteLine(tx.GasLimit);

            gethTracer = new GethLikeTxTracer(GethTraceOptions.Default);
            _transactionProcessor.CallAndRestore(tx, block.Header, gethTracer);

            string traceOutOfGas = new EthereumJsonSerializer().Serialize(gethTracer.BuildResult(), true);

            TestContext.WriteLine(traceOutOfGas);

            _transactionProcessor.CallAndRestore(tx, block.Header, outputTracer);

            bool failed = traceEnoughGas.Contains("failed") || traceEnoughGas.Contains("OutOfGas");

            failed.Should().BeTrue();
        }
Beispiel #5
0
        public CallOutput Call(BlockHeader blockHeader, Transaction transaction)
        {
            if (transaction.SenderAddress == null)
            {
                transaction.SenderAddress = Address.Zero;
            }

            BlockHeader header = new BlockHeader(blockHeader.Hash, Keccak.OfAnEmptySequenceRlp, blockHeader.Beneficiary,
                                                 blockHeader.Difficulty, blockHeader.Number + 1, (long)transaction.GasLimit, blockHeader.Timestamp + 1, Bytes.Empty);

            _stateProvider.StateRoot = blockHeader.StateRoot;
            if (transaction.Nonce == 0)
            {
                transaction.Nonce = GetNonce(blockHeader.StateRoot, transaction.SenderAddress);
            }

            transaction.Hash = Transaction.CalculateHash(transaction);
            CallOutputTracer callOutputTracer = new CallOutputTracer();

            _transactionProcessor.CallAndRestore(transaction, header, callOutputTracer);
            _stateProvider.Reset();
            _storageProvider.Reset();
            return(new CallOutput {
                Error = callOutputTracer.Error, GasSpent = callOutputTracer.GasSpent, OutputData = callOutputTracer.ReturnValue
            });
        }
        public void Blockhash_times_256_gas_cost_assumption_is_correct()
        {
            Rlp rlp      = BuildHeader();
            var bytecode =
                Prepare.EvmCode
                .PushData(256)
                .Op(Instruction.JUMPDEST)
                .PushData(1)
                .Op(Instruction.DUP2)
                .Op(Instruction.SUB)
                .Op(Instruction.DUP1)
                .Op(Instruction.BLOCKHASH)
                .Op(Instruction.POP)
                .PushData(0)
                .Op(Instruction.DUP2)
                .Op(Instruction.GT)
                .PushData(3)
                .Op(Instruction.JUMPI)
                .Op(Instruction.STOP)
                .Done;

            (Block block, Transaction transaction) = PrepareTx(
                BlockNumber, 1000000, bytecode, rlp.Bytes, 0);

            CallOutputTracer callOutputTracer = new CallOutputTracer();

            _processor.Execute(transaction, block.Header, callOutputTracer);
            callOutputTracer.GasSpent.Should().BeLessThan(21000 + 9600 + 20000);
        }
        protected CallOutputTracer Execute(long blockNumber, long gasLimit, byte[] code)
        {
            (var block, var transaction) = PrepareTx(blockNumber, gasLimit, code);
            CallOutputTracer tracer = new CallOutputTracer();

            _processor.Execute(transaction, block.Header, tracer);
            return(tracer);
        }
        protected CallOutputTracer Execute(params byte[] code)
        {
            (var block, var transaction) = PrepareTx(BlockNumber, 100000, code);
            CallOutputTracer tracer = new CallOutputTracer();

            _processor.Execute(transaction, block.Header, tracer);
            return(tracer);
        }
Beispiel #9
0
        public Block Load()
        {
            Block genesis = _chainSpec.Genesis;

            foreach ((Address address, ChainSpecAllocation allocation) in _chainSpec.Allocations.OrderBy(a => a.Key))
            {
                _stateProvider.CreateAccount(address, allocation.Balance);

                if (allocation.Code != null)
                {
                    Keccak codeHash = _stateProvider.UpdateCode(allocation.Code);
                    _stateProvider.UpdateCodeHash(address, codeHash, _specProvider.GenesisSpec);
                }

                if (allocation.Storage != null)
                {
                    foreach (KeyValuePair <UInt256, byte[]> storage in allocation.Storage)
                    {
                        _storageProvider.Set(new StorageCell(address, storage.Key), storage.Value.WithoutLeadingZeros().ToArray());
                    }
                }

                if (allocation.Constructor != null)
                {
                    Transaction constructorTransaction = new SystemTransaction()
                    {
                        SenderAddress = address,
                        Init          = allocation.Constructor,
                        GasLimit      = genesis.GasLimit
                    };

                    CallOutputTracer outputTracer = new CallOutputTracer();
                    _transactionProcessor.Execute(constructorTransaction, genesis.Header, outputTracer);

                    if (outputTracer.StatusCode != StatusCode.Success)
                    {
                        throw new InvalidOperationException($"Failed to initialize constructor for address {address}. Error: {outputTracer.Error}");
                    }
                }
            }

            // we no longer need the allocations - 0.5MB RAM, 9000 objects for mainnet
            _chainSpec.Allocations = null;

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

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

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

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

            return(genesis);
        }
Beispiel #10
0
        public CallOutput Call(BlockHeader blockHeader, Transaction transaction)
        {
            CallOutputTracer callOutputTracer = new CallOutputTracer();

            CallAndRestore(blockHeader, transaction, callOutputTracer);
            return(new CallOutput {
                Error = callOutputTracer.Error, GasSpent = callOutputTracer.GasSpent, OutputData = callOutputTracer.ReturnValue
            });
        }
Beispiel #11
0
        public void Shift_right(string a, string b, string result)
        {
            byte[] code = Prepare.EvmCode
                          .PushData(a)
                          .PushData(b)
                          .Op(Instruction.SHR)
                          .PushData(0)
                          .Op(Instruction.SSTORE)
                          .Done;

            CallOutputTracer receipt = Execute(code);

            AssertEip145(receipt, result);
        }
        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);
        }
Beispiel #13
0
        private bool TryCall(BlockHeader header, Transaction transaction, out byte[] result)
        {
            CallOutputTracer tracer = new CallOutputTracer();

            try
            {
                _transactionProcessor.Execute(transaction, header, tracer);
                result = tracer.ReturnValue;
                return(tracer.StatusCode == StatusCode.Success);
            }
            catch (Exception)
            {
                result = null;
                return(false);
            }
        }
Beispiel #14
0
        public CallOutput Call(BlockHeader blockHeader, Transaction transaction, CancellationToken cancellationToken)
        {
            CallOutputTracer callOutputTracer = new CallOutputTracer();

            CallAndRestore(blockHeader, blockHeader.Number, blockHeader.Timestamp, transaction,
                           new CancellationTxTracer(callOutputTracer, cancellationToken)
            {
                IsTracingActions        = true,
                IsTracingOpLevelStorage = true,
                IsTracingInstructions   = true,   // a little bit costly but almost all are simple calls
                IsTracingRefunds        = true
            });
            return(new CallOutput
            {
                Error = callOutputTracer.Error,
                GasSpent = callOutputTracer.GasSpent,
                OutputData = callOutputTracer.ReturnValue
            });
        }
 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 #16
0
        public void Not()
        {
            if (_simdDisabled)
            {
                Machine.DisableSimdInstructions();
            }

            byte[] a      = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0");
            byte[] result = Bytes.FromHexString("0x0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");

            byte[] code = Prepare.EvmCode
                          .PushData(a)
                          .PushData(a) // just to make gas usage same as in other tests
                          .Op(Instruction.NOT)
                          .PushData(0)
                          .Op(Instruction.SSTORE)
                          .Done;

            CallOutputTracer receipt = Execute(code);

            AssertSimd(receipt, result);
        }
        public static CallOutputTracer CallAndRestore(this IWeb3EthApi api, TransactionForRpc transactionCall, DeltaWithCid deltaWithCid)
        {
            var    parentDelta = deltaWithCid.Delta;
            Keccak root        = parentDelta.StateRoot.ToKeccak();

            if (transactionCall.Gas == null)
            {
                transactionCall.Gas = parentDelta.GasLimit;
            }

            var publicEntry = api.ToPublicEntry(transactionCall, root);

            var newDelta = deltaWithCid.CreateOneOffDelta(publicEntry);

            CallOutputTracer callOutputTracer = new CallOutputTracer();

            api.StateProvider.StateRoot = root;
            api.Executor.CallAndReset(newDelta, callOutputTracer);
            api.StateProvider.Reset();
            api.StorageProvider.Reset();
            return(callOutputTracer);
        }
Beispiel #18
0
        public void Xor()
        {
            if (_simdDisabled)
            {
                Machine.DisableSimdInstructions();
            }

            byte[] a      = Bytes.FromHexString("0xf0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0");
            byte[] b      = Bytes.FromHexString("0xff0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f0f");
            byte[] result = Bytes.FromHexString("0x0fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff");

            byte[] code = Prepare.EvmCode
                          .PushData(a)
                          .PushData(b)
                          .Op(Instruction.XOR)
                          .PushData(0)
                          .Op(Instruction.SSTORE)
                          .Done;

            CallOutputTracer receipt = Execute(code);

            AssertSimd(receipt, result);
        }
        public void Blockhash_times_256_no_loop()
        {
            Rlp     rlp             = BuildHeader();
            Prepare bytecodeBuilder = Prepare.EvmCode
                                      .PushData(0)
                                      .PushData(1);

            for (int i = 0; i < 256; i++)
            {
                bytecodeBuilder.Op(Instruction.ADD)
                .Op(Instruction.BLOCKHASH)
                .PushData(1);
            }

            byte[] bytecode = bytecodeBuilder.Done;

            (Block block, Transaction transaction) = PrepareTx(
                BlockNumber, 1000000, bytecode, rlp.Bytes, 0);

            CallOutputTracer callOutputTracer = new CallOutputTracer();

            _processor.Execute(transaction, block.Header, callOutputTracer);
            callOutputTracer.GasSpent.Should().BeLessThan(21000 + 9600 + 20000);
        }
Beispiel #20
0
        public void InvokeTransaction(BlockHeader header, ITransactionProcessor transactionProcessor, Transaction transaction, CallOutputTracer tracer)
        {
            bool failure;

            try
            {
                transactionProcessor.Execute(transaction, header, tracer);
                failure = tracer.StatusCode != StatusCode.Success;
            }
            catch (Exception e)
            {
                throw new AuRaException($"System call returned an exception '{e.Message}' at block {header.Number}.", e);
            }

            if (failure)
            {
                throw new AuRaException($"System call returned error '{tracer.Error}' at block {header.Number}.");
            }
        }
Beispiel #21
0
 private void AssertSimd(CallOutputTracer receipt, byte[] result)
 {
     AssertStorage(0, result);
     AssertGas(receipt, result.IsZero() ? ZeroResultGas : NonZeroResultGas);
 }
Beispiel #22
0
 private void AssertSimd(CallOutputTracer receipt, string result)
 {
     AssertSimd(receipt, Bytes.FromHexString(result));
 }
Beispiel #23
0
        public bool TryInvokeTransaction(BlockHeader header, ITransactionProcessor transactionProcessor, Transaction transaction, CallOutputTracer tracer)
        {
            if (transaction != null)
            {
                transactionProcessor.Execute(transaction, header, tracer);
                return(tracer.StatusCode == StatusCode.Success);
            }

            return(false);
        }
Beispiel #24
0
 public void InvokeTransaction(BlockHeader header, ITransactionProcessor transactionProcessor, Transaction transaction, CallOutputTracer tracer)
 {
     if (transaction != null && !TryInvokeTransaction(header, transactionProcessor, transaction, tracer))
     {
         throw new AuRaException($"System call returned error '{tracer.Error}' at block {header.Number}.");
     }
 }
Beispiel #25
0
        public void InvokeTransaction(BlockHeader header, ITransactionProcessor transactionProcessor, Transaction transaction, CallOutputTracer tracer, bool isReadOnly = false)
        {
            if (transaction != null)
            {
                if (isReadOnly)
                {
                    transactionProcessor.CallAndRestore(transaction, header, tracer);
                }
                else
                {
                    transactionProcessor.Execute(transaction, header, tracer);
                }

                if (tracer.StatusCode != StatusCode.Success)
                {
                    throw new AuRaException($"System call returned error '{tracer.Error}' at block {header.Number}.");
                }
            }
        }
Beispiel #26
0
 private void AssertEip145(CallOutputTracer receipt, byte result)
 {
     AssertEip145(receipt, new[] { result });
 }
 protected void AssertGas(CallOutputTracer receipt, long gas)
 {
     Assert.AreEqual(gas, receipt.GasSpent, "gas");
 }