private StateTransitionResult ApplyCreate(IState state, object[] parameters, byte[] code, BaseMessage message, uint160 address, RuntimeObserver.IGasMeter gasMeter, string type = null) { state.ContractState.CreateAccount(address); ISmartContractState smartContractState = state.CreateSmartContractState(state, gasMeter, address, message, state.ContractState); VmExecutionResult result = this.Vm.Create(state.ContractState, smartContractState, gasMeter, code, parameters, type); bool revert = !result.IsSuccess; if (revert) { return(StateTransitionResult.Fail( gasMeter.GasConsumed, result.Error)); } return(StateTransitionResult.Ok( gasMeter.GasConsumed, address, result.Success.Result )); }
public InternalExecutor(RuntimeObserver.IGasMeter gasMeter, IState state, IStateProcessor stateProcessor) { this.gasMeter = gasMeter; this.state = state; this.stateProcessor = stateProcessor; }
public MeteredPersistenceStrategy(IStateRepository stateDb, RuntimeObserver.IGasMeter gasMeter, IKeyEncodingStrategy keyEncodingStrategy) { Guard.NotNull(stateDb, nameof(stateDb)); Guard.NotNull(gasMeter, nameof(gasMeter)); Guard.NotNull(gasMeter, nameof(keyEncodingStrategy)); this.stateDb = stateDb; this.gasMeter = gasMeter; this.keyEncodingStrategy = keyEncodingStrategy; }
/// <summary> /// Invokes a method on an existing smart contract /// </summary> public VmExecutionResult ExecuteMethod(ISmartContractState contractState, RuntimeObserver.IGasMeter gasMeter, MethodCall methodCall, byte[] contractCode, string typeName) { ContractByteCode code; // Code we're loading from database - can assume it's valid. using (IContractModuleDefinition moduleDefinition = this.moduleDefinitionReader.Read(contractCode).Value) { var observer = new Observer(gasMeter, new MemoryMeter(MemoryUnitLimit)); var rewriter = new ObserverRewriter(observer); if (!this.Rewrite(moduleDefinition, rewriter)) { return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Rewrite module failed")); } Result <ContractByteCode> getCodeResult = this.GetByteCode(moduleDefinition); if (!getCodeResult.IsSuccess) { return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Serialize module failed")); } code = getCodeResult.Value; } Result <IContract> contractLoadResult = this.Load( code, typeName, contractState.Message.ContractAddress.ToUint160(), contractState); if (!contractLoadResult.IsSuccess) { return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, contractLoadResult.Error)); } IContract contract = contractLoadResult.Value; this.LogExecutionContext(contract.State.Block, contract.State.Message, contract.Address); IContractInvocationResult invocationResult = contract.Invoke(methodCall); if (!invocationResult.IsSuccess) { this.logger.LogTrace("(-)[CALLCONTRACT_INSTANTIATION_FAILED]"); return(GetInvocationVmErrorResult(invocationResult)); } this.logger.LogTrace("[CALL_CONTRACT_INSTANTIATION_SUCCEEDED]"); return(VmExecutionResult.Ok(invocationResult.Return, typeName)); }
public ObserverTests() { var context = new ContractExecutorTestContext(); this.network = context.Network; this.TestAddress = "0x0000000000000000000000000000000000000001".HexToAddress(); this.repository = context.State; this.moduleReader = new ContractModuleDefinitionReader(); this.assemblyLoader = new ContractAssemblyLoader(); this.gasMeter = new GasMeter((RuntimeObserver.Gas) 5000000); var block = new TestBlock { Coinbase = this.TestAddress, Number = 1 }; var message = new TestMessage { ContractAddress = this.TestAddress, Sender = this.TestAddress, Value = Value }; var getBalance = new Func <ulong>(() => Balance); var persistentState = new TestPersistentState(); var network = new SmartContractsRegTest(); var serializer = new ContractPrimitiveSerializer(network); this.state = new SmartContractState( new Block(1, this.TestAddress), new Message(this.TestAddress, this.TestAddress, 0), new PersistentState(new MeteredPersistenceStrategy(this.repository, this.gasMeter, new BasicKeyEncodingStrategy()), context.Serializer, this.TestAddress.ToUint160()), context.Serializer, new ContractLogHolder(), Mock.Of <IInternalTransactionExecutor>(), new InternalHashHelper(), () => 1000); this.rewriter = new ObserverRewriter(new Observer(this.gasMeter, new MemoryMeter(ReflectionVirtualMachine.MemoryUnitLimit))); }
/// <summary> /// Sets up a new <see cref="ISmartContractState"/> based on the current state. /// </summary> public ISmartContractState Create(IState state, RuntimeObserver.IGasMeter gasMeter, uint160 address, BaseMessage message, IStateRepository repository) { IPersistenceStrategy persistenceStrategy = new MeteredPersistenceStrategy(repository, gasMeter, new BasicKeyEncodingStrategy()); var persistentState = new PersistentState(persistenceStrategy, this.serializer, address); var contractLogger = new MeteredContractLogger(gasMeter, state.LogHolder, this.PrimitiveSerializer); var contractState = new SmartContractState( state.Block, new Message( address.ToAddress(), message.From.ToAddress(), message.Amount ), persistentState, this.serializer, contractLogger, this.InternalTransactionExecutorFactory.Create(gasMeter, state), new InternalHashHelper(), () => state.GetBalance(address)); return(contractState); }
/// <summary> /// Creates a new instance of a smart contract by invoking the contract's constructor /// </summary> public VmExecutionResult Create(IStateRepository repository, ISmartContractState contractState, RuntimeObserver.IGasMeter gasMeter, byte[] contractCode, object[] parameters, string typeName = null) { string typeToInstantiate; ContractByteCode code; // Decompile the contract execution code Result <IContractModuleDefinition> moduleResult = this.moduleDefinitionReader.Read(contractCode); if (moduleResult.IsFailure) { this.logger.LogTrace(moduleResult.Error); this.logger.LogTrace("(-)[CONTRACT_BYTECODE_INVALID]"); return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, "Contract bytecode is not valid IL.")); } // Validate contract execution code using (IContractModuleDefinition moduleDefinition = moduleResult.Value) { 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.Fail(VmExecutionErrorKind.ValidationFailed, new SmartContractValidationException(validation.Errors).ToString())); } typeToInstantiate = typeName ?? moduleDefinition.ContractType.Name; var observer = new Observer(gasMeter, new MemoryMeter(MemoryUnitLimit)); var rewriter = new ObserverRewriter(observer); if (!this.Rewrite(moduleDefinition, rewriter)) { return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Rewrite module failed")); } Result <ContractByteCode> getCodeResult = this.GetByteCode(moduleDefinition); if (!getCodeResult.IsSuccess) { return(VmExecutionResult.Fail(VmExecutionErrorKind.RewriteFailed, "Serialize module failed")); } code = getCodeResult.Value; } Result <IContract> contractLoadResult = this.Load( code, typeToInstantiate, contractState.Message.ContractAddress.ToUint160(), contractState); if (!contractLoadResult.IsSuccess) { return(VmExecutionResult.Fail(VmExecutionErrorKind.LoadFailed, contractLoadResult.Error)); } IContract contract = contractLoadResult.Value; this.LogExecutionContext(contract.State.Block, contract.State.Message, contract.Address); // Set the code and the Type before the method is invoked repository.SetCode(contract.Address, contractCode); repository.SetContractType(contract.Address, typeToInstantiate); // Invoke the constructor of the provided contract code IContractInvocationResult invocationResult = contract.InvokeConstructor(parameters); if (!invocationResult.IsSuccess) { this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_FAILED]"); return(GetInvocationVmErrorResult(invocationResult)); } this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]"); return(VmExecutionResult.Ok(invocationResult.Return, typeToInstantiate)); }
public MeteredContractLogger(RuntimeObserver.IGasMeter gasMeter, IContractLogger logger, IContractPrimitiveSerializer serializer) { this.gasMeter = gasMeter; this.logger = logger; this.serializer = serializer; }
/// <summary> /// Sets up a new <see cref="ISmartContractState"/> based on the current state. /// </summary> public ISmartContractState CreateSmartContractState(IState state, RuntimeObserver.IGasMeter gasMeter, uint160 address, BaseMessage message, IStateRepository repository) { return(this.smartContractStateFactory.Create(state, gasMeter, address, message, repository)); }
public IInternalTransactionExecutor Create(RuntimeObserver.IGasMeter gasMeter, IState state) { return(new InternalExecutor(gasMeter, state, this.stateProcessor)); }
private StateTransitionResult ApplyCall(IState state, CallMessage message, byte[] contractCode, RuntimeObserver.IGasMeter gasMeter) { // This needs to happen after the base fee is charged, which is why it's in here. // TODO - Remove this check. It isn't possible for the method name to be null. if (message.Method.Name == null) { return(StateTransitionResult.Fail(gasMeter.GasConsumed, StateTransitionErrorKind.NoMethodName)); } string type = state.ContractState.GetContractType(message.To); ISmartContractState smartContractState = state.CreateSmartContractState(state, gasMeter, message.To, message, state.ContractState); VmExecutionResult result = this.Vm.ExecuteMethod(smartContractState, gasMeter, message.Method, contractCode, type); bool revert = !result.IsSuccess; if (revert) { return(StateTransitionResult.Fail( gasMeter.GasConsumed, result.Error)); } return(StateTransitionResult.Ok( gasMeter.GasConsumed, message.To, result.Success.Result )); }