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