/// <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); }
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); }
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); } }