/// <summary> /// Creates a new instance of a smart contract by invoking the contract's constructor /// </summary> public VmExecutionResult Create(byte[] contractCode, ISmartContractExecutionContext context, IGasMeter gasMeter, IPersistentState persistentState, IContractStateRepository repository) { this.logger.LogTrace("()"); byte[] gasInjectedCode = SmartContractGasInjector.AddGasCalculationToConstructor(contractCode); Type contractType = Load(gasInjectedCode); var internalTransferList = new List <TransferInfo>(); IInternalTransactionExecutor internalTransactionExecutor = this.internalTransactionExecutorFactory.Create(repository, internalTransferList); var balanceState = new BalanceState(repository, context.Message.Value, internalTransferList); var contractState = new SmartContractState( context.Block, context.Message, persistentState, gasMeter, internalTransactionExecutor, new InternalHashHelper(), () => balanceState.GetBalance(context.ContractAddress)); // Invoke the constructor of the provided contract code LifecycleResult result = SmartContractConstructor.Construct(contractType, contractState, context.Parameters); if (!result.Success) { LogException(result.Exception); this.logger.LogTrace("(-)[CREATE_CONTRACT_INSTANTIATION_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, result.Exception.InnerException ?? result.Exception)); } else { this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]"); } this.logger.LogTrace("(-):{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Success(internalTransferList, gasMeter.GasConsumed, result.Object)); }
/// <summary> /// Invokes a method on an existing smart contract /// </summary> public VmExecutionResult ExecuteMethod(byte[] contractCode, string contractMethodName, ISmartContractExecutionContext context, IGasMeter gasMeter, IPersistentState persistentState, IContractStateRepository repository) { this.logger.LogTrace("(){0}:{1}", nameof(contractMethodName), contractMethodName); ISmartContractExecutionResult executionResult = new SmartContractExecutionResult(); if (contractMethodName == null) { this.logger.LogTrace("(-)[CALLCONTRACT_METHODNAME_NOT_GIVEN]"); return(VmExecutionResult.Error(gasMeter.GasConsumed, null)); } byte[] gasInjectedCode = SmartContractGasInjector.AddGasCalculationToContractMethod(contractCode, contractMethodName); Type contractType = Load(gasInjectedCode); if (contractType == null) { this.logger.LogTrace("(-)[CALLCONTRACT_CONTRACTTYPE_NULL]"); return(VmExecutionResult.Error(gasMeter.GasConsumed, null)); } var internalTransferList = new List <TransferInfo>(); IInternalTransactionExecutor internalTransactionExecutor = this.internalTransactionExecutorFactory.Create(repository, internalTransferList); var balanceState = new BalanceState(repository, context.Message.Value, internalTransferList); var contractState = new SmartContractState( context.Block, context.Message, persistentState, gasMeter, internalTransactionExecutor, new InternalHashHelper(), () => balanceState.GetBalance(context.ContractAddress)); LifecycleResult result = SmartContractRestorer.Restore(contractType, contractState); if (!result.Success) { LogException(result.Exception); this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); executionResult.Exception = result.Exception.InnerException ?? result.Exception; executionResult.GasConsumed = gasMeter.GasConsumed; return(VmExecutionResult.Error(gasMeter.GasConsumed, result.Exception.InnerException ?? result.Exception)); } else { this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]"); } object methodResult = null; try { MethodInfo methodToInvoke = contractType.GetMethod(contractMethodName); if (methodToInvoke == null) { throw new ArgumentException(string.Format("[CALLCONTRACT_METHODTOINVOKE_NULL_DOESNOT_EXIST]:{0}={1}", nameof(contractMethodName), contractMethodName)); } if (methodToInvoke.IsConstructor) { throw new ConstructorInvocationException("[CALLCONTRACT_CANNOT_INVOKE_CTOR]"); } SmartContract smartContract = result.Object; methodResult = methodToInvoke.Invoke(smartContract, context.Parameters); } catch (ArgumentException argumentException) { LogException(argumentException); return(VmExecutionResult.Error(gasMeter.GasConsumed, argumentException)); } catch (TargetInvocationException targetException) { LogException(targetException); return(VmExecutionResult.Error(gasMeter.GasConsumed, targetException.InnerException ?? targetException)); } catch (TargetParameterCountException parameterException) { LogException(parameterException); } catch (ConstructorInvocationException constructorInvocationException) { LogException(constructorInvocationException); return(VmExecutionResult.Error(gasMeter.GasConsumed, constructorInvocationException)); } this.logger.LogTrace("(-):{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Success(internalTransferList, gasMeter.GasConsumed, methodResult)); }