public IState Create(IStateRepository stateRoot, IBlock block, ulong txOutValue, uint256 transactionHash) { var logHolder = new ContractLogHolder(); var internalTransfers = new List <TransferInfo>(); return(new State(this.smartContractStateFactory, stateRoot, logHolder, internalTransfers, block, transactionHash)); }
/// <summary> /// Creates a new instance of a smart contract by invoking the contract's constructor /// </summary> public VmExecutionResult Create(IGasMeter gasMeter, IContractState repository, ICreateData createData, ITransactionContext transactionContext, string typeName = null) { this.logger.LogTrace("()"); // TODO: Spend Validation + Creation Fee here. string typeToInstantiate; ContractByteCode code; // Decompile the contract execution code and validate it. using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(createData.ContractExecutionCode)) { SmartContractValidationResult validation = moduleDefinition.Validate(this.validator); // If validation failed, refund the sender any remaining gas. if (!validation.IsValid) { this.logger.LogTrace("(-)[CONTRACT_VALIDATION_FAILED]"); return(VmExecutionResult.Error(gasMeter.GasConsumed, new SmartContractValidationException(validation.Errors))); } typeToInstantiate = typeName ?? moduleDefinition.ContractType.Name; moduleDefinition.InjectConstructorGas(); code = moduleDefinition.ToByteCode(); } var internalTransferList = new List <TransferInfo>(); uint160 address = this.addressGenerator.GenerateAddress(transactionContext.TransactionHash, transactionContext.GetNonceAndIncrement()); var contractLogger = new ContractLogHolder(this.network); ISmartContractState contractState = this.SetupState(contractLogger, internalTransferList, gasMeter, repository, transactionContext, address); Result <IContract> contractLoadResult = this.Load( code, typeToInstantiate, address, contractState); if (!contractLoadResult.IsSuccess) { // TODO this is temporary until we improve error handling overloads var exception = new Exception(contractLoadResult.Error); LogException(exception); this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, exception)); } IContract contract = contractLoadResult.Value; LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address, createData); // Create an account for the contract in the state repository. repository.CreateAccount(contract.Address); // Invoke the constructor of the provided contract code IContractInvocationResult invocationResult = contract.InvokeConstructor(createData.MethodParameters); if (!invocationResult.IsSuccess) { this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_FAILED]"); return(VmExecutionResult.Error(gasMeter.GasConsumed, new Exception("Constructor invocation failed!"))); } this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]"); this.logger.LogTrace("(-):{0}={1}, {2}={3}", nameof(contract.Address), contract.Address, nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); repository.SetCode(contract.Address, createData.ContractExecutionCode); repository.SetContractType(contract.Address, contract.Type.Name); return(VmExecutionResult.CreationSuccess(contract.Address, internalTransferList, gasMeter.GasConsumed, invocationResult.Return, contractLogger.GetRawLogs())); }
public ContractLogHolderTests() { this.network = new SmartContractsRegTest(); this.serializer = new ContractPrimitiveSerializer(this.network); this.logHolder = new ContractLogHolder(); }
/// <summary> /// Invokes a method on an existing smart contract /// </summary> public VmExecutionResult ExecuteMethod( IGasMeter gasMeter, IContractState repository, ICallData callData, ITransactionContext transactionContext) { this.logger.LogTrace("(){0}:{1}", nameof(callData.MethodName), callData.MethodName); if (callData.MethodName == null) { this.logger.LogTrace("(-)[CALLCONTRACT_METHODNAME_NOT_GIVEN]"); return(VmExecutionResult.Error(gasMeter.GasConsumed, null)); } byte[] contractExecutionCode = repository.GetCode(callData.ContractAddress); string typeName = repository.GetContractType(callData.ContractAddress); if (contractExecutionCode == null) { return(VmExecutionResult.Error(gasMeter.GasConsumed, new SmartContractDoesNotExistException(callData.MethodName))); } // TODO consolidate this with CallData. MethodCall methodCall = new MethodCall(callData.MethodName, callData.MethodParameters); ContractByteCode code; using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractExecutionCode)) { moduleDefinition.InjectMethodGas(typeName, methodCall); code = moduleDefinition.ToByteCode(); } var internalTransferList = new List <TransferInfo>(); var contractLogger = new ContractLogHolder(this.network); ISmartContractState contractState = this.SetupState(contractLogger, internalTransferList, gasMeter, repository, transactionContext, callData.ContractAddress); Result <IContract> contractLoadResult = this.Load( code, typeName, callData.ContractAddress, contractState); if (!contractLoadResult.IsSuccess) { // TODO this is temporary until we improve error handling overloads var exception = new Exception(contractLoadResult.Error); LogException(exception); this.logger.LogTrace("(-)[LOAD_CONTRACT_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, exception)); } IContract contract = contractLoadResult.Value; LogExecutionContext(this.logger, contract.State.Block, contract.State.Message, contract.Address, callData); IContractInvocationResult invocationResult = contract.Invoke(methodCall); if (!invocationResult.IsSuccess) { this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]:{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Error(gasMeter.GasConsumed, new Exception("Method invocation failed!"))); } this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]"); this.logger.LogTrace("(-):{0}={1}", nameof(gasMeter.GasConsumed), gasMeter.GasConsumed); return(VmExecutionResult.Success(internalTransferList, gasMeter.GasConsumed, invocationResult.Return, contractLogger.GetRawLogs())); }