/// <summary> /// A precompiled contract which acts as memcpy, returning a copy of the message data provided. /// </summary> /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param> private static EVMExecutionResult Precompile_Identity(MeadowEVM evm) { // Charge the gas for the precompile operation before processing. (A base fee, plus for every word) BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_IDENTITY_BASE + (EVMDefinitions.GetWordCount(evm.Message.Data.Length) * GasDefinitions.GAS_PRECOMPILE_IDENTITY_WORD); evm.GasState.Deduct(gasCharge); // We simply return the data back return(new EVMExecutionResult(evm, evm.Message.Data, true)); }
/// <summary> /// A precompiled contract which computes a SHA256 hash from the message data. /// </summary> /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param> private static EVMExecutionResult Precompile_SHA256(MeadowEVM evm) { // Charge the gas for the precompile operation before processing. (A base fee, plus for every word) BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_SHA256_BASE + (EVMDefinitions.GetWordCount(evm.Message.Data.Length) * GasDefinitions.GAS_PRECOMPILE_SHA256_WORD); evm.GasState.Deduct(gasCharge); // We compute a hash of the message data. byte[] hash = SHA256.Create().ComputeHash(evm.Message.Data); // Return the hash return(new EVMExecutionResult(evm, hash, true)); }
/// <summary> /// A precompiled contract which computes a RIPEMD160 hash from the message data. /// </summary> /// <param name="evm">The Ethereum Virtual Machine instance we are executing inside of.</param> private static EVMExecutionResult Precompile_RIPEMD160(MeadowEVM evm) { // Charge the gas for the precompile operation before processing. (A base fee, plus for every word) BigInteger gasCharge = GasDefinitions.GAS_PRECOMPILE_RIPEMD160_BASE + (EVMDefinitions.GetWordCount(evm.Message.Data.Length) * GasDefinitions.GAS_PRECOMPILE_RIPEMD160_WORD); evm.GasState.Deduct(gasCharge); // We compute a hash of the message data. byte[] hash = new RIPEMD160Managed().ComputeHash(evm.Message.Data); // We make the return value into the size of a word. byte[] result = new byte[EVMDefinitions.WORD_SIZE]; Array.Copy(hash, 0, result, result.Length - hash.Length, hash.Length); // Return the result return(new EVMExecutionResult(evm, result, true)); }
public override void Execute() { // Obtain the memory offset and size BigInteger offset = Stack.Pop(); BigInteger size = Stack.Pop(); // Deduct our gas accordingly. GasState.Deduct(EVMDefinitions.GetWordCount(size) * GasDefinitions.GAS_SHA3_WORD); // Read our data to hash byte[] data = Memory.ReadBytes((long)offset, (int)size); // Hash our read data. byte[] hash = KeccakHash.ComputeHashBytes(data); // Push it onto our stack. Stack.Push(BigIntegerConverter.GetBigInteger(hash)); }
/// <summary> /// Expands the memory stream if needed (and charges gas) to accomodate for an operation to occur at the given address with a given size. /// </summary> /// <param name="address">The address where data is presumed to be read or written.</param> /// <param name="size">The size of the data presumed to be read or written.</param> public void ExpandStream(BigInteger address, BigInteger size) { // If our address space doesn't extend to handle data in these bounds, expand memory. if (address + size > Length) { // Memory is allocated such that it is aligned to the size of a WORD. BigInteger currentWordCount = EVMDefinitions.GetWordCount(Length); BigInteger targetWordCount = EVMDefinitions.GetWordCount(address + size); // Calculate cost of gas for expanding our array. BigInteger currentMemoryCost = GasDefinitions.GetMemoryAllocationCost(EVM.Version, currentWordCount); BigInteger targetMemoryCost = GasDefinitions.GetMemoryAllocationCost(EVM.Version, targetWordCount); BigInteger costDelta = targetMemoryCost - currentMemoryCost; // Deduct the difference in cost for expanding our memory. EVM.GasState.Deduct(costDelta); // Set the size of our stream _internalBufferStream.SetLength((long)targetWordCount * EVMDefinitions.WORD_SIZE); // Update our change count ChangeCount++; } }
internal static ExecutionTrace CoreExecutionTraceJsonExecutionTrace(Meadow.EVM.Debugging.Tracing.ExecutionTrace coreExecutionTrace) { // If the execution trace is null, we return null if (coreExecutionTrace == null) { return(null); } // Create our array of trace points ExecutionTracePoint[] tracepoints = new ExecutionTracePoint[coreExecutionTrace.Tracepoints.Count]; // Populate all tracepoint items. for (int i = 0; i < tracepoints.Length; i++) { // Obtain our trace point. var executionTracePoint = coreExecutionTrace.Tracepoints[i]; // Define our memory and stack Data[] executionMemory = null; Data[] executionStack = executionTracePoint.Stack.Select(s => new Data(s)).ToArray(); if (executionTracePoint.Memory != null) { int wordCount = (int)EVMDefinitions.GetWordCount(executionTracePoint.Memory.Length); Span <byte> memorySpan = executionTracePoint.Memory; executionMemory = new Data[wordCount]; for (int x = 0; x < executionMemory.Length; x++) { executionMemory[x] = new Data(memorySpan.Slice(x * EVMDefinitions.WORD_SIZE, EVMDefinitions.WORD_SIZE)); } } // Obtain our memory tracepoints[i] = new ExecutionTracePoint() { CallData = executionTracePoint.CallData, Code = executionTracePoint.Code, ContractAddress = executionTracePoint.ContractAddress == null ? (Address?)null : new Address(executionTracePoint.ContractAddress.ToByteArray()), ContractDeployed = executionTracePoint.ContractDeployed, Opcode = executionTracePoint.Opcode, GasRemaining = (UInt256)executionTracePoint.GasRemaining, GasCost = (UInt256)executionTracePoint.GasCost, PC = executionTracePoint.PC, Depth = executionTracePoint.Depth, Stack = executionStack, Memory = executionMemory, Storage = executionTracePoint.Storage }; } // Create our array of exceptions ExecutionTraceException[] exceptions = new ExecutionTraceException[coreExecutionTrace.Exceptions.Count]; // Populate all exception items for (int i = 0; i < exceptions.Length; i++) { // Set our item. exceptions[i] = new ExecutionTraceException() { TraceIndex = coreExecutionTrace.Exceptions[i].TraceIndex, Message = coreExecutionTrace.Exceptions[i].Exception.Message }; } // Obtain our execution trace analysis. ExecutionTrace executionTrace = new ExecutionTrace() { Tracepoints = tracepoints, Exceptions = exceptions }; // Return our execution trace. return(executionTrace); }
/// <summary> /// Provides the cost of gas for a given /// </summary> /// <param name="currentVersion">The Ethereum release currently being executed.</param> /// <param name="size">The size</param> /// <returns></returns> public static BigInteger GetMemoryCopyCost(EthereumRelease currentVersion, BigInteger size) { return(EVMDefinitions.GetWordCount(size) * GAS_MEMORY_COPY); }