public void TestRpcListUnspentWithParametersIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); var minerAddress = BitcoinAddress.Create(ReadyBlockchain.BitcoinRegTestMinerAddress, network); RPCClient rpcClient = node.CreateRPCClient(); // Validate existing address and minconf. var coins = rpcClient.ListUnspent((int)network.Consensus.CoinbaseMaturity + 2, 99999, minerAddress); coins.Should().NotBeNull(); // Maturity is 100 and we have 150 coins in the current chain. coins.Length.Should().Be(50 - 1); // Validate unknown address. var unknownAddress = new Key().GetBitcoinSecret(network).GetAddress(); coins = rpcClient.ListUnspent(1, 99999, unknownAddress); coins.Should().NotBeNull(); coins.Should().BeEmpty(); // Test just min conf. var response = rpcClient.SendCommand(RPCOperations.listunspent, (int)network.Consensus.CoinbaseMaturity + 2); var result = response.ResultString; result.Should().NotBeNullOrEmpty(); } }
public void IndexAddresses_All_Nodes_Synced_Reorg_Connected() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var nodeConfig = new NodeConfigParameters { { "-addressindex", "1" } }; var minerA = builder.CreateStratisPowNode(network, "ai-4-minerA", configParameters: nodeConfig).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).Start(); var minerB = builder.CreateStratisPowNode(network, "ai-4-minerB", configParameters: nodeConfig).WithDummyWallet().Start(); var syncer = builder.CreateStratisPowNode(network, "ai-4-syncer", configParameters: nodeConfig).Start(); // Sync the network to height 10. TestHelper.ConnectAndSync(syncer, minerA); TestHelper.ConnectAndSync(syncer, minerB); // Stop sending blocks from miner A to syncer TestHelper.DisableBlockPropagation(minerA, syncer); // Stop sending blocks from miner B to syncer TestHelper.DisableBlockPropagation(minerB, syncer); // Miner A advances 2 blocks [12] // Syncer = 10 // Miner A = 12 // Miner B = 10 TestHelper.MineBlocks(minerA, 2); Assert.True(TestHelper.IsNodeSyncedAtHeight(syncer, 10)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, 12)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, 10)); // Miner B advances 1 block [11] // Syncer = 10 // Miner A = 12 // Miner B = 11 TestHelper.MineBlocks(minerB, 1); Assert.True(TestHelper.IsNodeSyncedAtHeight(syncer, 10)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, 12)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, 11)); // Enable sending blocks from miner A to syncer TestHelper.EnableBlockPropagation(minerA, syncer); // Enable sending blocks from miner B to syncer TestHelper.EnableBlockPropagation(minerB, syncer); // Miner B advances 2 blocks [13] // Syncer = 13 // Miner A = 13 // Miner B = 13 TestHelper.MineBlocks(minerA, 1, false); TestHelper.MineBlocks(minerB, 1, false); Assert.True(TestHelper.IsNodeSyncedAtHeight(syncer, 13)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, 13)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, 13)); } }
private Network InitReg() { Network network = new BitcoinRegTest(); network.MoneyUnits = GetMoneyUnitsMainAndTest(); return(network); }
public void IndexAddresses_All_Nodes_Synced() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var nodeConfig = new NodeConfigParameters { { "-addressindex", "1" } }; CoreNode stratisNode1 = builder.CreateStratisPowNode(network, "ai-1-stratisNode1", configParameters: nodeConfig).WithDummyWallet().Start(); CoreNode stratisNode2 = builder.CreateStratisPowNode(network, "ai-1-stratisNode2", configParameters: nodeConfig).WithDummyWallet().Start(); CoreNode stratisNode3 = builder.CreateStratisPowNode(network, "ai-1-stratisNode3", configParameters: nodeConfig).WithDummyWallet().Start(); // Connect all the nodes. TestHelper.Connect(stratisNode1, stratisNode2); TestHelper.Connect(stratisNode1, stratisNode3); TestHelper.Connect(stratisNode2, stratisNode3); // Mine up to a height of 100. TestHelper.MineBlocks(stratisNode1, 100); TestBase.WaitLoop(() => stratisNode1.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 100); TestBase.WaitLoop(() => stratisNode2.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 100); TestBase.WaitLoop(() => stratisNode3.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 100); } }
public void TestRpcSendToAddressSpendRefreshesTimeout() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); var aliceAddress = new Key().GetBitcoinSecret(network).GetAddress(); RPCClient rpcClient = node.CreateRPCClient(); // Unlock for 20 seconds. rpcClient.WalletPassphrase("password", 20); // Send a transaction. rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)).Should().NotBeNull(); // Wait 10 seconds and then send another transaction, should still be unlocked. Thread.Sleep(10 * 1000); var bobAddress = new Key().GetBitcoinSecret(network).GetAddress(); rpcClient.SendToAddress(bobAddress, Money.Coins(1.0m)).Should().NotBeNull(); // Now wait 10 seconds so the wallet should be back locked and a transaction should fail. Thread.Sleep(10 * 1000); Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); } }
public void TestRpcListUnspentWithParametersIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); const int numCoins = 5; int blocksToMine = (int)network.Consensus.CoinbaseMaturity + numCoins; TestHelper.MineBlocks(node, blocksToMine); TestHelper.WaitLoop(() => node.FullNode.GetBlockStoreTip().Height == blocksToMine); var minerAddress = BitcoinAddress.Create(node.MinerHDAddress.Address, network); // validate existing address and minconf var coins = rpcClient.ListUnspent((int)network.Consensus.CoinbaseMaturity + 2, 99999, minerAddress); coins.Should().NotBeNull(); coins.Length.Should().Be(numCoins - 1); // validate unknown address var unknownAddress = new Key().GetBitcoinSecret(network).GetAddress(); coins = rpcClient.ListUnspent(1, 99999, unknownAddress); coins.Should().NotBeNull(); coins.Should().BeEmpty(); // test just min conf var response = rpcClient.SendCommand(RPCOperations.listunspent, (int)network.Consensus.CoinbaseMaturity + 2); var result = response.ResultString; result.Should().NotBeNullOrEmpty(); } }
public void TestRpcSendToAddressCantSpendWhenLocked() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); int blocksToMine = (int)network.Consensus.CoinbaseMaturity + 1; TestHelper.MineBlocks(node, blocksToMine); TestHelper.WaitLoop(() => node.FullNode.GetBlockStoreTip().Height == blocksToMine); var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); // Not unlocked case. Assert.Throws <RPCException>(() => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m))); // Unlock and lock case. rpcClient.WalletPassphrase("password", 60); rpcClient.SendCommand(RPCOperations.walletlock); Assert.Throws <RPCException>(() => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m))); // Unlock timesout case. rpcClient.WalletPassphrase("password", 5); Thread.Sleep(120 * 1000); // 2 minutes. Assert.Throws <RPCException>(() => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m))); } }
public void TestRpcSendToAddressIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); int blocksToMine = (int)network.Consensus.CoinbaseMaturity + 1; TestHelper.MineBlocks(node, blocksToMine); TestHelper.WaitLoop(() => node.FullNode.GetBlockStoreTip().Height == blocksToMine); var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); rpcClient.WalletPassphrase("password", 60); var txid = rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)); rpcClient.SendCommand(RPCOperations.walletlock); // Check the hash calculated correctly. var tx = rpcClient.GetRawTransaction(txid); Assert.Equal(txid, tx.GetHash()); // Check the output is the right amount. var coin = tx.Outputs.AsCoins().First(c => c.ScriptPubKey == aliceAddress.ScriptPubKey); Assert.Equal(coin.Amount, Money.Coins(1.0m)); } }
public void TestRpcSendToAddressCantSpendWhenLocked() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); var aliceAddress = new Key().GetBitcoinSecret(network).GetAddress(); RPCClient rpcClient = node.CreateRPCClient(); // Not unlocked case. Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); // Unlock and lock case. rpcClient.WalletPassphrase("password", 60); rpcClient.SendCommand(RPCOperations.walletlock); action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); // Unlock timesout case. rpcClient.WalletPassphrase("password", 5); Thread.Sleep(10 * 1000); // 10 seconds. action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); } }
public void IndexAddresses_All_Nodes_Synced_Reorg() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var nodeConfig = new NodeConfigParameters { { "-addressindex", "1" } }; var minerA = builder.CreateStratisPowNode(network, "ai-2-minerA", configParameters: nodeConfig).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).Start(); var minerB = builder.CreateStratisPowNode(network, "ai-2-minerB", configParameters: nodeConfig).WithDummyWallet().Start(); var syncer = builder.CreateStratisPowNode(network, "ai-2-syncer", configParameters: nodeConfig).Start(); // Sync the network to height 10. TestHelper.ConnectAndSync(syncer, minerA, minerB); // Disconnect syncer from miner B TestHelper.Disconnect(syncer, minerB); // MinerA = 15 // MinerB = 10 // Syncer = 15 TestHelper.MineBlocks(minerA, 5); TestBase.WaitLoop(() => TestHelper.AreNodesSynced(syncer, minerA)); // MinerA = 15 // MinerB = 15 // Syncer = 15 TestHelper.Connect(syncer, minerB); // Disconnect syncer from miner A TestHelper.Disconnect(syncer, minerA); // MinerA = 15 // MinerB = 25 // Syncer = 25 TestHelper.MineBlocks(minerB, 10); TestBase.WaitLoop(() => TestHelper.AreNodesSynced(syncer, minerB)); // MinerA = 35 // MinerB = 25 // Syncer = 25 TestHelper.MineBlocks(minerA, 20); TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 35)); TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 25)); TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 25)); TestHelper.Connect(syncer, minerA); Assert.True(TestHelper.IsNodeSyncedAtHeight(syncer, 35)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, 35)); Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, 35)); TestBase.WaitLoop(() => minerA.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 35); TestBase.WaitLoop(() => minerB.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 35); TestBase.WaitLoop(() => syncer.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 35); } }
public void ReorgChain_AfterInitialRewind_ChainB_MinerB_Disconnects() { using (var builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var minerA = builder.CreateStratisPowNode(network).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).WithDummyWallet(); var minerB = builder.CreateStratisPowNode(network).WithDummyWallet(); var syncer = builder.CreateStratisPowNode(network).WithDummyWallet(); bool minerADisconnectedFromMinerB = false; // Configure the interceptor to disconnect a node after a certain block has been disconnected (rewound). void interceptor(ChainedHeaderBlock chainedHeaderBlock) { if (minerADisconnectedFromMinerB) { return; } if (chainedHeaderBlock.ChainedHeader.Previous.Height == 10) { // Ensure that minerA's tips has rewound to 10. TestHelper.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 10)); TestHelper.Disconnect(minerA, minerB); minerADisconnectedFromMinerB = true; return; } } minerA.SetDisconnectInterceptor(interceptor); // Start the nodes. minerA.Start(); minerB.Start(); syncer.Start(); // MinerB/Syncer syncs with MinerA. TestHelper.ConnectAndSync(minerA, minerB, syncer); // Disable block propagation from MinerA to MinerB so that it can mine on its own and create a fork. TestHelper.DisableBlockPropagation(minerA, minerB); // MinerA continues to mine to height 14. TestHelper.MineBlocks(minerA, 4); TestHelper.WaitLoop(() => minerA.FullNode.ConsensusManager().Tip.Height == 14); TestHelper.WaitLoop(() => minerB.FullNode.ConsensusManager().Tip.Height == 10); TestHelper.WaitLoop(() => syncer.FullNode.ConsensusManager().Tip.Height == 14); // MinerB mines 5 more blocks so that a reorg is triggered. TestHelper.MineBlocks(minerB, 5); TestHelper.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 15)); // MinerA and Syncer should have reorged to the longer chain. TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(minerA, minerB)); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(syncer, minerB)); } }
public void TestRpcSendManyWithValidDataIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); int blocksToMine = (int)network.Consensus.CoinbaseMaturity + 1; TestHelper.MineBlocks(node, blocksToMine); TestHelper.WaitLoop(() => node.FullNode.GetBlockStoreTip().Height == blocksToMine); var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); var bob = new Key().GetBitcoinSecret(network); var bobAddress = bob.GetAddress(); rpcClient.WalletPassphrase("password", 60); // Test with just defaults. const decimal coinsForAlice = 1.0m; const decimal coinsForBob = 2.0m; Dictionary <string, decimal> addresses = new Dictionary <string, decimal>(); addresses.Add(aliceAddress.ToString(), coinsForAlice); addresses.Add(bobAddress.ToString(), coinsForBob); var addressesJson = JsonConvert.SerializeObject(addresses); var response = rpcClient.SendCommand(RPCOperations.sendmany, string.Empty, addressesJson); var txid = new uint256(response.ResultString); // Check the hash calculated correctly. var tx = rpcClient.GetRawTransaction(txid); txid.Should().Be(tx.GetHash()); // Check the output is the right amount. var aliceCoins = tx.Outputs.AsCoins().First(c => c.ScriptPubKey == aliceAddress.ScriptPubKey); aliceCoins.Amount.Should().Be(Money.Coins(coinsForAlice)); var bobCoins = tx.Outputs.AsCoins().First(c => c.ScriptPubKey == bobAddress.ScriptPubKey); bobCoins.Amount.Should().Be(Money.Coins(coinsForBob)); // TODO: Enable test below once WalletTransactionHandler supports recepients with SubtractFeeFromAmount=true // Test option to subtract fees from outputs. //var subtractFeeAddresses = new[] { aliceAddress.ToString(), bobAddress.ToString() }; //response = rpcClient.SendCommand(RPCOperations.sendmany, string.Empty, addressesJson, 0, string.Empty, subtractFeeAddresses); //txid = new uint256(response.ResultString); // Check the hash calculated correctly. //tx = rpcClient.GetRawTransaction(txid); //txid.Should().Be(tx.GetHash()); // Check the output is the right amount. //aliceCoins = tx.Outputs.AsCoins().First(c => c.ScriptPubKey == aliceAddress.ScriptPubKey); //aliceCoins.Amount.Should().NotBeSameAs(Money.Coins(coinsForAlice)); //bobCoins = tx.Outputs.AsCoins().First(c => c.ScriptPubKey == bobAddress.ScriptPubKey); //bobCoins.Amount.Should().NotBeSameAs(Money.Coins(coinsForBob)); } }
public void TestRpcGetNetworkInfo() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); RPCClient rpcClient = node.CreateRPCClient(); var response = rpcClient.SendCommand(RPCOperations.getnetworkinfo); response.ResultString.Should().NotBeNullOrEmpty(); } }
public void TestRpcSendToAddressInsufficientFunds() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); var aliceAddress = new Key().GetBitcoinSecret(network).GetAddress(); RPCClient rpcClient = node.CreateRPCClient(); rpcClient.WalletPassphrase("password", 30); Action action = () => rpcClient.SendToAddress(aliceAddress, Money.Coins(10000.0m)); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_ERROR); } }
public void TestRpcListUnspentWithDefaultsIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); const int numCoins = 5; int blocksToMine = (int)network.Consensus.CoinbaseMaturity + numCoins; TestHelper.MineBlocks(node, blocksToMine); TestHelper.WaitLoop(() => node.FullNode.GetBlockStoreTip().Height == blocksToMine); var coins = rpcClient.ListUnspent(); coins.Should().NotBeNull(); coins.Length.Should().Be(numCoins); } }
public void TestRpcGetBalanceIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); CoreNode node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); int maturity = (int)network.Consensus.CoinbaseMaturity; TestHelper.MineBlocks(node, maturity); Assert.Equal(Money.Zero, rpcClient.GetBalance()); // test with defaults. TestHelper.MineBlocks(node, 1); Assert.Equal(Money.Coins(50), rpcClient.GetBalance(0, false)); // test with parameters. } }
public async Task TestScanRPCCapabilitiesOnBitcoinNetworkAsync() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest10Miner).Start(); RPCClient rpcClient = node.CreateRPCClient(); RPCCapabilities capabilities = await rpcClient.ScanRPCCapabilitiesAsync(); capabilities.SupportEstimateSmartFee.Should().BeFalse(); capabilities.SupportGetNetworkInfo.Should().BeTrue(); capabilities.SupportScanUTXOSet.Should().BeFalse(); capabilities.SupportSignRawTransactionWith.Should().BeFalse(); capabilities.SupportSegwit.Should().BeTrue(); capabilities.SupportGenerateToAddress.Should().BeTrue(); } }
public void TestRpcSendManyWithLockedWalletFails() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); RPCClient rpcClient = node.CreateRPCClient(); var addresses = new Dictionary <string, decimal> { { new Key().GetBitcoinSecret(network).GetAddress().ToString(), 1.0m }, { new Key().GetBitcoinSecret(network).GetAddress().ToString(), 2.0m } }; var addressesJson = JsonConvert.SerializeObject(addresses); Action action = () => rpcClient.SendCommand(RPCOperations.sendmany, string.Empty, addressesJson); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_WALLET_UNLOCK_NEEDED); } }
public void TestRpcGetBlockHeaderForBestBlockHashSuccessfull() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(new BitcoinRegTest()).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); RPCClient rpcClient = node.CreateRPCClient(); var hash = rpcClient.GetBestBlockHash(); // get hex representation of block header RPCResponse resp = rpcClient.SendCommand("getblockheader", hash.ToString(), false); // load header from hex representation var header = rpcClient.Network.Consensus.ConsensusFactory.CreateBlockHeader(); var bytes = Encoders.Hex.DecodeData(resp.Result.Value <string>()); header.FromBytes(bytes); // validate header has same hash as best block header.GetHash().Should().Be(hash); } }
public void TestRpcSendManyWithInvalidParametersFails() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithWallet().Start(); RPCClient rpcClient = node.CreateRPCClient(); rpcClient.WalletPassphrase("password", 60); // Test with empty list of addresses var addresses = new Dictionary <string, decimal>(); var addressesJson = JsonConvert.SerializeObject(addresses); Action action = () => rpcClient.SendCommand(RPCOperations.sendmany, string.Empty, addressesJson); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_PARAMETER); // Test with malformed Json. addressesJson = "[\"address\""; action = () => rpcClient.SendCommand(RPCOperations.sendmany, string.Empty, addressesJson); action.Should().Throw <RPCException>().Which.RPCCode.Should().Be(RPCErrorCode.RPC_PARSE_ERROR); } }
public void TestRpcSendToAddressIsSuccessful() { using (NodeBuilder builder = NodeBuilder.Create(this)) { Network network = new BitcoinRegTest(); var node = builder.CreateStratisPowNode(network).WithReadyBlockchainData(ReadyBlockchain.BitcoinRegTest150Miner).Start(); RPCClient rpcClient = node.CreateRPCClient(); var alice = new Key().GetBitcoinSecret(network); var aliceAddress = alice.GetAddress(); rpcClient.WalletPassphrase("password", 60); var txid = rpcClient.SendToAddress(aliceAddress, Money.Coins(1.0m)); rpcClient.SendCommand(RPCOperations.walletlock); // Check the hash calculated correctly. var tx = rpcClient.GetRawTransaction(txid); Assert.Equal(txid, tx.GetHash()); // Check the output is the right amount. var coin = tx.Outputs.AsCoins().First(c => c.ScriptPubKey == aliceAddress.ScriptPubKey); Assert.Equal(coin.Amount, Money.Coins(1.0m)); } }
public ProofOfWorkMiningTests() { this.regTest = new BitcoinRegTest(); }
public async Task ListAddressGroupingsAsync() { using (var builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var nodeConfig = new NodeConfigParameters { { "-txIndex", "1" } }; this.miner = builder.CreateStratisPowNode(network, agent: "la-1-miner", configParameters: nodeConfig).WithWallet().Start(); this.receiver = builder.CreateStratisPowNode(network, agent: "la-1-receiver", configParameters: nodeConfig).WithWallet().Start(); // Mine blocks to get coins. TestHelper.MineBlocks(this.miner, 101); // Sync miner with receiver. TestHelper.ConnectAndSync(this.miner, this.receiver); // Send 10 coins from miner to receiver. SendCoins(this.miner, this.receiver, Money.Coins(10)); // Receiver's listaddressgroupings response contains 1 array with 1 item. var result = await CallListAddressGroupingsAsync(); result.Count().Should().Be(1); result[0].AddressGroups.First().Amount.Should().Be(Money.Coins(10)); // Send 5 coins to miner from receiver; this will return 5 coins back to a change address on receiver. SendCoins(this.receiver, this.miner, Money.Coins(5)); // Get the change address. var receiver_Wallet = this.receiver.FullNode.WalletManager().GetWallet(walletName); var firstChangeAddress = receiver_Wallet.GetAllAddresses().First(a => a.IsChangeAddress() && a.Transactions.Any()); //--------------------------------------------------- // Receiver's listaddressgroupings response contains 1 array with 2 items: // - The initial receive address // - The change address address //--------------------------------------------------- result = await CallListAddressGroupingsAsync(); result.Count().Should().Be(1); result[0].AddressGroups.Count().Should().Be(2); result[0].AddressGroups.First().Amount.Should().Be(Money.Coins(0)); // Initial receive address balance should be 0. result[0].AddressGroups.First(a => a.Address == firstChangeAddress.Address).Amount.Should().Be(Money.Coins((decimal)4.9999548)); // Change address balance after sending 5 coins. //--------------------------------------------------- // Send 5 coins from miner to receiver's change address SendCoins(this.miner, this.receiver, Money.Coins(5), firstChangeAddress); //--------------------------------------------------- // Receiver's listaddressgroupings response contains 1 array with 2 items: // - The initial receive address // - The change address address //--------------------------------------------------- result = await CallListAddressGroupingsAsync(); result.Count().Should().Be(1); result[0].AddressGroups.Count().Should().Be(2); result[0].AddressGroups.First().Amount.Should().Be(Money.Coins(0)); // Initial receive address balance should be 0. result[0].AddressGroups.First(a => a.Address == firstChangeAddress.Address).Amount.Should().Be(Money.Coins((decimal)4.9999548 + 5)); // Change address balance + 5 coins. //--------------------------------------------------- // Send the (full balance - 1) from receiver to miner. var balance = this.receiver.FullNode.WalletManager().GetSpendableTransactionsInWallet(walletName).Sum(t => t.Transaction.Amount) - Money.Coins(1); SendCoins(this.receiver, this.miner, balance); // Get the change address. receiver_Wallet = this.receiver.FullNode.WalletManager().GetWallet(walletName); var changeAddresses = receiver_Wallet.GetAllAddresses().Where(a => a.IsChangeAddress() && a.Transactions.Any()); var secondChangeAddress = receiver_Wallet.GetAllAddresses().First(a => a.IsChangeAddress() && a.Transactions.Any() && a.Address != firstChangeAddress.Address); //--------------------------------------------------- // Receiver's listaddressgroupings response contains 1 array with 3 items: // - The initial receive address // - The change address address // - The change address of sending the full balance - 1 //--------------------------------------------------- result = await CallListAddressGroupingsAsync(); result.Count().Should().Be(1); result[0].AddressGroups.Count().Should().Be(3); result[0].AddressGroups.Count(a => a.Address == firstChangeAddress.Address).Should().Be(1); result[0].AddressGroups.Count(a => a.Address == secondChangeAddress.Address).Should().Be(1); result[0].AddressGroups.First(a => a.Address == secondChangeAddress.Address).Amount.Should().Be(Money.Coins((decimal)0.99992520)); //--------------------------------------------------- // Send 5 coins to a new unused address on the receiver's wallet. SendCoins(this.miner, this.receiver, Money.Coins(5)); // Receiver's listaddressgroupings response contains 2 arrays: // - Array 1 > The initial receive address // - Array 1 > The change address address // - Array 1 > The change address of sending the full balance - 1 // - Array 2 > The receive address of the new transaction result = await CallListAddressGroupingsAsync(); result.Count().Should().Be(2); result[1].AddressGroups[0].Amount.Should().Be(Money.Coins(5)); } }
public void ReorgChain_AfterInitialRewind_ChainA_Extension_MinerC_Disconnects() { using (var builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var minerA = builder.CreateStratisPowNode(network).WithDummyWallet(); var minerB = builder.CreateStratisPowNode(network).NoValidation().WithDummyWallet(); var syncer = builder.CreateStratisPowNode(network).WithDummyWallet(); // Configure the interceptor to disconnect a node after a certain block has been disconnected (rewound). bool interceptor(ChainedHeaderBlock chainedHeaderBlock) { if (chainedHeaderBlock.ChainedHeader.Previous.Height == 5) { // Ensure that minerA's tip has rewound to 5. TestHelper.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 5)); TestHelper.Disconnect(minerA, syncer); return(true); } return(false); } minerA.BlockDisconnectInterceptor(interceptor); // Start the nodes. minerA.Start(); minerB.Start(); syncer.Start(); // MinerA mines 5 blocks. TestHelper.MineBlocks(minerA, 5); // minerB and syncer syncs with minerA. TestHelper.ConnectAndSync(minerA, minerB, syncer); // Disconnect minerB from miner so that it can mine on its own and create a fork. TestHelper.Disconnect(minerA, minerB); // MinerA continues to mine to height 9. TestHelper.MineBlocks(minerA, 4); TestHelper.WaitLoop(() => minerA.FullNode.ConsensusManager().Tip.Height == 9); TestHelper.WaitLoop(() => minerB.FullNode.ConsensusManager().Tip.Height == 5); TestHelper.WaitLoop(() => syncer.FullNode.ConsensusManager().Tip.Height == 9); // minerB mines 5 more blocks: // Block 6,7,9,10 = valid // Block 8 = invalid Assert.False(TestHelper.IsNodeConnected(minerB)); TestHelper.BuildBlocks.OnNode(minerB).Amount(5).Invalid(8, (node, block) => BlockBuilder.InvalidCoinbaseReward(node, block)).BuildAsync(); // Reconnect minerA to minerB. TestHelper.Connect(minerA, minerB); // minerB should be disconnected from minerA. TestHelper.WaitLoop(() => !TestHelper.IsNodeConnectedTo(minerA, minerB)); // syncer should be disconnected from minerA (via interceptor). TestHelper.WaitLoop(() => !TestHelper.IsNodeConnectedTo(minerA, syncer)); // The reorg will fail at block 8 and roll back any changes. TestHelper.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 9)); TestHelper.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 10)); TestHelper.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 9)); } }
public void CreateWalletData() { string walltName = "wallet-with-funds"; string path = Path.Combine(WalletOutputDataPath + @"\txdb", walltName + ".db"); if (File.Exists(path)) { File.Delete(path); } var network = new BitcoinRegTest(); var folder = new DataFolder(WalletOutputDataPath); var wallet = new Features.Wallet.Types.Wallet() { Name = walltName }; var walletStore = new WalletStore(network, folder, wallet); string dataPath = Path.Combine(DataPath, "wallet-data-table.json"); var dataTable = JsonConvert.DeserializeObject <WalletDataItem[]>(File.ReadAllText(dataPath))[0]; WalletData walletData = new WalletData { Key = dataTable.Id, WalletName = dataTable.WalletName, EncryptedSeed = dataTable.EncryptedSeed, WalletTip = new HashHeightPair(uint256.Parse(dataTable.WalletTip.Split("-")[1]), int.Parse(dataTable.WalletTip.Split("-")[0])), BlockLocator = dataTable.BlockLocator.Select(uint256.Parse).ToList() }; walletStore.SetData(walletData); dataPath = Path.Combine(DataPath, "wallet-transactions-table.json"); var transactionsTable = JsonConvert.DeserializeObject <TransactionDataItem[]>(File.ReadAllText(dataPath)); foreach (var item in transactionsTable) { var trx = new TransactionOutputData { OutPoint = new OutPoint(uint256.Parse(item.OutPoint.Split("-")[0]), int.Parse(item.OutPoint.Split("-")[1])), Address = item.Address, Id = uint256.Parse(item.Id), Amount = new Money(item.Amount), Index = item.Index, BlockHeight = item.BlockHeight, BlockHash = item.BlockHash != null?uint256.Parse(item.BlockHash) : null, CreationTime = DateTimeOffset.FromUnixTimeSeconds(long.Parse(item.CreationTime)), ScriptPubKey = new Script(Encoders.Hex.DecodeData(item.ScriptPubKey)), IsPropagated = item.IsPropagated, AccountIndex = item.AccountIndex, IsCoinStake = item.IsCoinStake, IsCoinBase = item.IsCoinBase, IsColdCoinStake = item.IsColdCoinStake, }; if (item.SpendingDetails != null) { trx.SpendingDetails = new Features.Wallet.Database.SpendingDetails { BlockHeight = item.SpendingDetails.BlockHeight, IsCoinStake = item.SpendingDetails.IsCoinStake, CreationTime = DateTimeOffset.FromUnixTimeSeconds(long.Parse(item.SpendingDetails.CreationTime)), TransactionId = uint256.Parse(item.SpendingDetails.TransactionId) }; if (item.SpendingDetails.Payments != null) { foreach (PaymentDetails spendingDetailsPayment in item.SpendingDetails.Payments) { trx.SpendingDetails.Payments.Add(new Features.Wallet.Database.PaymentDetails { Amount = new Money(spendingDetailsPayment.Amount), DestinationAddress = spendingDetailsPayment.DestinationAddress, DestinationScriptPubKey = new Script(Encoders.Hex.DecodeData(spendingDetailsPayment.DestinationScriptPubKey)), OutputIndex = spendingDetailsPayment.OutputIndex, PayToSelf = spendingDetailsPayment.PayToSelf }); } } } walletStore.InsertOrUpdate(trx); } }
public async Task ReorgChain_AfterInitialRewind_ChainA_Extension_MinerC_DisconnectsAsync() { using (var builder = NodeBuilder.Create(this)) { var network = new BitcoinRegTest(); var minerA = builder.CreateStratisPowNode(network, "cmi-1-minerA").WithDummyWallet(); var minerB = builder.CreateStratisPowNode(network, "cmi-1-minerB").NoValidation().WithDummyWallet(); var syncer = builder.CreateStratisPowNode(network, "cmi-1-syncer").WithDummyWallet(); bool minerADisconnectedFromSyncer = false; // Configure the interceptor to disconnect a node after a certain block has been disconnected (rewound). void interceptor(ChainedHeaderBlock chainedHeaderBlock) { if (minerADisconnectedFromSyncer) { return; } if (chainedHeaderBlock.ChainedHeader.Previous.Height == 10) { // Ensure that minerA's tip has rewound to 10. TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 10)); TestHelper.Disconnect(minerA, syncer); minerADisconnectedFromSyncer = true; return; } } // Start minerA and mine 10 blocks. We cannot use a premade chain as it adversely affects the max tip age calculation, causing sporadic sync errors. minerA.Start(); TestHelper.MineBlocks(minerA, 10); TestBase.WaitLoop(() => minerA.FullNode.ConsensusManager().Tip.Height == 10); // Start the nodes. minerB.Start(); syncer.Start(); minerA.SetDisconnectInterceptor(interceptor); // minerB and syncer syncs with minerA. TestHelper.ConnectAndSync(minerA, minerB, syncer); // Disconnect minerB from miner so that it can mine on its own and create a fork. TestHelper.Disconnect(minerA, minerB); // MinerA continues to mine to height 14. TestHelper.MineBlocks(minerA, 4); TestBase.WaitLoop(() => minerA.FullNode.ConsensusManager().Tip.Height == 14); TestBase.WaitLoop(() => minerB.FullNode.ConsensusManager().Tip.Height == 10); TestBase.WaitLoop(() => syncer.FullNode.ConsensusManager().Tip.Height == 14); // minerB mines 5 more blocks: // Block 6,7,9,10 = valid // Block 8 = invalid Assert.False(TestHelper.IsNodeConnected(minerB)); await TestHelper.BuildBlocks.OnNode(minerB).Amount(5).Invalid(13, (node, block) => BlockBuilder.InvalidCoinbaseReward(node, block)).BuildAsync(); // Reconnect minerA to minerB. TestHelper.ConnectNoCheck(minerA, minerB); // minerB should be disconnected from minerA. TestBase.WaitLoop(() => !TestHelper.IsNodeConnectedTo(minerA, minerB)); // syncer should be disconnected from minerA (via interceptor). TestBase.WaitLoop(() => !TestHelper.IsNodeConnectedTo(minerA, syncer)); // The reorg will fail at block 8 and roll back any changes. TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 14)); TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 15)); TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 14)); } }