Пример #1
0
        public void SmartContracts_GasInjector_SingleParamConstructorGasInjectedSuccess()
        {
            SmartContractCompilationResult compilationResult =
                SmartContractCompiler.Compile(TestSingleConstructorSource);

            Assert.True(compilationResult.Success);
            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var gasLimit = (Gas)500000;
            var gasMeter = new GasMeter(gasLimit);

            var callData = new CreateData(gasLimit, originalAssemblyBytes);

            var transactionContext = new TransactionContext(
                txHash: uint256.One,
                blockHeight: 0,
                coinbase: TestAddress.ToUint160(this.network),
                sender: TestAddress.ToUint160(this.network),
                amount: 0
                );

            VmExecutionResult result = this.vm.Create(gasMeter,
                                                      this.repository,
                                                      callData,
                                                      transactionContext);

            // TODO: Un-hard-code this.
            // Constructor: 15
            // Property setter: 12
            // Storage: 150
            Assert.Equal((Gas)177, result.GasConsumed);
        }
Пример #2
0
        public void VM_Throws_Exception_CanCatch()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ThrowExceptionContract.cs");

            Assert.True(compilationResult.Success);

            byte[] contractCode = compilationResult.Compilation;

            var gasLimit = (Gas)10000;
            var gasMeter = new GasMeter(gasLimit);

            uint160 address = TestAddress.ToUint160(this.network);

            var callData = new CallData(gasLimit, address, "ThrowException");

            this.repository.SetCode(address, contractCode);
            this.repository.SetContractType(address, "ThrowExceptionContract");
            var transactionContext = new TransactionContext(uint256.One, 0, address, address, 0);

            VmExecutionResult result = this.vm.ExecuteMethod(gasMeter,
                                                             this.repository,
                                                             callData,
                                                             transactionContext);

            Assert.Equal(typeof(Exception), result.ExecutionException.GetType());
        }
        public void SmartContract_ValidateFormat_InitializedReadonlyField_Fails()
        {
            var adjustedSource = @"
                using System;
                using Stratis.SmartContracts;

                public class FieldTest : SmartContract
                {
                    private readonly int field1 = 1234567;

                    public FieldTest(ISmartContractState state) : base(state)
                    {
                    }
                }
            ";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(adjustedSource);

            Assert.True(compilationResult.Success);

            var validator = new FieldDefinitionValidator();

            byte[] assemblyBytes = compilationResult.Compilation;
            SmartContractDecompilation decomp = SmartContractDecompiler.GetModuleDefinition(assemblyBytes);

            IEnumerable <ValidationResult> result = validator.Validate(decomp.ContractType);

            Assert.NotEmpty(result);
        }
Пример #4
0
        public void TestGasInjector_OutOfGasFails()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/OutOfGasTest.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var gasLimit                  = (Gas)500000;
            var gasMeter                  = new GasMeter(gasLimit);
            var persistenceStrategy       = new MeteredPersistenceStrategy(this.repository, gasMeter, this.keyEncodingStrategy);
            var persistentState           = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network);
            var internalTxExecutorFactory =
                new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);
            var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory);

            var executionContext = new SmartContractExecutionContext(new Block(0, TestAddress), new Message(TestAddress, TestAddress, 0, (Gas)500000), TestAddress.ToUint160(this.network), 1);

            var result = vm.ExecuteMethod(
                originalAssemblyBytes,
                "UseAllGas",
                executionContext,
                gasMeter, persistentState, repository);

            Assert.NotNull(result.ExecutionException);
            Assert.Equal((Gas)0, gasMeter.GasAvailable);
            Assert.Equal(gasLimit, result.GasConsumed);
            Assert.Equal(gasLimit, gasMeter.GasConsumed);
        }
Пример #5
0
        public void SmartContracts_GasInjector_MultipleParamConstructorGasInjectedSuccess()
        {
            SmartContractCompilationResult compilationResult =
                SmartContractCompiler.Compile(TestMultipleConstructorSource);

            Assert.True(compilationResult.Success);
            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var gasLimit                  = (Gas)500000;
            var gasMeter                  = new GasMeter(gasLimit);
            var persistenceStrategy       = new MeteredPersistenceStrategy(this.repository, gasMeter, new BasicKeyEncodingStrategy());
            var persistentState           = new PersistentState(persistenceStrategy, TestAddress.ToUint160(this.network), this.network);
            var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);
            var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory);
            var executionContext = new SmartContractExecutionContext(new Block(0, TestAddress), new Message(TestAddress, TestAddress, 0, (Gas)500000), TestAddress.ToUint160(this.network), 1, new[] { "Tset Owner" });

            var result = vm.Create(
                originalAssemblyBytes,
                executionContext,
                gasMeter, persistentState, repository);

            // Constructor: 15
            // Property setter: 12
            // Storage: 150
            Assert.Equal((Gas)177, result.GasConsumed);
        }
Пример #6
0
        public void TestGasInjector_OutOfGasFails()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/OutOfGasTest.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var gasLimit = (Gas)500000;
            var gasMeter = new GasMeter(gasLimit);
            var internalTxExecutorFactory =
                new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);
            var vm = new ReflectionVirtualMachine(this.validator, internalTxExecutorFactory, this.loggerFactory, this.network);

            var address = TestAddress.ToUint160(this.network);

            var callData = new CallData(gasLimit, address, "UseAllGas");

            var transactionContext = new TransactionContext(uint256.One, 0, address, address, 0);

            this.repository.SetCode(callData.ContractAddress, originalAssemblyBytes);
            this.repository.SetContractType(callData.ContractAddress, "OutOfGasTest");

            var result = vm.ExecuteMethod(gasMeter, this.repository, callData, transactionContext);

            Assert.NotNull(result.ExecutionException);
            Assert.Equal((Gas)0, gasMeter.GasAvailable);
            Assert.Equal(gasLimit, result.GasConsumed);
            Assert.Equal(gasLimit, gasMeter.GasConsumed);
        }
Пример #7
0
        public void VM_Throws_Exception_CanCatch()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ThrowExceptionContract.cs");

            Assert.True(compilationResult.Success);

            byte[] contractCode = compilationResult.Compilation;

            var gasLimit = (Gas)10000;
            var gasMeter = new GasMeter(gasLimit);

            var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);
            var vm = new ReflectionVirtualMachine(this.validator, internalTxExecutorFactory, this.loggerFactory, this.network);

            var address = TestAddress.ToUint160(this.network);

            var callData = new CallData(gasLimit, address, "ThrowException");

            this.repository.SetCode(address, contractCode);
            this.repository.SetContractType(address, "ThrowExceptionContract");
            var transactionContext = new TransactionContext(uint256.One, 0, address, address, 0);

            var result = vm.ExecuteMethod(gasMeter,
                                          this.repository,
                                          callData,
                                          transactionContext);

            Assert.Equal(typeof(Exception), result.ExecutionException.GetType());
        }
Пример #8
0
        public void SmartContract_ValidateFormat_TwoTypes()
        {
            var adjustedSource = @"
using System;
using Stratis.SmartContracts;

public class Test : SmartContract
{
    public Test(ISmartContractState state) : base(state) {}
}


public class Test2 {
}
";
            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(adjustedSource);

            Assert.True(compilationResult.Success);

            var validator = new SmartContractFormatValidator();

            byte[] assemblyBytes             = compilationResult.Compilation;
            IContractModuleDefinition decomp = SmartContractDecompiler.GetModuleDefinition(assemblyBytes);

            var result = validator.Validate(decomp.ModuleDefinition);

            Assert.False(result.IsValid);
            Assert.Equal(2, result.Errors.Count());
        }
Пример #9
0
        /// <summary>
        /// Get the compiled bytecode for the specified C# source code.
        /// </summary>
        /// <param name="source"></param>
        public static SmartContractCompilationResult Compile(string source, IEnumerable <string> additionalReferencePaths = null)
        {
            SyntaxTree syntaxTree = CSharpSyntaxTree.ParseText(source);

            var references = GetReferences().ToList();

            if (additionalReferencePaths != null)
            {
                references.AddRange(additionalReferencePaths.Select(path => MetadataReference.CreateFromFile(path)));
            }

            CSharpCompilation compilation = CSharpCompilation.Create(
                "smartContract",
                new[] { syntaxTree },
                references,
                new CSharpCompilationOptions(
                    OutputKind.DynamicallyLinkedLibrary,
                    checkOverflow: true));


            using (var dllStream = new MemoryStream())
            {
                EmitResult emitResult = compilation.Emit(dllStream);
                if (!emitResult.Success)
                {
                    return(SmartContractCompilationResult.Failed(emitResult.Diagnostics));
                }

                return(SmartContractCompilationResult.Succeeded(dllStream.ToArray()));
            }
        }
Пример #10
0
        public void SmartContract_ValidateFormat_AssemblyReferences()
        {
            var adjustedSource = @"
using System;
using System.Linq;
using Stratis.SmartContracts;

public class Test : SmartContract
{
    public Test(ISmartContractState state) : base(state)
    {
        IQueryable q = null;    
    }
}
";
            SmartContractCompilationResult compilationResult = Compile(adjustedSource, new [] { typeof(IQueryable).Assembly.Location });

            Assert.True(compilationResult.Success);

            var validator = new SmartContractFormatValidator();

            byte[] assemblyBytes             = compilationResult.Compilation;
            IContractModuleDefinition decomp = SmartContractDecompiler.GetModuleDefinition(assemblyBytes);

            var result = validator.Validate(decomp.ModuleDefinition);

            Assert.False(result.IsValid);
            Assert.Single(result.Errors);
        }
        public void SME_CreateContract_MethodParameters_ParameterTypeMismatch()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ContractMethodParameterTypeMismatch.cs");

            Assert.True(compilationResult.Success);
            byte[] contractCode = compilationResult.Compilation;

            string[] methodParameters = new string[]
            {
                string.Format("{0}#{1}", (int)SmartContractCarrierDataType.Bool, true),
            };

            var carrier = SmartContractCarrier.CreateContract(0, contractCode, 1, (Gas)10000, methodParameters);
            var tx      = new Transaction();

            tx.AddOutput(0, new Script(carrier.Serialize()));

            ISmartContractTransactionContext transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, new uint160(2), tx);

            var executor = new Executor(this.loggerFactory,
                                        this.serializer,
                                        this.state,
                                        this.refundProcessor,
                                        this.transferProcessor,
                                        this.vm);

            ISmartContractExecutionResult result = executor.Execute(transactionContext);

            Assert.NotNull(result.Exception);
            Assert.Equal(GasPriceList.BaseCost, result.GasConsumed);
        }
        public void SME_CreateContract_ConstructorFails_Refund()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ContractConstructorInvalid.cs");

            Assert.True(compilationResult.Success);
            byte[] contractCode = compilationResult.Compilation;

            SmartContractCarrier carrier = SmartContractCarrier.CreateContract(0, contractCode, 1, (Gas)10000);
            var tx = new Transaction();

            tx.AddOutput(0, new Script(carrier.Serialize()));

            ISmartContractTransactionContext transactionContext = new SmartContractTransactionContext(BlockHeight, CoinbaseAddress, MempoolFee, new uint160(2), tx);

            var executor = new Executor(this.loggerFactory,
                                        this.serializer,
                                        this.state,
                                        this.refundProcessor,
                                        this.transferProcessor,
                                        this.vm);

            ISmartContractExecutionResult result = executor.Execute(transactionContext);

            Assert.NotNull(result.Exception);
            // Base cost + constructor cost
            Assert.Equal(GasPriceList.BaseCost + 13, result.GasConsumed);
        }
Пример #13
0
        public void Create_WithFunds()
        {
            using (MockChain chain = new MockChain(2))
            {
                MockChainNode sender   = chain.Nodes[0];
                MockChainNode receiver = chain.Nodes[1];

                // Mine some coins so we have balance
                int maturity = (int)chain.Network.Consensus.CoinbaseMaturity;
                TestHelper.MineBlocks(sender.CoreNode, sender.WalletName, sender.Password, sender.AccountName, maturity + 1);
                int spendable = GetSpendableBlocks(maturity + 1, maturity);
                Assert.Equal(Money.COIN * spendable * 50, (long)sender.WalletSpendableBalance);

                // Compile file
                SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/StorageDemo.cs");
                Assert.True(compilationResult.Success);

                // Send create with value, and ensure balance is stored.
                BuildCreateContractTransactionResponse sendResponse = sender.SendCreateContractTransaction(compilationResult.Compilation, 30);
                sender.WaitMempoolCount(1);
                TestHelper.MineBlocks(sender.CoreNode, sender.WalletName, sender.Password, sender.AccountName, 1);

                Assert.Equal((ulong)30 * 100_000_000, sender.GetContractBalance(sendResponse.NewContractAddress));
            }
        }
Пример #14
0
        public void TestGasInjector_OutOfGasFails()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/OutOfGasTest.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var callData = new MethodCall("UseAllGas");

            var module = this.moduleReader.Read(originalAssemblyBytes);

            module.InjectMethodGas("OutOfGasTest", callData);

            var assembly = this.assemblyLoader.Load(module.ToByteCode());

            var contract = Contract.CreateUninitialized(assembly.Value.GetType(module.ContractType.Name), this.state, null);

            var result = contract.Invoke(callData);

            Assert.False(result.IsSuccess);
            Assert.Equal((Gas)0, this.gasMeter.GasAvailable);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
            Assert.Equal(this.gasMeter.GasLimit, this.gasMeter.GasConsumed);
        }
Пример #15
0
        public void VM_Throws_Exception_CanCatch()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ThrowExceptionContract.cs");
            Assert.True(compilationResult.Success);

            byte[] contractCode = compilationResult.Compilation;

            var gasLimit = (Gas)100;
            var gasMeter = new GasMeter(gasLimit);
            var persistenceStrategy = new MeteredPersistenceStrategy(this.repository, gasMeter, this.keyEncodingStrategy);
            var persistentState = new PersistentState(persistenceStrategy,
                TestAddress.ToUint160(this.network), this.network);
            var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);
            var vm = new ReflectionVirtualMachine(internalTxExecutorFactory, this.loggerFactory);

            var context = new SmartContractExecutionContext(
                new Block(0, TestAddress),
                new Message(TestAddress, TestAddress, 0, gasLimit),
                TestAddress.ToUint160(this.network),
                1,
                new object[] { }
            );

            var result = vm.ExecuteMethod(
                contractCode,
                "ThrowException",
                context,
                gasMeter, persistentState, 
                this.repository);

            Assert.Equal(typeof(Exception), result.ExecutionException.GetType());
        }
        public void SmartContract_ValidateFormat_One_CustomStruct()
        {
            var adjustedSource = @"
                using System;
                using Stratis.SmartContracts;

                public class StructTest : SmartContract
                {
                    public struct Item
                    {
                        public int Number;
                        public string Name;
                    }

                    public StructTest(ISmartContractState state) : base(state)
                    {
                    }
                }
            ";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(adjustedSource);

            Assert.True(compilationResult.Success);

            var validator = new NestedTypeValidator();

            byte[] assemblyBytes = compilationResult.Compilation;
            SmartContractDecompilation     decomp = SmartContractDecompiler.GetModuleDefinition(assemblyBytes);
            IEnumerable <ValidationResult> result = validator.Validate(decomp.ContractType);

            Assert.Empty(result);
        }
Пример #17
0
        public void Validate_Determinism_ErrorMessages_TwoMethods()
        {
            string source = @"
                    using Stratis.SmartContracts;

                    public class MessageTest : SmartContract
                    {
                        public MessageTest(ISmartContractState smartContractState)
                            : base(smartContractState)
                        {
                        }

                        public void MessageTestFloat1()
                        {
                            float test = (float) 3.5;
                        }

                        public void MessageTestFloat2()
                        {
                            float test = (float) 3.5;
                        }
                    }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(source);

            Assert.True(compilationResult.Success);

            IContractModuleDefinition     moduleDefinition = SmartContractDecompiler.GetModuleDefinition(compilationResult.Compilation);
            SmartContractValidationResult result           = this.validator.Validate(moduleDefinition.ModuleDefinition);

            Assert.False(result.IsValid);
            Assert.Equal(2, result.Errors.Count());
            Assert.Equal("Float usage", result.Errors.First().ValidationType);
            Assert.Equal("Float usage", result.Errors.Skip(1).Take(1).First().ValidationType);
        }
Пример #18
0
        public void MockChain_AuctionTest()
        {
            using (MockChain chain = new MockChain(2))
            {
                MockChainNode sender   = chain.Nodes[0];
                MockChainNode receiver = chain.Nodes[1];

                sender.MineBlocks(10);

                SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/Auction.cs");
                Assert.True(compilationResult.Success);

                // Create contract and ensure code exists
                BuildCreateContractTransactionResponse response = sender.SendCreateContractTransaction(compilationResult.Compilation, new string[] { "10#20" });
                receiver.WaitMempoolCount(1);
                receiver.MineBlocks(2);
                Assert.NotNull(receiver.GetCode(response.NewContractAddress));
                Assert.NotNull(sender.GetCode(response.NewContractAddress));

                // Call contract and ensure owner is now highest bidder
                BuildCallContractTransactionResponse callResponse = sender.SendCallContractTransaction("Bid", response.NewContractAddress, 2);
                receiver.WaitMempoolCount(1);
                receiver.MineBlocks(2);
                Assert.Equal(sender.GetStorageValue(response.NewContractAddress, "Owner"), sender.GetStorageValue(response.NewContractAddress, "HighestBidder"));

                // Wait 20 blocks and end auction and check for transaction to victor
                sender.MineBlocks(20);
                sender.SendCallContractTransaction("AuctionEnd", response.NewContractAddress, 0);
                sender.WaitMempoolCount(1);
                sender.MineBlocks(1);
                NBitcoin.Block block = sender.GetLastBlock();
                Assert.Equal(3, block.Transactions.Count);
            }
        }
Пример #19
0
        public void Validate_Determinism_Recursion()
        {
            string source = @"
                    using Stratis.SmartContracts;

                    public class RecursionTest : SmartContract
                    {
                        public RecursionTest(ISmartContractState smartContractState)
                            : base(smartContractState)
                        {
                        }

                        public void Bid()
                        {
                            Job(5);
                        }

                        public void Job(int index)
                        {
                            if (index > 0)
                                Job(index - 1);
                        }
                    }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(source);

            Assert.True(compilationResult.Success);

            IContractModuleDefinition     moduleDefinition = SmartContractDecompiler.GetModuleDefinition(compilationResult.Compilation);
            SmartContractValidationResult result           = this.validator.Validate(moduleDefinition.ModuleDefinition);

            Assert.True(result.IsValid);
        }
Пример #20
0
        public void Validate_Determinism_ErrorMessages_Simple_DateTime()
        {
            string source = @"
                    using Stratis.SmartContracts;
                    using System;

                    public class MessageTest : SmartContract
                    {
                        public MessageTest(ISmartContractState smartContractState)
                            : base(smartContractState)
                        {
                        }

                        public void MessageTestDateTime()
                        {
                            var test = DateTime.Now;
                        }
                    }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(source);

            Assert.True(compilationResult.Success);

            IContractModuleDefinition     moduleDefinition = SmartContractDecompiler.GetModuleDefinition(compilationResult.Compilation);
            SmartContractValidationResult result           = this.validator.Validate(moduleDefinition.ModuleDefinition);

            Assert.False(result.IsValid);
            Assert.True(result.Errors.All(e => e is WhitelistValidator.WhitelistValidationResult));
        }
Пример #21
0
        public void Validate_Determinism_Async()
        {
            string adjustedSource = @"using System;
                                            using Stratis.SmartContracts;
                                            using System.Threading.Tasks;

                                            public class Test : SmartContract
                                            {
                                                public Test(ISmartContractState state)
                                                    : base(state) {}

                                            public async void Bid()
                                            {
                                                await Task.Run(job);
                                            }

                                            public async Task job()
                                            {
                                                int w = 9;
                                            }
                                            }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(adjustedSource);

            Assert.True(compilationResult.Success);

            byte[] assemblyBytes = compilationResult.Compilation;
            IContractModuleDefinition     moduleDefinition = SmartContractDecompiler.GetModuleDefinition(assemblyBytes);
            SmartContractValidationResult result           = this.validator.Validate(moduleDefinition.ModuleDefinition);

            Assert.False(result.IsValid);
        }
Пример #22
0
        public void Validate_Determinism_DisallowedMethodParams()
        {
            string adjustedSource = @"using System;
                                            using Stratis.SmartContracts;

                                            public class Test : SmartContract
                                            {
                                                public Test(ISmartContractState state)
                                                    : base(state) {}         

                                                public void DateTime1(DateTime param)
                                                {
                                                }

                                                public void F(float param)
                                                {
                                                }
                                            }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(adjustedSource);

            Assert.True(compilationResult.Success);

            byte[] assemblyBytes = compilationResult.Compilation;
            IContractModuleDefinition     moduleDefinition = SmartContractDecompiler.GetModuleDefinition(assemblyBytes);
            SmartContractValidationResult result           = this.validator.Validate(moduleDefinition.ModuleDefinition);

            Assert.False(result.IsValid);
            Assert.Equal(2, result.Errors.Count());
            Assert.True(result.Errors.All(e => e is MethodParamValidator.MethodParamValidationResult));
            Assert.Contains(result.Errors, e => e.Message.Contains("System.DateTime"));
            Assert.Contains(result.Errors, e => e.Message.Contains("System.Single"));
        }
Пример #23
0
        public void Validate_Determinism_ErrorMessages_Simple_DateTime()
        {
            string source = @"
                    using Stratis.SmartContracts;
                    using System;

                    public class MessageTest : SmartContract
                    {
                        public MessageTest(ISmartContractState smartContractState)
                            : base(smartContractState)
                        {
                        }

                        public void MessageTestDateTime()
                        {
                            var test = DateTime.Now;
                        }
                    }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(source);

            Assert.True(compilationResult.Success);

            SmartContractDecompilation    decompilation = SmartContractDecompiler.GetModuleDefinition(compilationResult.Compilation);
            SmartContractValidationResult result        = this.validator.Validate(decompilation);

            Assert.False(result.IsValid);
            Assert.Single(result.Errors);
            Assert.Equal(SmartContractDeterminismValidator.NonDeterministicMethodReference, result.Errors.First().ValidationType);
        }
Пример #24
0
        public void Validate_Determinism_ErrorMessages_Referenced_OneLevel()
        {
            string source = @"
                    using Stratis.SmartContracts;

                    public class MessageTest : SmartContract
                    {
                        public MessageTest(ISmartContractState smartContractState)
                            : base(smartContractState)
                        {
                        }

                        public void MessageTestValid()
                        {
                            MessageTestFloat1();
                        }

                        public void MessageTestFloat1()
                        {
                            float test = (float) 3.5; test = test + 1;
                        }
                    }";

            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile(source);

            Assert.True(compilationResult.Success);

            SmartContractDecompilation    decompilation = SmartContractDecompiler.GetModuleDefinition(compilationResult.Compilation);
            SmartContractValidationResult result        = this.validator.Validate(decompilation);

            Assert.False(result.IsValid);
            Assert.Single(result.Errors);
            Assert.Equal("Float usage", result.Errors.First().ValidationType);
        }
        public void TestGasInjector_ContractMethodWithRecursion_GasInjectionSucceeds()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/Recursion.cs");

            Assert.True(compilationResult.Success);

            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var gasLimit = (Gas)500000;
            var gasMeter = new GasMeter(gasLimit);
            var internalTxExecutorFactory =
                new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);
            var vm = new ReflectionVirtualMachine(this.validator, internalTxExecutorFactory, this.loggerFactory, this.network, this.addressGenerator);

            uint160 address = TestAddress.ToUint160(this.network);

            var callData = new CallData(gasLimit, address, nameof(Recursion.DoRecursion));

            var transactionContext = new TransactionContext(uint256.One, 0, address, address, 0);

            this.repository.SetCode(callData.ContractAddress, originalAssemblyBytes);
            this.repository.SetContractType(callData.ContractAddress, nameof(Recursion));

            VmExecutionResult result = vm.ExecuteMethod(gasMeter, this.repository, callData, transactionContext);

            Assert.Null(result.ExecutionException);
            Assert.True(result.GasConsumed > 0);
        }
        public void SmartContracts_GasInjector_MultipleParamConstructorGasInjectedSuccess()
        {
            SmartContractCompilationResult compilationResult =
                SmartContractCompiler.Compile(TestMultipleConstructorSource);

            Assert.True(compilationResult.Success);
            byte[] originalAssemblyBytes = compilationResult.Compilation;

            var gasLimit = (Gas)500000;
            var gasMeter = new GasMeter(gasLimit);
            var internalTxExecutorFactory = new InternalTransactionExecutorFactory(this.keyEncodingStrategy, this.loggerFactory, this.network);

            var vm = new ReflectionVirtualMachine(this.validator, internalTxExecutorFactory, this.loggerFactory, this.network, this.addressGenerator);

            var callData = new CreateData(gasLimit, originalAssemblyBytes, new[] { "Test Owner" });

            var transactionContext = new TransactionContext(
                txHash: uint256.One,
                blockHeight: 0,
                coinbase: TestAddress.ToUint160(this.network),
                sender: TestAddress.ToUint160(this.network),
                amount: 0
                );

            VmExecutionResult result = vm.Create(gasMeter,
                                                 this.repository,
                                                 callData, transactionContext);

            // Constructor: 15
            // Property setter: 12
            // Storage: 150
            Assert.Equal((Gas)177, result.GasConsumed);
        }
        public void Create_WithFunds_Via_Controller()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode scSender   = builder.CreateSmartContractPowNode();
                CoreNode scReceiver = builder.CreateSmartContractPowNode();

                builder.StartAll();

                scSender.NotInIBD();
                scReceiver.NotInIBD();

                scSender.FullNode.Network.Consensus.CoinbaseMaturity   = 1L;
                scReceiver.FullNode.Network.Consensus.CoinbaseMaturity = 1L;
                int maturity = (int)scReceiver.FullNode.Network.Consensus.CoinbaseMaturity;

                scSender.FullNode.WalletManager().CreateWallet(Password, WalletName, Passphrase);
                scReceiver.FullNode.WalletManager().CreateWallet(Password, WalletName, Passphrase);
                HdAddress addr = scSender.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference(WalletName, AccountName));
                Features.Wallet.Wallet wallet = scSender.FullNode.WalletManager().GetWalletByName(WalletName);
                Key key = wallet.GetExtendedPrivateKeyForAddress(Password, addr).PrivateKey;

                scSender.SetDummyMinerSecret(new BitcoinSecret(key, scSender.FullNode.Network));
                scReceiver.SetDummyMinerSecret(new BitcoinSecret(key, scReceiver.FullNode.Network));

                scSender.GenerateStratisWithMiner(2);
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(scSender));

                var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount);
                Assert.Equal(Money.COIN * (maturity + 1) * 50, total);

                SmartContractsController       senderSmartContractsController = scSender.FullNode.NodeService <SmartContractsController>();
                SmartContractWalletController  senderWalletController         = scSender.FullNode.NodeService <SmartContractWalletController>();
                SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/StorageDemo.cs");
                Assert.True(compilationResult.Success);

                var buildRequest = new BuildCreateContractTransactionRequest
                {
                    AccountName  = AccountName,
                    Amount       = "30",
                    GasLimit     = "10000",
                    GasPrice     = "1",
                    ContractCode = compilationResult.Compilation.ToHexString(),
                    FeeAmount    = "0.001",
                    Password     = Password,
                    WalletName   = WalletName,
                    Sender       = addr.Address
                };

                JsonResult result   = (JsonResult)senderSmartContractsController.BuildCreateSmartContractTransaction(buildRequest);
                var        response = (BuildCreateContractTransactionResponse)result.Value;
                scSender.CreateRPCClient().AddNode(scReceiver.Endpoint, true);

                SmartContractSharedSteps.SendTransactionAndMine(scSender, scReceiver, senderWalletController, response.Hex);

                ContractStateRepositoryRoot senderState = scSender.FullNode.NodeService <ContractStateRepositoryRoot>();
                Assert.Equal((ulong)30 * 100_000_000, senderState.GetCurrentBalance(new Address(response.NewContractAddress).ToUint160(new SmartContractsRegTest())));
            }
        }
Пример #28
0
        public void Test_CatCreation()
        {
            using (MockChain chain = new MockChain(2))
            {
                MockChainNode sender   = chain.Nodes[0];
                MockChainNode receiver = chain.Nodes[1];

                TestHelper.MineBlocks(sender.CoreNode, sender.WalletName, sender.Password, sender.AccountName, 1);

                SmartContractCompilationResult compilationResult = SmartContractCompiler.CompileFile("SmartContracts/ContractCreation.cs");
                Assert.True(compilationResult.Success);

                // Create contract and ensure code exists
                BuildCreateContractTransactionResponse response = sender.SendCreateContractTransaction(compilationResult.Compilation, 0);
                receiver.WaitMempoolCount(1);
                TestHelper.MineBlocks(receiver.CoreNode, receiver.WalletName, receiver.Password, receiver.AccountName, 2);
                Assert.NotNull(receiver.GetCode(response.NewContractAddress));
                Assert.NotNull(sender.GetCode(response.NewContractAddress));

                // Call contract and ensure internal contract was created.
                BuildCallContractTransactionResponse callResponse = sender.SendCallContractTransaction("CreateCat", response.NewContractAddress, 0);
                receiver.WaitMempoolCount(1);
                TestHelper.MineBlocks(receiver.CoreNode, receiver.WalletName, receiver.Password, receiver.AccountName, 1);
                chain.WaitForAllNodesToSync();
                Assert.Equal(1, BitConverter.ToInt32(sender.GetStorageValue(response.NewContractAddress, "CatCounter")));
                uint160 lastCreatedCatAddress     = new uint160(sender.GetStorageValue(response.NewContractAddress, "LastCreatedCat"));
                uint160 expectedCreatedCatAddress = this.addressGenerator.GenerateAddress(callResponse.TransactionId, 0);
                Assert.Equal(expectedCreatedCatAddress, lastCreatedCatAddress);

                // Test that the contract address, event name, and logging values are available in the bloom, from internal create.
                var scBlockHeader = receiver.GetLastBlock().Header as SmartContractBlockHeader;
                Assert.True(scBlockHeader.LogsBloom.Test(lastCreatedCatAddress.ToBytes()));
                Assert.True(scBlockHeader.LogsBloom.Test(Encoding.UTF8.GetBytes("CatCreated")));
                Assert.True(scBlockHeader.LogsBloom.Test(BitConverter.GetBytes(0)));
                // And sanity test that a random value is not available in bloom.
                Assert.False(scBlockHeader.LogsBloom.Test(Encoding.UTF8.GetBytes("RandomValue")));

                // Do a create that should transfer all funds sent now.
                const double amount = 20;
                BuildCallContractTransactionResponse callResponse2 = sender.SendCallContractTransaction("CreateCatWithFunds", response.NewContractAddress, amount);
                receiver.WaitMempoolCount(1);
                TestHelper.MineBlocks(receiver.CoreNode, receiver.WalletName, receiver.Password, receiver.AccountName, 1);

                // Check created contract has expected balance.
                lastCreatedCatAddress = new uint160(sender.GetStorageValue(response.NewContractAddress, "LastCreatedCat"));
                Assert.Equal(amount * Money.COIN, sender.GetContractBalance(lastCreatedCatAddress.ToAddress(chain.Network)));

                // Check block has 3 transactions. Coinbase, our tx, and then a condensing tx.
                var block = receiver.GetLastBlock();
                Assert.Equal(3, block.Transactions.Count);
                // Condensing tx has 1 input and 1 output - FROM: real tx. TO: new contract address.
                Assert.Single(block.Transactions[2].Inputs);
                Assert.Single(block.Transactions[2].Outputs);
                Assert.Equal(block.Transactions[1].GetHash(), block.Transactions[2].Inputs[0].PrevOut.Hash); //  References tx above.
                Assert.Equal(amount * Money.COIN, (ulong)block.Transactions[2].Outputs[0].Value);
                Assert.True(block.Transactions[2].Inputs[0].ScriptSig.IsSmartContractSpend());
                Assert.True(block.Transactions[2].Outputs[0].ScriptPubKey.IsSmartContractInternalCall());
            }
        }
        public void SmartContract_Compiler_ReturnsFalse()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile("Uncompilable");

            Assert.False(compilationResult.Success);
            Assert.NotEmpty(compilationResult.Diagnostics);
            Assert.Null(compilationResult.Compilation);
        }
        public void SmartContract_Compiler_ReturnsTrue()
        {
            SmartContractCompilationResult compilationResult = SmartContractCompiler.Compile("class C{static void M(){}}");

            Assert.True(compilationResult.Success);
            Assert.Empty(compilationResult.Diagnostics);
            Assert.NotNull(compilationResult.Compilation);
        }