Beispiel #1
0
        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
                       ));
        }
Beispiel #2
0
 public InternalExecutor(RuntimeObserver.IGasMeter gasMeter,
                         IState state,
                         IStateProcessor stateProcessor)
 {
     this.gasMeter       = gasMeter;
     this.state          = state;
     this.stateProcessor = stateProcessor;
 }
Beispiel #3
0
        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));
        }
Beispiel #5
0
        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));
        }
Beispiel #8
0
 public MeteredContractLogger(RuntimeObserver.IGasMeter gasMeter, IContractLogger logger, IContractPrimitiveSerializer serializer)
 {
     this.gasMeter   = gasMeter;
     this.logger     = logger;
     this.serializer = serializer;
 }
Beispiel #9
0
 /// <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));
 }
Beispiel #11
0
        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
                       ));
        }