public void Test12() { ContractStateRoot repository = new ContractStateRoot(new MemoryDictionarySource()); IContractState track = repository.StartTracking(); track.SetCode(new uint160(cow), cowCode); track.SetCode(new uint160(horse), horseCode); Assert.Equal(cowCode, track.GetCode(new uint160(cow))); Assert.Equal(horseCode, track.GetCode(new uint160(horse))); track.Rollback(); Assert.Null(repository.GetCode(new uint160(cow))); Assert.Null(repository.GetCode(new uint160(horse))); }
/// <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())); }