/// <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); } }
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(); }
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); }
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); }
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 }); }
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); }
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); } }
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(); } }
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); }
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); }
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}."); } }
private void AssertSimd(CallOutputTracer receipt, byte[] result) { AssertStorage(0, result); AssertGas(receipt, result.IsZero() ? ZeroResultGas : NonZeroResultGas); }
private void AssertSimd(CallOutputTracer receipt, string result) { AssertSimd(receipt, Bytes.FromHexString(result)); }
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); }
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}."); } }
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}."); } } }
private void AssertEip145(CallOutputTracer receipt, byte result) { AssertEip145(receipt, new[] { result }); }
protected void AssertGas(CallOutputTracer receipt, long gas) { Assert.AreEqual(gas, receipt.GasSpent, "gas"); }