예제 #1
0
        /// <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));
        }
예제 #2
0
        /// <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));
        }
예제 #3
0
        /// <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));
        }
예제 #4
0
        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));
        }
예제 #5
0
        /// <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++;
            }
        }
예제 #6
0
        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);
        }
예제 #7
0
 /// <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);
 }