/// <summary>
        /// Contract validation failed, so set the gas units used to a value from the price list and set
        /// the validation errors in a <see cref="SmartContractValidationException"/>.
        /// </summary>
        public static SmartContractExecutionResult ValidationFailed(SmartContractValidationResult validationResult)
        {
            var executionResult = new SmartContractExecutionResult
            {
                Exception   = new SmartContractValidationException(validationResult.Errors),
                GasConsumed = GasPriceList.ContractValidationFailed()
            };

            return(executionResult);
        }
        /// <summary>
        /// Contract does not exist, so set the gas units used to a value from the price list and set
        /// a <see cref="SmartContractDoesNotExistException"/>.
        /// </summary>
        internal static ISmartContractExecutionResult ContractDoesNotExist(string methodName)
        {
            var executionResult = new SmartContractExecutionResult
            {
                Exception   = new SmartContractDoesNotExistException(methodName),
                GasConsumed = GasPriceList.ContractDoesNotExist()
            };

            return(executionResult);
        }
Esempio n. 3
0
        public void StoreBytes(uint160 address, byte[] key, byte[] value)
        {
            byte[] encodedKey    = this.keyEncodingStrategy.GetBytes(key);
            Gas    operationCost = GasPriceList.StorageSaveOperationCost(
                encodedKey,
                value);

            this.gasMeter.Spend(operationCost);
            this.stateDb.SetStorageValue(address, encodedKey, value);
        }
        /// <summary>
        /// Contract does not exist, so set the gas units used to a value from the price list and set
        /// a <see cref="SmartContractDoesNotExistException"/>.
        /// </summary>
        internal static ISmartContractExecutionResult ContractDoesNotExist(SmartContractCarrier carrier)
        {
            var executionResult = new SmartContractExecutionResult
            {
                Exception   = new SmartContractDoesNotExistException(carrier.CallData.MethodName),
                GasConsumed = GasPriceList.ContractDoesNotExist()
            };

            return(executionResult);
        }
Esempio n. 5
0
        public byte[] FetchBytes(uint160 address, byte[] key)
        {
            byte[] encodedKey = this.keyEncodingStrategy.GetBytes(key);
            byte[] value      = this.stateDb.GetStorageValue(address, encodedKey);

            Gas operationCost = GasPriceList.StorageRetrieveOperationCost(encodedKey, value);

            this.gasMeter.Spend(operationCost);

            return(value);
        }
        private static void InjectSpendGasMethod(MethodDefinition methodDefinition, MethodReference gasMethod)
        {
            int position = 0;
            List <Instruction> branches  = methodDefinition.Body.Instructions.Where(x => BranchingOps.Contains(x.OpCode)).ToList();
            List <Instruction> branchTos = branches.Select(x => (Instruction)x.Operand).ToList();

            Instruction currentSegmentStart = methodDefinition.Body.Instructions.FirstOrDefault();
            Gas         gasTally            = Gas.None;

            Dictionary <Instruction, Gas> gasToSpendForSegment = new Dictionary <Instruction, Gas>();

            while (position < methodDefinition.Body.Instructions.Count)
            {
                Instruction instruction = methodDefinition.Body.Instructions[position];

                Gas instructionCost = GasPriceList.InstructionOperationCost(instruction);

                // is the end of a segment. Include the current instruction in the count.
                if (branches.Contains(instruction))
                {
                    gasTally = (Gas)(gasTally + instructionCost);
                    gasToSpendForSegment.Add(currentSegmentStart, gasTally);
                    gasTally = Gas.None;
                    position++;
                    if (position == methodDefinition.Body.Instructions.Count)
                    {
                        break;
                    }
                    currentSegmentStart = methodDefinition.Body.Instructions[position];
                }
                // is the start of a new segment. Don't include the current instruction in count.
                else if (branchTos.Contains(instruction) && instruction != currentSegmentStart)
                {
                    gasToSpendForSegment.Add(currentSegmentStart, gasTally);
                    gasTally            = Gas.None;
                    currentSegmentStart = instruction;
                    position++;
                }
                // is a call to another method
                else if (CallingOps.Contains(instruction.OpCode))
                {
                    var methodToCall = (MethodReference)instruction.Operand;

                    // If it's a method inside this contract then the gas will be injected no worries.
                    if (methodToCall.DeclaringType == methodDefinition.DeclaringType)
                    {
                        position++;
                        gasTally = (Gas)(gasTally + instructionCost);
                    }
                    // If it's a method outside this contract then we will need to get some average in future.
                    else
                    {
                        Gas methodCallCost = GasPriceList.MethodCallCost(methodToCall);

                        position++;
                        gasTally = (Gas)(gasTally + instructionCost + methodCallCost);
                    }
                }
                // any other instruction. just increase counter.
                else
                {
                    position++;
                    gasTally = (Gas)(gasTally + instructionCost);
                }
            }

            if (!gasToSpendForSegment.ContainsKey(currentSegmentStart))
            {
                gasToSpendForSegment.Add(currentSegmentStart, gasTally);
            }

            foreach (Instruction instruction in gasToSpendForSegment.Keys)
            {
                var injectAfterInstruction = instruction;

                // If it's a constructor we need to skip the first 3 instructions.
                // These will always be invoking the base constructor
                // ldarg.0
                // ldarg.0
                // call SmartContract::ctor
                if (methodDefinition.IsConstructor)
                {
                    injectAfterInstruction = instruction.Next.Next.Next;
                }

                AddSpendGasMethodBeforeInstruction(methodDefinition, gasMethod, injectAfterInstruction, gasToSpendForSegment[instruction]);
            }

            ILProcessor il = methodDefinition.Body.GetILProcessor();

            foreach (Instruction instruction in branches)
            {
                var         oldReference   = (Instruction)instruction.Operand;
                Instruction newReference   = oldReference.Previous.Previous.Previous; // 3 were inserted
                Instruction newInstruction = il.Create(instruction.OpCode, newReference);
                il.Replace(instruction, newInstruction);
            }
        }