Esempio n. 1
0
        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);
            }
        }
Esempio n. 5
0
        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));
            }
        }
Esempio n. 9
0
        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));
            }
        }
Esempio n. 13
0
 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();
     }
 }
Esempio n. 14
0
        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);
            }
        }
Esempio n. 16
0
        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.
            }
        }
Esempio n. 17
0
        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();
            }
        }
Esempio n. 18
0
        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);
            }
        }
Esempio n. 19
0
        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);
            }
        }
Esempio n. 20
0
        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);
            }
        }
Esempio n. 21
0
        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));
            }
        }
Esempio n. 22
0
 public ProofOfWorkMiningTests()
 {
     this.regTest = new BitcoinRegTest();
 }
Esempio n. 23
0
        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));
            }
        }
Esempio n. 24
0
        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));
            }
        }
Esempio n. 25
0
        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);
            }
        }
Esempio n. 26
0
        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));
            }
        }