Esempio n. 1
0
        public static OpcodeDescriptorAttribute GetDescriptor(this InstructionOpcode opcode)
        {
            // Check our cache for our descriptor.
            if (_cachedDescriptors.TryGetValue(opcode, out var val))
            {
                return(val);
            }

            // Cache miss, obtain our enum option's field info
            FieldInfo fi = opcode.GetType().GetField(opcode.ToString());

            if (fi == null)
            {
                return(null);
            }

            // Obtain all attributes of type we are interested in.
            var attributes = fi.GetCustomAttributes <OpcodeDescriptorAttribute>(false).ToArray();

            // If one exists, cache it and return it.
            if (attributes != null && attributes.Length > 0)
            {
                _cachedDescriptors[opcode] = attributes[0];
                return(attributes[0]);
            }

            return(null);
        }
Esempio n. 2
0
        public static string GetIntelInstructionOpcode(this InstructionOpcode type)
        {
            const string result = "none";

            switch (type)
            {
            case InstructionOpcode.None:
                break;

            case InstructionOpcode.Add:
                return("add");

            case InstructionOpcode.Subtract:
                return("sub");

            case InstructionOpcode.Multiply:
                return("imul");

            case InstructionOpcode.Divide:
                return("idiv");

            default:
                throw new ArgumentOutOfRangeException(nameof(type), type, null);
            }
            return(result);
        }
        public static string GetArguments(InstructionOpcode opcode)
        {
            var index = (byte)opcode;

            if (index >= Arguments.Count)
            {
                throw new ArgumentOutOfRangeException(nameof(opcode), $"Out-of-range: {opcode} with index {index}");
            }
            return(Arguments[index]);
        }
Esempio n. 4
0
        private void Step()
        {
            // Verify we're not at the end of the stream
            if (ExecutionState.PC >= Code.Length)
            {
                // If we reached the end, exit with the remainder of the gas and a success status.
                ExecutionState.Result = new EVMExecutionResult(this, null, true);
                return;
            }

            // Set our position back to the start of the instruction, grab our opcode and verify it.
            InstructionOpcode opcode = (InstructionOpcode)Code.Span[(int)ExecutionState.PC];

            // Obtain our base cost for this opcode. If we fail to, the instruction isn't implemented yet.
            uint?instructionBaseGasCost = GasDefinitions.GetInstructionBaseGasCost(State.Configuration.Version, opcode);

            if (instructionBaseGasCost == null)
            {
                throw new EVMException($"Invalid opcode {opcode.ToString()} read when executing!");
            }

            // If we just jumped, then this next opcode should be a JUMPDEST.
            if (ExecutionState.JumpedLastInstruction && opcode != InstructionOpcode.JUMPDEST)
            {
                throw new EVMException($"Invalid jump to offset {ExecutionState.PC} in code!");
            }

            // Obtain our instruction implementation for this opcode
            var             opcodeDescriptor = opcode.GetDescriptor();
            InstructionBase instruction      = opcodeDescriptor.GetInstructionImplementation(this);

            // Record our code coverage for this execution.
            CoverageMap?.RecordExecution(instruction.Offset, (ExecutionState.PC - instruction.Offset));

            // Record our instruction execution tracing
            if (State.Configuration.DebugConfiguration.IsTracing)
            {
                State.Configuration.DebugConfiguration.ExecutionTrace?.RecordExecution(this, instruction, GasState.Gas, (BigInteger)instructionBaseGasCost);
            }

            // Deduct base gas cost
            GasState.Deduct((BigInteger)instructionBaseGasCost);

            // Debug: Print out instruction execution information.
            //if (opcode == InstructionOpcode.JUMPDEST)
            //    Console.WriteLine($"\r\n---------------------------------------------------------------\r\n");
            //Console.WriteLine($"0x{instruction.Offset.ToString("X4")}: {instruction}");
            //Console.WriteLine($"Stack: {ExecutionState.Stack}");

            // Execute the instruction
            instruction.Execute();
        }
Esempio n. 5
0
        /// <summary>
        /// Obtains the base gas cost of executing the given opcode on the given Ethereum release version.
        /// </summary>
        /// <param name="currentVersion">The release of Ethereum to assume when obtaining the base gas cost for the given opcode.</param>
        /// <param name="opcode">The opcode to obtain the base gas cost for.</param>
        /// <returns>Returns the base gas cost for the given instruction on the given Ethereum release.</returns>
        public static uint?GetInstructionBaseGasCost(EthereumRelease currentVersion, InstructionOpcode opcode)
        {
            // Obtain the cost for this version. It is null if it does not exist yet, or was never declared.
            uint cost = 0;

            if (_baseGasLookup[currentVersion].TryGetValue(opcode, out cost))
            {
                return(cost);
            }
            else
            {
                return(null);
            }
        }
Esempio n. 6
0
        public static OpcodeBaseGasCostAttribute[] GetBaseGasCosts(this InstructionOpcode opcode)
        {
            // Cache miss, obtain our enum option's field info
            FieldInfo fi = opcode.GetType().GetField(opcode.ToString());

            if (fi == null)
            {
                return(null);
            }

            // Obtain all attributes of type we are interested in.
            var attributes = fi.GetCustomAttributes <OpcodeBaseGasCostAttribute>(false).ToArray();

            return(attributes);
        }
Esempio n. 7
0
 public CpuContext(
     uint instructionAddress,
     uint programCounter,
     InstructionOpcode opcode,
     uint operands,
     bool error,
     CpuErrorCode errorCode)
 {
     InstructionAddress = instructionAddress;
     ProgramCounter = programCounter;
     Opcode = opcode;
     Operands = operands;
     Error = error;
     ErrorCode = errorCode;
 }
Esempio n. 8
0
 public Instruction(InstructionOpcode opcode, string parameter = null)
 {
     Opcode    = opcode;
     Parameter = parameter;
 }