protected PoAMockChainFixture(int nodeNum) { var network = new SmartContractsPoARegTest(); // TODO: The PoA tests seem to use the same network class to do sets of tests with different rule requirements (signed/unsigned). Need to normalise it to avoid this hack. network.Consensus.MempoolRules.Remove(typeof(AllowedCodeHashLogicMempoolRule)); this.builder = SmartContractNodeBuilder.Create(this); CoreNode factory(int nodeIndex) => this.builder.CreateSmartContractPoANode(network, nodeIndex).Start(); PoAMockChain mockChain = new PoAMockChain(nodeNum, factory).Build(); this.Chain = mockChain; MockChainNode node1 = this.Chain.Nodes[0]; MockChainNode node2 = this.Chain.Nodes[1]; // Get premine mockChain.MineBlocks(10); // Send half to other from whoever received premine if ((long)node1.WalletSpendableBalance == node1.CoreNode.FullNode.Network.Consensus.PremineReward.Satoshi) { this.PayHalfPremine(node1, node2); } else { this.PayHalfPremine(node2, node1); } }
protected PoAMockChainFixture(int nodeNum) { var network = new SmartContractsPoARegTest(); this.builder = SmartContractNodeBuilder.Create(this); CoreNode factory(int nodeIndex) => this.builder.CreateSmartContractPoANode(network, nodeIndex).Start(); PoAMockChain mockChain = new PoAMockChain(2, factory).Build(); this.Chain = mockChain; MockChainNode node1 = this.Chain.Nodes[0]; MockChainNode node2 = this.Chain.Nodes[1]; // Get premine mockChain.MineBlocks(10); // Send half to other from whoever received premine if ((long)node1.WalletSpendableBalance == node1.CoreNode.FullNode.Network.Consensus.PremineReward.Satoshi) { this.PayHalfPremine(node1, node2); } else { this.PayHalfPremine(node2, node1); } }
public SmartContractRPCTests() { var network = new SmartContractsPoARegTest(); this.network = network; this.builder = SmartContractNodeBuilder.Create(this); this.nodeFactory = (nodeIndex) => this.builder.CreateSmartContractPoANode(network, nodeIndex).Start(); this.methodParameterStringSerializer = new MethodParameterStringSerializer(this.network); }
public TestChain() { var network = new SmartContractsPoARegTest(); this.network = network; this.builder = SmartContractNodeBuilder.Create(this); this.nodeFactory = (nodeIndex) => this.builder.CreateSmartContractPoANode(network, nodeIndex).Start(); this.chain = new PoAMockChain(2, nodeFactory, SharedWalletMnemonic); this.paramSerializer = new MethodParameterStringSerializer(network); // TODO: Inject }
public PoWMockChain(int numberOfNodes) { this.builder = SmartContractNodeBuilder.Create(this); this.nodes = new MockChainNode[numberOfNodes]; for (int nodeIndex = 0; nodeIndex < numberOfNodes; nodeIndex++) { CoreNode node = this.builder.CreateSmartContractPowNode().Start(); for (int j = 0; j < nodeIndex; j++) { MockChainNode otherNode = this.nodes[j]; TestHelper.Connect(node, otherNode.CoreNode); } this.nodes[nodeIndex] = new MockChainNode(node, this); } }
public PoAMockChain(int numNodes) { this.builder = SmartContractNodeBuilder.Create(this); this.nodes = new MockChainNode[numNodes]; var network = new SmartContractsPoARegTest(); this.Network = network; for (int i = 0; i < numNodes; i++) { CoreNode node = this.builder.CreateSmartContractPoANode(network.FederationKeys[i]).Start(); for (int j = 0; j < i; j++) { MockChainNode otherNode = this.nodes[j]; TestHelper.Connect(node, otherNode.CoreNode); TestHelper.Connect(otherNode.CoreNode, node); } this.nodes[i] = new MockChainNode(node, this); } }
public PoWMockChain(int numNodes) { this.Network = new SmartContractsRegTest(); // TODO: Make this configurable. this.builder = SmartContractNodeBuilder.Create(this); this.nodes = new MockChainNode[numNodes]; for (int i = 0; i < numNodes; i++) { CoreNode node = this.builder.CreateSmartContractPowNode().Start(); // Add other nodes for (int j = 0; j < i; j++) { MockChainNode otherNode = this.nodes[j]; TestHelper.Connect(node, otherNode.CoreNode); TestHelper.Connect(otherNode.CoreNode, node); } this.nodes[i] = new MockChainNode(node, this); } }
public void NodesCanConnectToEachOthers() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { var node1 = builder.CreateSmartContractPowNode().Start(); var node2 = builder.CreateSmartContractPowNode().Start(); Assert.Empty(node1.FullNode.ConnectionManager.ConnectedPeers); Assert.Empty(node2.FullNode.ConnectionManager.ConnectedPeers); TestHelper.Connect(node1, node2); Assert.Single(node1.FullNode.ConnectionManager.ConnectedPeers); Assert.Single(node2.FullNode.ConnectionManager.ConnectedPeers); var behavior = node1.FullNode.ConnectionManager.ConnectedPeers.First().Behaviors.OfType <IConnectionManagerBehavior>().FirstOrDefault(); Assert.False(behavior.AttachedPeer.Inbound); Assert.True(behavior.OneTry); behavior = node2.FullNode.ConnectionManager.ConnectedPeers.First().Behaviors.OfType <IConnectionManagerBehavior>().FirstOrDefault(); Assert.True(behavior.AttachedPeer.Inbound); Assert.False(behavior.OneTry); } }
public void SmartContractsController_Builds_Transaction_With_Minimum_Inputs() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { CoreNode scSender = builder.CreateSmartContractPowNode().WithWallet().Start(); var maturity = (int)scSender.FullNode.Network.Consensus.CoinbaseMaturity; HdAddress addr = TestHelper.MineBlocks(scSender, maturity + 5).AddressUsed; int spendableBlocks = GetSpendableBlocks(maturity + 5, maturity); var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount); Assert.Equal(Money.COIN * spendableBlocks * 50, total); SmartContractsController senderSmartContractsController = scSender.FullNode.NodeService <SmartContractsController>(); SmartContractWalletController senderWalletController = scSender.FullNode.NodeService <SmartContractWalletController>(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/StorageDemo.cs"); Assert.True(compilationResult.Success); var buildRequest = new BuildCreateContractTransactionRequest { AccountName = AccountName, GasLimit = 10_000, 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; var transaction = scSender.FullNode.Network.CreateTransaction(response.Hex); Assert.Single(transaction.Inputs); } }
public void SmartContracts_AddToMempool_Success() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { var stratisNodeSync = builder.CreateSmartContractPowNode().WithWallet().Start(); TestHelper.MineBlocks(stratisNodeSync, 105); // coinbase maturity = 100 var block = stratisNodeSync.FullNode.BlockStore().GetBlockAsync(stratisNodeSync.FullNode.Chain.GetBlock(4).HashBlock).Result; var prevTrx = block.Transactions.First(); var dest = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network); var tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey))); tx.AddOutput(new TxOut("25", dest.PubKey.Hash)); tx.AddOutput(new TxOut("24", new Key().PubKey.Hash)); // 1 btc fee tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false); stratisNodeSync.Broadcast(tx); TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 1); } }
public void SendAndReceiveSmartContractTransactionsUsingController() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { CoreNode scSender = builder.CreateSmartContractPowNode().WithWallet().Start(); CoreNode scReceiver = builder.CreateSmartContractPowNode().WithWallet().Start(); int maturity = (int)scReceiver.FullNode.Network.Consensus.CoinbaseMaturity; HdAddress addr = TestHelper.MineBlocks(scSender, maturity + 5).AddressUsed; int spendable = GetSpendableBlocks(maturity + 5, maturity); var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount); Assert.Equal(Money.COIN * spendable * 50, total); SmartContractsController senderSmartContractsController = scSender.FullNode.NodeService <SmartContractsController>(); SmartContractWalletController senderWalletController = scSender.FullNode.NodeService <SmartContractWalletController>(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/StorageDemo.cs"); Assert.True(compilationResult.Success); Gas gasLimit = (Gas)(SmartContractFormatRule.GasLimitMaximum / 2); var buildRequest = new BuildCreateContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit, GasPrice = SmartContractMempoolValidator.MinGasPrice, 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; TestHelper.Connect(scSender, scReceiver); SmartContractSharedSteps.SendTransaction(scSender, scReceiver, senderWalletController, response.Hex); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // Check receipt was stored and can be retrieved. var receiptResponse = (ReceiptResponse)((JsonResult)senderSmartContractsController.GetReceipt(response.TransactionId.ToString())).Value; Assert.True(receiptResponse.Success); Assert.Equal(response.NewContractAddress, receiptResponse.NewContractAddress); Assert.Null(receiptResponse.To); Assert.Equal(addr.Address, receiptResponse.From); string storageRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress.ToString(), StorageKey = "TestSave", DataType = MethodParameterDataType.String })).Value; Assert.Equal("Hello, smart contract world!", storageRequestResult); string ownerRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress.ToString(), StorageKey = "Owner", DataType = MethodParameterDataType.Address })).Value; Assert.NotEmpty(ownerRequestResult); string counterRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress.ToString(), StorageKey = "Counter", DataType = MethodParameterDataType.Int })).Value; Assert.Equal("12345", counterRequestResult); var callRequest = new BuildCallContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit, GasPrice = SmartContractMempoolValidator.MinGasPrice, Amount = "0", MethodName = "Increment", ContractAddress = response.NewContractAddress, FeeAmount = "0.001", Password = Password, WalletName = WalletName, Sender = addr.Address }; result = (JsonResult)senderSmartContractsController.BuildCallSmartContractTransaction(callRequest); var callResponse = (BuildCallContractTransactionResponse)result.Value; SmartContractSharedSteps.SendTransaction(scSender, scReceiver, senderWalletController, callResponse.Hex); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); counterRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress.ToString(), StorageKey = "Counter", DataType = MethodParameterDataType.Int })).Value; Assert.Equal("12346", counterRequestResult); // Check receipt was stored and can be retrieved. receiptResponse = (ReceiptResponse)((JsonResult)senderSmartContractsController.GetReceipt(callResponse.TransactionId.ToString())).Value; Assert.True(receiptResponse.Success); Assert.Null(receiptResponse.NewContractAddress); Assert.Equal(response.NewContractAddress, receiptResponse.To); Assert.Equal(addr.Address, receiptResponse.From); // Test serialization // TODO: When refactoring integration tests, move this to the one place and test all types, from method param to storage to serialization. var serializationRequest = new BuildCallContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit, GasPrice = SmartContractMempoolValidator.MinGasPrice, Amount = "0", MethodName = "TestSerializer", ContractAddress = response.NewContractAddress, FeeAmount = "0.001", Password = Password, WalletName = WalletName, Sender = addr.Address }; result = (JsonResult)senderSmartContractsController.BuildCallSmartContractTransaction(serializationRequest); var serializationResponse = (BuildCallContractTransactionResponse)result.Value; SmartContractSharedSteps.SendTransaction(scSender, scReceiver, senderWalletController, serializationResponse.Hex); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // Would have only saved if execution completed successfully counterRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress.ToString(), StorageKey = "Int32", DataType = MethodParameterDataType.Int })).Value; Assert.Equal("12345", counterRequestResult); } }
public void SmartContracts_AddToMempool_OnlyValid() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { var stratisNodeSync = builder.CreateSmartContractPowNode().WithWallet().Start(); var callDataSerializer = new CallDataSerializer(new ContractPrimitiveSerializer(stratisNodeSync.FullNode.Network)); TestHelper.MineBlocks(stratisNodeSync, 105); // coinbase maturity = 100 var block = stratisNodeSync.FullNode.BlockStore().GetBlockAsync(stratisNodeSync.FullNode.Chain.GetBlock(4).HashBlock).Result; var prevTrx = block.Transactions.First(); var dest = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network); // Gas higher than allowed limit var tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey))); var contractTxData = new ContractTxData(1, 100, new Gas(10_000_000), new uint160(0), "Test"); tx.AddOutput(new TxOut(1, new Script(callDataSerializer.Serialize(contractTxData)))); tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false); stratisNodeSync.Broadcast(tx); // OP_SPEND in user's tx - we can't sign this because the TransactionBuilder recognises the ScriptPubKey is invalid. tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), new Script(new[] { (byte)ScOpcodeType.OP_SPEND }))); tx.AddOutput(new TxOut(1, new Script(callDataSerializer.Serialize(contractTxData)))); stratisNodeSync.Broadcast(tx); // 2 smart contract outputs tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey))); tx.AddOutput(new TxOut(1, new Script(callDataSerializer.Serialize(contractTxData)))); tx.AddOutput(new TxOut(1, new Script(callDataSerializer.Serialize(contractTxData)))); tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false); stratisNodeSync.Broadcast(tx); // Send to contract uint160 contractAddress = new uint160(123); var state = stratisNodeSync.FullNode.NodeService <IStateRepositoryRoot>(); state.CreateAccount(contractAddress); state.Commit(); tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey))); tx.AddOutput(new TxOut(100, PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(new KeyId(contractAddress)))); tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false); stratisNodeSync.Broadcast(tx); // Gas price lower than minimum tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey))); var lowGasPriceContractTxData = new ContractTxData(1, SmartContractMempoolValidator.MinGasPrice - 1, new Gas(SmartContractFormatRule.GasLimitMaximum), new uint160(0), "Test"); tx.AddOutput(new TxOut(1, new Script(callDataSerializer.Serialize(lowGasPriceContractTxData)))); tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false); stratisNodeSync.Broadcast(tx); // After 5 seconds (plenty of time but ideally we would have a more accurate measure) no txs in mempool. All failed validation. Thread.Sleep(5000); Assert.Empty(stratisNodeSync.CreateRPCClient().GetRawMempool()); // Valid tx still works tx = stratisNodeSync.FullNode.Network.CreateTransaction(); tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey))); tx.AddOutput(new TxOut("25", dest.PubKey.Hash)); tx.AddOutput(new TxOut("24", new Key().PubKey.Hash)); // 1 btc fee tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false); stratisNodeSync.Broadcast(tx); TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 1); } }
public void SendAndReceiveSmartContractTransactionsOnPosNetwork() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { CoreNode scSender = builder.CreateSmartContractPosNode().WithWallet().Start(); CoreNode scReceiver = builder.CreateSmartContractPosNode().WithWallet().Start(); var callDataSerializer = new CallDataSerializer(new ContractPrimitiveSerializer(scSender.FullNode.Network)); var maturity = (int)scSender.FullNode.Network.Consensus.CoinbaseMaturity; HdAddress senderAddress = TestHelper.MineBlocks(scSender, maturity + 5).AddressUsed; // The mining should add coins to the wallet. var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount); Assert.Equal(Money.COIN * 6 * 50, total); // Create a token contract ulong gasPrice = 1; int vmVersion = 1; Gas gasLimit = (Gas)5000; ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferTestPos.cs"); Assert.True(compilationResult.Success); var contractTxData = new ContractTxData(vmVersion, gasPrice, gasLimit, compilationResult.Compilation); var contractCreateScript = new Script(callDataSerializer.Serialize(contractTxData)); var txBuildContext = new TransactionBuildContext(scSender.FullNode.Network) { AccountReference = new WalletAccountReference(WalletName, AccountName), ChangeAddress = senderAddress, MinConfirmations = maturity, FeeType = FeeType.High, WalletPassword = Password, Recipients = new[] { new Recipient { Amount = 0, ScriptPubKey = contractCreateScript } }.ToList() }; // Build the transfer contract transaction var transferContractTransaction = BuildTransferContractTransaction(scSender, txBuildContext); // Add the smart contract transaction to the mempool to be mined. scSender.AddToStratisMempool(transferContractTransaction); // Ensure the smart contract transaction is in the mempool. TestHelper.WaitLoop(() => scSender.CreateRPCClient().GetRawMempool().Length > 0); // Mine the token transaction and wait for it sync TestHelper.MineBlocks(scSender, 1); // Sync to the receiver node TestHelper.ConnectAndSync(scSender, scReceiver); // Ensure that boths nodes has the contract IStateRepositoryRoot senderState = scSender.FullNode.NodeService <IStateRepositoryRoot>(); IStateRepositoryRoot receiverState = scReceiver.FullNode.NodeService <IStateRepositoryRoot>(); IAddressGenerator addressGenerator = scSender.FullNode.NodeService <IAddressGenerator>(); uint160 tokenContractAddress = addressGenerator.GenerateAddress(transferContractTransaction.GetHash(), 0); Assert.NotNull(senderState.GetCode(tokenContractAddress)); Assert.NotNull(receiverState.GetCode(tokenContractAddress)); scSender.FullNode.MempoolManager().Clear(); // Create a transfer token contract compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferTestPos.cs"); Assert.True(compilationResult.Success); contractTxData = new ContractTxData(vmVersion, gasPrice, gasLimit, compilationResult.Compilation); contractCreateScript = new Script(callDataSerializer.Serialize(contractTxData)); txBuildContext = new TransactionBuildContext(scSender.FullNode.Network) { AccountReference = new WalletAccountReference(WalletName, AccountName), ChangeAddress = senderAddress, MinConfirmations = maturity, FeeType = FeeType.High, WalletPassword = Password, Recipients = new[] { new Recipient { Amount = 0, ScriptPubKey = contractCreateScript } }.ToList() }; // Build the transfer contract transaction transferContractTransaction = BuildTransferContractTransaction(scSender, txBuildContext); // Add the smart contract transaction to the mempool to be mined. scSender.AddToStratisMempool(transferContractTransaction); // Wait for the token transaction to be picked up by the mempool TestHelper.WaitLoop(() => scSender.CreateRPCClient().GetRawMempool().Length > 0); TestHelper.MineBlocks(scSender, 1); // Ensure both nodes are synced with each other TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); tokenContractAddress = addressGenerator.GenerateAddress(transferContractTransaction.GetHash(), 0); // nonce is 0 for user contract creation. Assert.NotNull(senderState.GetCode(tokenContractAddress)); Assert.NotNull(receiverState.GetCode(tokenContractAddress)); scSender.FullNode.MempoolManager().Clear(); // Create a call contract transaction which will transfer funds contractTxData = new ContractTxData(1, gasPrice, gasLimit, tokenContractAddress, "Test"); Script contractCallScript = new Script(callDataSerializer.Serialize(contractTxData)); txBuildContext = new TransactionBuildContext(scSender.FullNode.Network) { AccountReference = new WalletAccountReference(WalletName, AccountName), ChangeAddress = senderAddress, MinConfirmations = maturity, FeeType = FeeType.High, WalletPassword = Password, Recipients = new[] { new Recipient { Amount = 1000, ScriptPubKey = contractCallScript } }.ToList() }; // Build the transfer contract transaction var callContractTransaction = BuildTransferContractTransaction(scSender, txBuildContext); // Add the smart contract transaction to the mempool to be mined. scSender.AddToStratisMempool(callContractTransaction); // Wait for the token transaction to be picked up by the mempool TestHelper.WaitLoop(() => scSender.CreateRPCClient().GetRawMempool().Length > 0); TestHelper.MineBlocks(scSender, 1); // Ensure the nodes are synced TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // The balance should now reflect the transfer Assert.Equal((ulong)900, senderState.GetCurrentBalance(tokenContractAddress)); } }
public PoAMockChain(int numNodes) { this.builder = SmartContractNodeBuilder.Create(this); this.nodes = new MockChainNode[numNodes]; }
public void SendAndReceiveLocalSmartContractTransactionsUsingController() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { CoreNode scSender = builder.CreateSmartContractPowNode().WithWallet().Start(); CoreNode scReceiver = builder.CreateSmartContractPowNode().WithWallet().Start(); int maturity = (int)scReceiver.FullNode.Network.Consensus.CoinbaseMaturity; HdAddress addr = TestHelper.MineBlocks(scSender, maturity + 5).AddressUsed; int spendable = GetSpendableBlocks(maturity + 5, maturity); var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount); Assert.Equal(Money.COIN * spendable * 50, total); SmartContractsController senderSmartContractsController = scSender.FullNode.NodeService <SmartContractsController>(); SmartContractWalletController senderWalletController = scSender.FullNode.NodeService <SmartContractWalletController>(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/StorageDemo.cs"); Assert.True(compilationResult.Success); Gas gasLimit = (Gas)(SmartContractFormatRule.GasLimitMaximum / 2); var buildRequest = new BuildCreateContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit.ToString(), GasPrice = SmartContractMempoolValidator.MinGasPrice.ToString(), 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; TestHelper.Connect(scSender, scReceiver); SmartContractSharedSteps.SendTransaction(scSender, scReceiver, senderWalletController, response.Hex); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // Check wallet history is updating correctly. result = (JsonResult)senderWalletController.GetHistory(new WalletHistoryRequest { AccountName = AccountName, WalletName = WalletName }); var walletHistoryModel = (WalletHistoryModel)result.Value; Assert.Single(walletHistoryModel.AccountsHistoryModel.First().TransactionsHistory.Where(x => x.Type == TransactionItemType.Send)); string counterRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress, StorageKey = "Counter", DataType = MethodParameterDataType.Int })).Value; Assert.Equal("12345", counterRequestResult); var callRequest = new BuildCallContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit.ToString(), GasPrice = SmartContractMempoolValidator.MinGasPrice.ToString(), Amount = "0", MethodName = "Increment", ContractAddress = response.NewContractAddress, FeeAmount = "0.001", Password = Password, WalletName = WalletName, Sender = addr.Address }; result = (JsonResult)senderSmartContractsController.LocalCallSmartContractTransaction(callRequest); var callResponse = (ILocalExecutionResult)result.Value; // Check that the locally executed transaction returns the correct results Assert.Equal(12346, callResponse.Return); Assert.False(callResponse.Revert); Assert.True(callResponse.GasConsumed > 0); Assert.Null(callResponse.ErrorMessage); Assert.NotNull(callResponse.InternalTransfers); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // Check that the on-chain storage has not changed after mining counterRequestResult = (string)((JsonResult)senderSmartContractsController.GetStorage(new GetStorageRequest { ContractAddress = response.NewContractAddress, StorageKey = "Counter", DataType = MethodParameterDataType.Int })).Value; Assert.Equal("12345", counterRequestResult); // Check wallet history again to make sure nothing has changed result = (JsonResult)senderWalletController.GetHistory(new WalletHistoryRequest { AccountName = AccountName, WalletName = WalletName }); walletHistoryModel = (WalletHistoryModel)result.Value; Assert.Single(walletHistoryModel.AccountsHistoryModel.First().TransactionsHistory.Where(x => x.Type == TransactionItemType.Send)); } }
public void SendAndReceiveSmartContractTransactions() { NetworkRegistration.Register(new SmartContractsRegTest()); using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { CoreNode scSender = builder.CreateSmartContractPowNode().WithWallet().Start(); CoreNode scReceiver = builder.CreateSmartContractPowNode().WithWallet().Start(); var callDataSerializer = new CallDataSerializer(new ContractPrimitiveSerializer(scSender.FullNode.Network)); var maturity = (int)scSender.FullNode.Network.Consensus.CoinbaseMaturity; HdAddress senderAddress = TestHelper.MineBlocks(scSender, maturity + 5).AddressUsed; // The mining should add coins to the wallet. int spendableBlocks = GetSpendableBlocks(maturity + 5, maturity); var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount); Assert.Equal(Money.COIN * spendableBlocks * 50, total); // Create a token contract. ulong gasPrice = SmartContractMempoolValidator.MinGasPrice; int vmVersion = 1; Gas gasLimit = (Gas)(SmartContractFormatRule.GasLimitMaximum / 2); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferTest.cs"); Assert.True(compilationResult.Success); var contractTxData = new ContractTxData(vmVersion, gasPrice, gasLimit, compilationResult.Compilation); var contractCreateScript = new Script(callDataSerializer.Serialize(contractTxData)); var txBuildContext = new TransactionBuildContext(scSender.FullNode.Network) { AccountReference = new WalletAccountReference(WalletName, AccountName), MinConfirmations = maturity, TransactionFee = new Money(1, MoneyUnit.BTC), FeeType = FeeType.High, WalletPassword = Password, Recipients = new[] { new Recipient { Amount = 0, ScriptPubKey = contractCreateScript } }.ToList() }; Transaction transferContractTransaction = (scSender.FullNode.NodeService <IWalletTransactionHandler>() as SmartContractWalletTransactionHandler).BuildTransaction(txBuildContext); // Broadcast the token transaction to the network. scSender.FullNode.NodeService <IBroadcasterManager>().BroadcastTransactionAsync(transferContractTransaction); // Wait for the token transaction to be picked up by the mempool. TestHelper.WaitLoop(() => scSender.CreateRPCClient().GetRawMempool().Length > 0); // Mine the token transaction and wait for it to sync. TestHelper.MineBlocks(scSender, 1); // Sync to the receiver node. TestHelper.ConnectAndSync(scSender, scReceiver); // Ensure that both nodes have the contract. IStateRepositoryRoot senderState = scSender.FullNode.NodeService <IStateRepositoryRoot>(); IStateRepositoryRoot receiverState = scReceiver.FullNode.NodeService <IStateRepositoryRoot>(); IAddressGenerator addressGenerator = scSender.FullNode.NodeService <IAddressGenerator>(); uint160 tokenContractAddress = addressGenerator.GenerateAddress(transferContractTransaction.GetHash(), 0); Assert.NotNull(senderState.GetCode(tokenContractAddress)); Assert.NotNull(receiverState.GetCode(tokenContractAddress)); scSender.FullNode.MempoolManager().Clear(); // Create a transfer token contract. compilationResult = ContractCompiler.CompileFile("SmartContracts/TransferTest.cs"); Assert.True(compilationResult.Success); contractTxData = new ContractTxData(vmVersion, gasPrice, gasLimit, compilationResult.Compilation); contractCreateScript = new Script(callDataSerializer.Serialize(contractTxData)); txBuildContext = new TransactionBuildContext(scSender.FullNode.Network) { AccountReference = new WalletAccountReference(WalletName, AccountName), MinConfirmations = maturity, TransactionFee = new Money(1, MoneyUnit.BTC), FeeType = FeeType.High, WalletPassword = Password, Recipients = new[] { new Recipient { Amount = 0, ScriptPubKey = contractCreateScript } }.ToList() }; // Broadcast the token transaction to the network. transferContractTransaction = (scSender.FullNode.NodeService <IWalletTransactionHandler>() as SmartContractWalletTransactionHandler).BuildTransaction(txBuildContext); scSender.FullNode.NodeService <IBroadcasterManager>().BroadcastTransactionAsync(transferContractTransaction); // Wait for the token transaction to be picked up by the mempool. TestHelper.WaitLoop(() => scSender.CreateRPCClient().GetRawMempool().Length > 0); TestHelper.MineBlocks(scSender, 1); // Ensure both nodes are synced with each other. TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // Ensure that both nodes have the contract. senderState = scSender.FullNode.NodeService <IStateRepositoryRoot>(); receiverState = scReceiver.FullNode.NodeService <IStateRepositoryRoot>(); tokenContractAddress = addressGenerator.GenerateAddress(transferContractTransaction.GetHash(), 0); Assert.NotNull(senderState.GetCode(tokenContractAddress)); Assert.NotNull(receiverState.GetCode(tokenContractAddress)); scSender.FullNode.MempoolManager().Clear(); // Create a call contract transaction which will transfer funds. contractTxData = new ContractTxData(1, gasPrice, gasLimit, tokenContractAddress, "Test"); Script contractCallScript = new Script(callDataSerializer.Serialize(contractTxData)); txBuildContext = new TransactionBuildContext(scSender.FullNode.Network) { AccountReference = new WalletAccountReference(WalletName, AccountName), MinConfirmations = maturity, TransactionFee = new Money(1, MoneyUnit.BTC), FeeType = FeeType.High, WalletPassword = Password, Recipients = new[] { new Recipient { Amount = 1000, ScriptPubKey = contractCallScript } }.ToList() }; // Broadcast the token transaction to the network. transferContractTransaction = (scSender.FullNode.NodeService <IWalletTransactionHandler>() as SmartContractWalletTransactionHandler).BuildTransaction(txBuildContext); scSender.FullNode.NodeService <IBroadcasterManager>().BroadcastTransactionAsync(transferContractTransaction); TestHelper.WaitLoop(() => scSender.CreateRPCClient().GetRawMempool().Length > 0); // Mine the transaction. TestHelper.MineBlocks(scSender, 1); // Ensure the nodes are synced TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // The balance should now reflect the transfer. Assert.Equal((ulong)900, senderState.GetCurrentBalance(tokenContractAddress)); } }
public void SendAndReceiveLocalSmartContractPropertyCallTransactionsUsingController() { using (SmartContractNodeBuilder builder = SmartContractNodeBuilder.Create(this)) { CoreNode scSender = builder.CreateSmartContractPowNode().WithWallet().Start(); CoreNode scReceiver = builder.CreateSmartContractPowNode().WithWallet().Start(); int maturity = (int)scReceiver.FullNode.Network.Consensus.CoinbaseMaturity; HdAddress addr = TestHelper.MineBlocks(scSender, maturity + 5).AddressUsed; int spendable = GetSpendableBlocks(maturity + 5, maturity); var total = scSender.FullNode.WalletManager().GetSpendableTransactionsInWallet(WalletName).Sum(s => s.Transaction.Amount); Assert.Equal(Money.COIN * spendable * 50, total); SmartContractsController senderSmartContractsController = scSender.FullNode.NodeService <SmartContractsController>(); SmartContractWalletController senderWalletController = scSender.FullNode.NodeService <SmartContractWalletController>(); ContractCompilationResult compilationResult = ContractCompiler.CompileFile("SmartContracts/StorageDemo.cs"); Assert.True(compilationResult.Success); Gas gasLimit = (Gas)(SmartContractFormatRule.GasLimitMaximum / 2); var buildRequest = new BuildCreateContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit, GasPrice = SmartContractMempoolValidator.MinGasPrice, 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; TestHelper.Connect(scSender, scReceiver); SmartContractSharedSteps.SendTransaction(scSender, scReceiver, senderWalletController, response.Hex); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); // Make a call request where the MethodName is the name of a property var callRequest = new BuildCallContractTransactionRequest { AccountName = AccountName, GasLimit = gasLimit, GasPrice = SmartContractMempoolValidator.MinGasPrice, Amount = "0", MethodName = "Counter", ContractAddress = response.NewContractAddress, FeeAmount = "0.001", Password = Password, WalletName = WalletName, Sender = addr.Address }; result = (JsonResult)senderSmartContractsController.LocalCallSmartContractTransaction(callRequest); var callResponse = (ILocalExecutionResult)result.Value; // Check that the locally executed transaction returns the correct results Assert.Equal(12345, callResponse.Return); Assert.False(callResponse.Revert); Assert.True(callResponse.GasConsumed > 0); Assert.Null(callResponse.ErrorMessage); Assert.NotNull(callResponse.InternalTransfers); TestHelper.MineBlocks(scReceiver, 2); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(scReceiver, scSender)); } }
public PoAMockChain(int numNodes, Mnemonic mnemonic = null) { this.builder = SmartContractNodeBuilder.Create(this); this.nodes = new MockChainNode[numNodes]; this.initMnemonic = mnemonic; }