public void SmartContract_Constructor_NoParamSuccess()
        {
            LifecycleResult constructionResult = SmartContractConstructor
                                                 .Construct(typeof(NoParamContract), this.state);

            Assert.True(constructionResult.Success);
            Assert.NotNull(constructionResult.Object);
        }
        public void SmartContract_Constructor_ConstructorInvokedSuccess()
        {
            LifecycleResult constructionResult = SmartContractConstructor
                                                 .Construct(typeof(ConstructorInvokedContract), this.state);

            Assert.True(constructionResult.Success);
            Assert.NotNull(constructionResult.Object);
            Assert.True(((ConstructorInvokedContract)constructionResult.Object).ConstructorInvoked);
        }
        public void SmartContract_Constructor_OneParamSuccess()
        {
            ulong startBlock = 12345;

            LifecycleResult constructionResult = SmartContractConstructor
                                                 .Construct(typeof(OneParamContract), this.state, startBlock);

            Assert.True(constructionResult.Success);
            Assert.NotNull(constructionResult.Object);
        }
        public void SmartContract_Constructor_NonpublicStateFieldsSetSuccess()
        {
            LifecycleResult constructionResult = SmartContractConstructor
                                                 .Construct(typeof(NoParamContract), this.state);

            Assert.True(constructionResult.Success);

            SmartContract contract = constructionResult.Object;

            FieldInfo[] fields = typeof(SmartContract).GetFields(
                BindingFlags.Instance
                | BindingFlags.NonPublic
                );

            foreach (FieldInfo field in fields)
            {
                object value = field.GetValue(contract);

                switch (field.Name)
                {
                case "Block":
                    Assert.Equal(this.state.Block, value);
                    break;

                case "Message":
                    Assert.Equal(this.state.Message, value);
                    break;

                case "PersistentState":
                    Assert.Equal(this.state.PersistentState, value);
                    break;

                case "gasMeter":
                    Assert.Equal(this.state.GasMeter, value);
                    break;

                case "getBalance":
                    Assert.Equal(this.state.GetBalance, value);
                    break;

                case "internalTransactionExecutor":
                    Assert.Equal(this.state.InternalTransactionExecutor, value);
                    break;

                case "internalHashHelper":
                    Assert.Equal(this.state.InternalHashHelper, value);
                    break;

                case "smartContractState":
                    Assert.Equal(this.state, value);
                    break;
                }
            }
        }
        public void SmartContract_Constructor_InvalidParamSuccess()
        {
            ulong startBlock = 12345;

            LifecycleResult constructionResult = SmartContractConstructor
                                                 .Construct(typeof(NoParamContract), this.state, startBlock);

            Assert.False(constructionResult.Success);
            Assert.Null(constructionResult.Object);
            Assert.NotNull(constructionResult.Exception);
        }
        /// <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));
        }
Exemplo n.º 7
0
        private static void ValidateContract(string fileName, IConsole console, string[] parameters, ValidationServiceResult validationServiceResult)
        {
            byte[] compilation;
            SmartContractDecompilation decompilation;

            BuildModuleDefinition(console, validationServiceResult, out compilation, out decompilation);

            console.WriteLine($"Validating file {fileName}...");

            Assembly smartContract = Assembly.Load(compilation);

            var serializer = new MethodParameterSerializer();

            object[] methodParameters = null;
            if (parameters.Length != 0)
            {
                var methodParametersRaw = new MethodParameterSerializer().ToRaw(parameters);
                methodParameters = serializer.ToObjects(methodParametersRaw);
            }

            validationServiceResult.LifeCycleResult = SmartContractConstructor.Construct(smartContract.ExportedTypes.FirstOrDefault(), new ValidatorSmartContractState(), methodParameters);
            if (!validationServiceResult.LifeCycleResult.Success)
            {
                console.WriteLine("Smart contract construction failed.");
                console.WriteLine("If the smart contract is constructed with parameters, please ensure they are provided.");
            }

            validationServiceResult.DeterminismValidationResult = new SmartContractDeterminismValidator().Validate(decompilation);
            validationServiceResult.FormatValidationResult      = new SmartContractFormatValidator(ReferencedAssemblyResolver.AllowedAssemblies).Validate(decompilation);
            if (!validationServiceResult.DeterminismValidationResult.IsValid || !validationServiceResult.FormatValidationResult.IsValid)
            {
                console.WriteLine("Smart Contract failed validation. Run validate [FILE] for more info.");
            }

            console.WriteLine();
        }
        /// <summary>
        /// Creates a new instance of a smart contract by invoking the contract's constructor
        /// </summary>
        public VmExecutionResult Create(IGasMeter gasMeter,
                                        IContractStateRepository repository,
                                        ICreateData createData,
                                        ITransactionContext transactionContext)
        {
            this.logger.LogTrace("()");

            // TODO: Spend Validation + Creation Fee here.

            // Decompile the contract execution code and validate it.
            SmartContractDecompilation decompilation = SmartContractDecompiler.GetModuleDefinition(createData.ContractExecutionCode);

            SmartContractValidationResult validation = this.validator.Validate(decompilation);

            // 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)));
            }

            byte[] gasInjectedCode = SmartContractGasInjector.AddGasCalculationToConstructor(createData.ContractExecutionCode, decompilation.ContractType.Name);

            Type contractType = Load(gasInjectedCode, decompilation.ContractType.Name);

            uint160 contractAddress = this.addressGenerator.GenerateAddress(transactionContext.TransactionHash, transactionContext.GetNonceAndIncrement());

            // Create an account for the contract in the state repository.
            repository.CreateAccount(contractAddress);

            IPersistenceStrategy persistenceStrategy = new MeteredPersistenceStrategy(repository, gasMeter, new BasicKeyEncodingStrategy());

            var persistentState = new PersistentState(persistenceStrategy, contractAddress, this.network);

            var internalTransferList = new List <TransferInfo>();

            IInternalTransactionExecutor internalTransactionExecutor = this.internalTransactionExecutorFactory.Create(this, repository, internalTransferList, transactionContext);

            var balanceState = new BalanceState(repository, transactionContext.Amount, internalTransferList);

            var contractState = new SmartContractState(
                new Block(
                    transactionContext.BlockHeight,
                    transactionContext.Coinbase.ToAddress(this.network)
                    ),
                new Message(
                    contractAddress.ToAddress(this.network),
                    transactionContext.From.ToAddress(this.network),
                    transactionContext.Amount
                    ),
                persistentState,
                gasMeter,
                internalTransactionExecutor,
                new InternalHashHelper(),
                () => balanceState.GetBalance(contractAddress));

            LogExecutionContext(this.logger, contractState.Block, contractState.Message, contractAddress, createData);

            // Invoke the constructor of the provided contract code
            LifecycleResult result = SmartContractConstructor.Construct(contractType, contractState, createData.MethodParameters);

            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));
            }

            this.logger.LogTrace("[CREATE_CONTRACT_INSTANTIATION_SUCCEEDED]");

            this.logger.LogTrace("(-):{0}={1}, {2}={3}", nameof(contractAddress), contractAddress, nameof(gasMeter.GasConsumed), gasMeter.GasConsumed);

            repository.SetCode(contractAddress, createData.ContractExecutionCode);
            repository.SetContractType(contractAddress, contractType.Name);

            return(VmExecutionResult.CreationSuccess(contractAddress, internalTransferList, gasMeter.GasConsumed, result.Object));
        }