コード例 #1
0
ファイル: StratisXRPCTests.cs プロジェクト: oumarxy/blockcore
        /// <inheritdoc />
        protected override void InitializeFixture()
        {
            // TODO: Make a ReadyBlockChainData for these tests
            this.Builder = NodeBuilder.Create(this);
            this.Node    = this.Builder.CreateStratisXNode().Start();

            // Add a peer node and connect the nodes together
            var config = new NodeConfigParameters()
            {
                { "addnode", this.Node.Endpoint.ToString() }
            };

            this.Builder.CreateStratisXNode(configParameters: config).Start();

            this.RpcClient = this.Node.CreateRPCClient();

            // Generate 11 blocks
            this.RpcClient.SendCommand(RPCOperations.generate, 11);

            var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token;

            TestBase.WaitLoop(() => this.RpcClient.GetBlockCount() >= 11, cancellationToken: cancellationToken);
            //TestBase.WaitLoop(() => this.RpcClient.GetPeersInfo().Length > 0, cancellationToken: cancellationToken);

            // TODO: Disable staking
        }
コード例 #2
0
        public async Task GetRawTransactionWithTransactionAndBlockHashInBlockchainAndNotIndexedAsync()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var configParameters = new NodeConfigParameters {
                    { "txindex", "0" }
                };

                CoreNode node = builder.CreateStratisCustomPowNode(new BitcoinRegTest(), configParameters).WithWallet().Start();
                TestHelper.MineBlocks(node, 5);

                // Get the last block we have.
                string lastBlockHash = await $"http://localhost:{node.ApiPort}/api"
                                       .AppendPathSegment("consensus/getbestblockhash")
                                       .GetJsonAsync <string>();

                BlockTransactionDetailsModel tip = await $"http://localhost:{node.ApiPort}/api"
                                                   .AppendPathSegment("blockstore/block")
                                                   .SetQueryParams(new { hash = lastBlockHash, outputJson = true, showtransactiondetails = true })
                                                   .GetJsonAsync <BlockTransactionDetailsModel>();

                string txId = tip.Transactions.First().TxId;

                RPCClient    rpc            = node.CreateRPCClient();
                Func <Task>  getTransaction = async() => { await rpc.SendCommandAsync(RPCOperations.getrawtransaction, txId); };
                RPCException exception      = getTransaction.Should().Throw <RPCException>().Which;
                exception.RPCCode.Should().Be(RPCErrorCode.RPC_INVALID_ADDRESS_OR_KEY);
                exception.Message.Should().Be("No such mempool transaction. Use -txindex to enable blockchain transaction queries.");
            }
        }
コード例 #3
0
        public void GatewayNodeCanSyncFirst15KBlocks()
        {
            Network network = new StratisMain10KCheckpoint();

            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // TODO: Add the necessary executables for Linux & OSX
                return;
            }

            using (NodeBuilder builder = NodeBuilder.Create(this).WithLogsEnabled())
            {
                CoreNode stratisXNode = builder.CreateMainnetStratisXNode()
                                        .WithReadyBlockchainData(ReadyBlockchain.StratisXMainnet15K);

                var gatewayParameters = new NodeConfigParameters();
                gatewayParameters.Add("regtest", "0");
                gatewayParameters.Add("gateway", "1");
                gatewayParameters.Add("whitelist", stratisXNode.Endpoint.ToString());
                CoreNode gatewayNode = builder.CreateStratisPosNode(network, configParameters: gatewayParameters, isGateway: true);

                gatewayNode.Start();
                stratisXNode.Start();

                RPCClient stratisXRpc    = stratisXNode.CreateRPCClient();
                RPCClient gatewayNodeRpc = gatewayNode.CreateRPCClient();

                gatewayNodeRpc.AddNode(stratisXNode.Endpoint);

                TestBase.WaitLoop(() => gatewayNode.FullNode.ChainIndexer.Height >= 15_000, waitTimeSeconds: 600);
            }
        }
コード例 #4
0
        public void Transaction_CreatedByXNode_TraversesSBFN_ReachesSecondXNode()
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // TODO: Add the necessary executables for Linux & OSX
                return;
            }

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var network = new StratisRegTest();

                CoreNode xNode1 = builder.CreateStratisXNode(version: "2.0.0.5").Start();

                var callback = new Action <IFullNodeBuilder>(build => build
                                                             .UseBlockStore()
                                                             .UsePosConsensus()
                                                             .UseMempool()
                                                             .UseWallet()
                                                             .AddPowPosMining()
                                                             .AddRPC());

                var config = new NodeConfigParameters();
                config.Add("whitelist", xNode1.Endpoint.ToString());
                config.Add("gateway", "1");

                CoreNode sbfnNode2 = builder
                                     .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config)
                                     .WithWallet().Start();

                CoreNode xNode3 = builder.CreateStratisXNode(version: "2.0.0.5").Start();

                RPCClient xRpc1    = xNode1.CreateRPCClient();
                RPCClient sbfnRpc2 = sbfnNode2.CreateRPCClient();
                RPCClient xRpc3    = xNode3.CreateRPCClient();

                // Connect the nodes linearly. X does not appear to respond properly to the addnode RPC so SBFN needs to initiate.
                sbfnRpc2.AddNode(xNode1.Endpoint, false);
                sbfnRpc2.AddNode(xNode3.Endpoint, false);

                xRpc1.SendCommand(RPCOperations.generate, 11);

                var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token;

                TestBase.WaitLoop(() => xRpc1.GetBlockCount() >= 11, cancellationToken: shortCancellationToken);

                TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == sbfnRpc2.GetBestBlockHash(), cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == xRpc3.GetBestBlockHash(), cancellationToken: shortCancellationToken);

                // Send transaction to arbitrary address.
                var alice        = new Key().GetBitcoinSecret(network);
                var aliceAddress = alice.GetAddress();
                xRpc1.SendCommand(RPCOperations.sendtoaddress, aliceAddress.ToString(), 1);

                TestBase.WaitLoop(() => xRpc1.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => sbfnRpc2.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => xRpc3.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);
            }
        }
コード例 #5
0
 public CustomNodeRunner(string dataDir, Action <IFullNodeBuilder> callback, Network network,
                         ProtocolVersion protocolVersion = ProtocolVersion.PROTOCOL_VERSION, NodeConfigParameters configParameters = null, string agent = "Custom")
     : base(dataDir)
 {
     this.callback         = callback;
     this.Network          = network;
     this.protocolVersion  = protocolVersion;
     this.agent            = agent;
     this.configParameters = configParameters ?? new NodeConfigParameters();
 }
コード例 #6
0
 public CustomNodeRunner(string dataDir, Action <IFullNodeBuilder> callback, Network network,
                         uint protocolVersion, NodeConfigParameters configParameters = null, string agent = "Custom",
                         uint minProtocolVersion = ProtocolVersion.SENDHEADERS_VERSION)
     : base(dataDir, agent)
 {
     this.callback           = callback;
     this.Network            = network;
     this.protocolVersion    = protocolVersion;
     this.configParameters   = configParameters ?? new NodeConfigParameters();
     this.minProtocolVersion = minProtocolVersion;
 }
コード例 #7
0
        private void a_gap_limit_of_21()
        {
            int customUnusedAddressBuffer = 21;
            var configParameters          = new NodeConfigParameters {
                { "walletaddressbuffer", customUnusedAddressBuffer.ToString() }
            };

            this.sendingStratisBitcoinNode   = this.nodeBuilder.CreateStratisPowNode(this.network).WithWallet().Start();
            this.receivingStratisBitcoinNode = this.nodeBuilder.CreateStratisCustomPowNode(this.network, configParameters).WithWallet().Start();

            TestHelper.ConnectAndSync(this.sendingStratisBitcoinNode, this.receivingStratisBitcoinNode);
            this.MineSpendableCoins();
        }
コード例 #8
0
        public void When_Connecting_WithConnectOnly_Connect_ToTheRequestedPeer()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode node1 = builder.CreateStratisPosNode(this.posNetwork, "conn-4-node1").Start();

                var nodeConfig = new NodeConfigParameters
                {
                    { "-connect", node1.Endpoint.ToString() }
                };

                CoreNode node2 = builder.CreateStratisPosNode(this.posNetwork, "conn-4-node2", configParameters: nodeConfig).Start();

                TestBase.WaitLoop(() => TestHelper.IsNodeConnectedTo(node1, node2));
            }
        }
コード例 #9
0
        public async Task Can_BanAndDisconnect_Peer_From_ApiAsync()
        {
            using (var builder = NodeBuilder.Create(this))

            {
                var network = new StratisRegTest();

                var nodeA = builder.CreateStratisPosNode(network, "nc-1-nodeA").Start();

                var nodeBIp        = "127.0.0.2";
                var nodeBIpAddress = IPAddress.Parse(nodeBIp);

                var nodeBConfig = new NodeConfigParameters
                {
                    { "-externalip", nodeBIp }
                };

                var nodeB = builder.CreateStratisPosNode(network, agent: "nc-1-nodeB", configParameters: nodeBConfig).Start();

                var nodeAaddressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                nodeAaddressManager.AddPeer(new IPEndPoint(nodeBIpAddress, nodeB.Endpoint.Port), IPAddress.Loopback);

                TestHelper.Connect(nodeA, nodeB);

                var banPeerModel = new SetBanPeerViewModel()
                {
                    BanDurationSeconds = 100,
                    BanCommand         = "add",
                    PeerAddress        = nodeBIp
                };

                await $"http://localhost:{nodeA.ApiPort}/api".AppendPathSegment("network/setban").PostJsonAsync(banPeerModel);

                TestBase.WaitLoop(() => !TestHelper.IsNodeConnectedTo(nodeA, nodeB));

                var nodeBEndPoint = new IPEndPoint(nodeBIpAddress, nodeB.Endpoint.Port);

                var addressManager = nodeA.FullNode.NodeService <IPeerAddressManager>();
                var peer           = nodeAaddressManager.FindPeer(nodeBEndPoint);

                var peerBanning = nodeA.FullNode.NodeService <IPeerBanning>();
                Assert.True(peerBanning.IsBanned(nodeBEndPoint));
            }
        }
コード例 #10
0
        public void XMinesBlocks_SBFNSyncs()
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // TODO: Add the necessary executables for Linux & OSX
                return;
            }

            using (NodeBuilder builder = NodeBuilder.Create(this).WithLogsEnabled())
            {
                var network = new StratisRegTest();

                CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start();

                var callback = new Action <IFullNodeBuilder>(build => build
                                                             .UseBlockStore()
                                                             .UsePosConsensus()
                                                             .UseMempool()
                                                             .UseWallet()
                                                             .AddPowPosMining()
                                                             .AddRPC());

                var config = new NodeConfigParameters();
                config.Add("whitelist", stratisXNode.Endpoint.ToString());
                config.Add("gateway", "1");

                CoreNode stratisNode = builder
                                       .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config)
                                       .WithWallet().Start();

                RPCClient stratisXRpc    = stratisXNode.CreateRPCClient();
                RPCClient stratisNodeRpc = stratisNode.CreateRPCClient();

                stratisNodeRpc.AddNode(stratisXNode.Endpoint, false);

                stratisXRpc.SendCommand(RPCOperations.generate, 10);

                var cancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token;

                TestBase.WaitLoop(() => stratisXRpc.GetBlockCount() >= 10, cancellationToken: cancellationToken);
                TestBase.WaitLoop(() => stratisXRpc.GetBestBlockHash() == stratisNodeRpc.GetBestBlockHash(), cancellationToken: cancellationToken);
            }
        }
コード例 #11
0
        public void PremineNodeWithWalletWithOverrides()
        {
            var configParameters = new NodeConfigParameters {
                { "savetrxhex", "true" }
            };

            var callback = new Action <IFullNodeBuilder>(builder => builder
                                                         .UseBlockStore()
                                                         .UsePosConsensus()
                                                         .UseMempool()
                                                         .UseWallet()
                                                         .AddPowPosMining()
                                                         .AddRPC()
                                                         .MockIBD()
                                                         .UseTestChainedHeaderTree()
                                                         .OverrideDateTimeProviderFor <MiningFeature>());

            this.PremineNodeWithCoins = this.nodeBuilder.CreateCustomNode(callback, new StratisRegTest(), ProtocolVersion.PROTOCOL_VERSION, agent: "mint-pmnode", configParameters: configParameters);
            this.PremineNodeWithCoins.WithWallet().Start();
        }
コード例 #12
0
        private void a_gap_limit_of_21()
        {
            int customUnusedAddressBuffer = 21;
            var configParameters          =
                new NodeConfigParameters {
                { "walletaddressbuffer", customUnusedAddressBuffer.ToString() }
            };

            this.nodeGroup = this.nodeGroupBuilder
                             .StratisPowNode(SendingNodeName).Start().NotInIBD()
                             .WithWallet(SendingWalletName, WalletPassword)
                             .StratisCustomPowNode(ReceivingNodeName, configParameters).Start()
                             .WithWallet(ReceivingWalletName, WalletPassword)
                             .WithConnections()
                             .Connect(SendingNodeName, ReceivingNodeName)
                             .AndNoMoreConnections()
                             .Build();

            MineSpendableCoins();
        }
コード例 #13
0
        public void Ensure_Node_DoesNot_ReconnectTo_SameNode()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var nodeConfig = new NodeConfigParameters
                {
                    { "-debug", "1" }
                };

                CoreNode nodeA = builder.CreateStratisPowNode(this.powNetwork, "conn-1-nodeA", configParameters: nodeConfig).Start();
                CoreNode nodeB = builder.CreateStratisPowNode(this.powNetwork, "conn-1-nodeB", configParameters: nodeConfig).Start();

                TestHelper.Connect(nodeA, nodeB);
                TestHelper.ConnectNoCheck(nodeA, nodeB);

                TestBase.WaitLoop(() => nodeA.FullNode.ConnectionManager.ConnectedPeers.Count() == 1);
                TestBase.WaitLoop(() => nodeB.FullNode.ConnectionManager.ConnectedPeers.Count() == 1);

                Assert.False(nodeA.FullNode.ConnectionManager.ConnectedPeers.First().Inbound);
                Assert.True(nodeB.FullNode.ConnectionManager.ConnectedPeers.First().Inbound);
            }
        }
コード例 #14
0
        public void NodeServer_Enabled_When_ConnectNode_Args_Specified_And_Listen_Specified()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var nodeConfig = new NodeConfigParameters
                {
                    { "-connect", "0" },
                    { "-listen", "1" }
                };

                CoreNode node1 = builder.CreateStratisPowNode(this.powNetwork, "conn-9-node1", configParameters: nodeConfig).Start();
                CoreNode node2 = builder.CreateStratisPowNode(this.powNetwork, "conn-9-node2").Start();

                Assert.True(node1.FullNode.ConnectionManager.Servers.Any());

                TestHelper.Connect(node1, node2);

                Assert.True(TestHelper.IsNodeConnectedTo(node2, node1));

                TestHelper.DisconnectAll(node1, node2);
            }
        }
コード例 #15
0
        private void a_gap_limit_of_21()
        {
            int customUnusedAddressBuffer = 21;
            var configParameters          = new NodeConfigParameters {
                { "walletaddressbuffer", customUnusedAddressBuffer.ToString() }
            };

            this.sendingStratisBitcoinNode = this.nodeBuilder.CreateStratisPowNode(this.network);
            this.sendingStratisBitcoinNode.Start();
            this.sendingStratisBitcoinNode.NotInIBD();
            Mnemonic sendingMnemonic = this.sendingStratisBitcoinNode.FullNode.WalletManager().CreateWallet(WalletPassword, SendingWalletName, WalletPassphrase);

            this.sendingStratisBitcoinNode.Mnemonic = sendingMnemonic;

            this.receivingStratisBitcoinNode = this.nodeBuilder.CreateStratisCustomPowNode(this.network, configParameters);
            this.receivingStratisBitcoinNode.Start();
            this.receivingStratisBitcoinNode.NotInIBD();
            Mnemonic receivingMnemonic = this.receivingStratisBitcoinNode.FullNode.WalletManager().CreateWallet(WalletPassword, ReceivingWalletName, WalletPassphrase);

            this.receivingStratisBitcoinNode.Mnemonic = receivingMnemonic;

            TestHelper.ConnectAndSync(this.sendingStratisBitcoinNode, this.receivingStratisBitcoinNode);
            this.MineSpendableCoins();
        }
コード例 #16
0
 public NodeGroupBuilder StratisCustomPowNode(string nodeName, NodeConfigParameters configParameters)
 {
     this.nodes.Add(nodeName, this.nodeBuilder.CreateStratisCustomPowNode(configParameters));
     return(this);
 }
コード例 #17
0
        public void Transaction_TraversesNodes_AndIsMined_AndNodesSync()
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // TODO: Add the necessary executables for Linux & OSX
                return;
            }

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var network = new StratisRegTest();

                CoreNode xNode1 = builder.CreateStratisXNode(version: "2.0.0.5").Start();

                var callback = new Action <IFullNodeBuilder>(build => build
                                                             .UseBlockStore()
                                                             .UsePosConsensus()
                                                             .UseMempool()
                                                             .UseWallet()
                                                             .AddPowPosMining()
                                                             .AddRPC());

                var config = new NodeConfigParameters();
                config.Add("whitelist", xNode1.Endpoint.ToString());
                config.Add("gateway", "1");

                CoreNode sbfnNode2 = builder
                                     .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config)
                                     .WithWallet().Start();

                CoreNode xNode3 = builder.CreateStratisXNode(version: "2.0.0.5").Start();

                RPCClient xRpc1    = xNode1.CreateRPCClient();
                RPCClient sbfnRpc2 = sbfnNode2.CreateRPCClient();
                RPCClient xRpc3    = xNode3.CreateRPCClient();

                sbfnRpc2.AddNode(xNode1.Endpoint, false);
                sbfnRpc2.AddNode(xNode3.Endpoint, false);

                xRpc1.SendCommand(RPCOperations.generate, 11);

                var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(1)).Token;

                TestBase.WaitLoop(() => xRpc1.GetBlockCount() >= 11, cancellationToken: shortCancellationToken);

                TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == sbfnRpc2.GetBestBlockHash(), cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => xRpc1.GetBestBlockHash() == xRpc3.GetBestBlockHash(), cancellationToken: shortCancellationToken);

                // Send transaction to arbitrary address.
                var alice        = new Key().GetBitcoinSecret(network);
                var aliceAddress = alice.GetAddress();
                xRpc1.SendCommand(RPCOperations.sendtoaddress, aliceAddress.ToString(), 1);

                TestBase.WaitLoop(() => xRpc1.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => sbfnRpc2.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => xRpc3.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);

                // TODO: Until #2468 is fixed we need an X node to mine the block so it doesn't get rejected.
                xRpc1.SendCommand(RPCOperations.generate, 1);
                TestBase.WaitLoop(() => xRpc1.GetBlockCount() >= 12, cancellationToken: shortCancellationToken);

                // We expect that SBFN and the other X node will sync correctly.
                TestBase.WaitLoop(() => sbfnRpc2.GetBestBlockHash() == xRpc1.GetBestBlockHash(), cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => xRpc3.GetBestBlockHash() == xRpc1.GetBestBlockHash(), cancellationToken: shortCancellationToken);

                // Sanity check - mempools should all become empty.
                TestBase.WaitLoop(() => xRpc1.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => sbfnRpc2.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => xRpc3.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken);
            }
        }
コード例 #18
0
        public void XMinesTransaction_SBFNSyncs()
        {
            if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
            {
                // TODO: Add the necessary executables for Linux & OSX
                return;
            }

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var network = new StratisRegTest();

                CoreNode stratisXNode = builder.CreateStratisXNode(version: "2.0.0.5").Start();

                var callback = new Action <IFullNodeBuilder>(build => build
                                                             .UseBlockStore()
                                                             .UsePosConsensus()
                                                             .UseMempool()
                                                             .UseWallet()
                                                             .AddPowPosMining()
                                                             .AddRPC());

                var config = new NodeConfigParameters();
                config.Add("whitelist", stratisXNode.Endpoint.ToString());
                config.Add("gateway", "1");

                CoreNode stratisNode = builder
                                       .CreateCustomNode(callback, network, protocolVersion: ProtocolVersion.PROVEN_HEADER_VERSION, minProtocolVersion: ProtocolVersion.POS_PROTOCOL_VERSION, configParameters: config)
                                       .WithWallet().Start();

                RPCClient stratisXRpc    = stratisXNode.CreateRPCClient();
                RPCClient stratisNodeRpc = stratisNode.CreateRPCClient();

                stratisXRpc.AddNode(stratisNode.Endpoint, false);
                stratisNodeRpc.AddNode(stratisXNode.Endpoint, false);

                stratisXRpc.SendCommand(RPCOperations.generate, 11);

                var shortCancellationToken = new CancellationTokenSource(TimeSpan.FromMinutes(2)).Token;

                // Without this there seems to be a race condition between the blocks all getting generated and SBFN syncing high enough to fall through the getbestblockhash check.
                TestBase.WaitLoop(() => stratisXRpc.GetBlockCount() >= 11, cancellationToken: shortCancellationToken);

                TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: shortCancellationToken);

                // Send transaction to arbitrary address from X side.
                var alice        = new Key().GetBitcoinSecret(network);
                var aliceAddress = alice.GetAddress();
                stratisXRpc.SendCommand(RPCOperations.sendtoaddress, aliceAddress.ToString(), 1);

                TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);

                // Transaction should percolate through to SBFN's mempool.
                TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 1, cancellationToken: shortCancellationToken);

                // Now X must mine the block.
                stratisXRpc.SendCommand(RPCOperations.generate, 1);
                TestBase.WaitLoop(() => stratisXRpc.GetBlockCount() >= 12, cancellationToken: shortCancellationToken);

                // We expect that SBFN will sync correctly.
                TestBase.WaitLoop(() => stratisNodeRpc.GetBestBlockHash() == stratisXRpc.GetBestBlockHash(), cancellationToken: shortCancellationToken);

                // Sanity check - mempools should both become empty.
                TestBase.WaitLoop(() => stratisNodeRpc.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken);
                TestBase.WaitLoop(() => stratisXRpc.GetRawMempool().Length == 0, cancellationToken: shortCancellationToken);
            }
        }
コード例 #19
0
        public CoreNode CreateNode(NodeBuilder nodeBuilder, string agent, ProtocolVersion version = ProtocolVersion.ALT_PROTOCOL_VERSION, NodeConfigParameters configParameters = null)
        {
            var callback = new Action <IFullNodeBuilder>(builder => builder
                                                         .UseBlockStore()
                                                         .UsePosConsensus()
                                                         .UseMempool()
                                                         .AddRPC()
                                                         .UseNodeHost()
                                                         .UseTestChainedHeaderTree()
                                                         .MockIBD()
                                                         );

            return(nodeBuilder.CreateCustomNode(callback, new StratisOverrideRegTest(), ProtocolVersion.PROVEN_HEADER_VERSION, agent: agent, configParameters: configParameters));
        }
コード例 #20
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));
            }
        }
        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));

                // Connect syncer to miner A
                //TestHelper.Connect(syncer, minerA);

                // 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 IndexAddresses_All_Nodes_Synced_Reorg_With_UTXOs()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var network = new BitcoinRegTestOverrideCoinbaseMaturity(5);

                var nodeConfig = new NodeConfigParameters
                {
                    { "-addressindex", "1" }
                };

                var minerA = builder.CreateStratisPowNode(network, "ai-3-minerA", configParameters: nodeConfig).WithWallet().Start();
                var minerB = builder.CreateStratisPowNode(network, "ai-3-minerB", configParameters: nodeConfig).WithWallet().Start();
                var syncer = builder.CreateStratisPowNode(network, "ai-3-syncer", configParameters: nodeConfig).WithWallet().Start();

                // minerA mines to height 10
                // MinerA = 10
                // MinerB = 10
                // Syncer = 10
                TestHelper.MineBlocks(minerA, 10);

                // Sync the network to height 10.
                TestHelper.ConnectAndSync(syncer, minerA);
                TestHelper.ConnectAndSync(syncer, minerB);

                // Disconnect syncer from miner A
                TestHelper.Disconnect(syncer, minerA);
                TestHelper.Disconnect(syncer, minerB);

                // minerB mines to height 10
                // MinerA = 10
                // MinerB = 20
                // Syncer = 10
                TestHelper.MineBlocks(minerB, 10);
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 10));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 20));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 10));

                // Miner A mines on its own chain.
                // MinerA = 25
                // MinerB = 20
                // Syncer = 10
                TestHelper.MineBlocks(minerA, 15);
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 25));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 20));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 10));

                // Reconnect syncer to minerA.
                TestHelper.Connect(syncer, minerA);
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 25));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 20));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 25));

                // Spend some coins on minerA by sending 10 STRAT to syncer.
                TestHelper.SendCoins(minerA, syncer, Money.Coins(10));

                // Miner A mines the transaction and advances onto 35.
                // MinerA = 40
                // MinerB = 20
                // Syncer = 20
                TestHelper.MineBlocks(minerA, 15);
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerA, 40));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(minerB, 20));
                TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(syncer, 40));

                // minerB mines to height 50
                // MinerA = 40
                // MinerB = 50
                // Syncer = 40
                TestHelper.MineBlocks(minerB, 40);

                // Reconnect minerB (the longer chain), this will trigger the reorg.
                TestHelper.Connect(syncer, minerB);

                Assert.True(TestHelper.IsNodeSyncedAtHeight(syncer, 60));
                Assert.True(TestHelper.IsNodeSyncedAtHeight(minerA, 60));
                Assert.True(TestHelper.IsNodeSyncedAtHeight(minerB, 60));

                TestBase.WaitLoop(() => minerA.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 60);
                TestBase.WaitLoop(() => minerB.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 60);
                TestBase.WaitLoop(() => syncer.FullNode.NodeService <IAddressIndexer>().IndexerTip.Height == 60);

                // The transaction got reverted.
                TestHelper.CheckWalletBalance(syncer, 0);
            }
        }
コード例 #23
0
        public void Staking_Wallet_Can_Mint_New_Coins()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var configParameters = new NodeConfigParameters {
                    { "txindex", "1" }
                };
                var network = new StraxRegTest();

                var minerA = builder.CreateStratisPosNode(network, "stake-1-minerA", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start();

                var addressUsed = TestHelper.MineBlocks(minerA, (int)network.Consensus.PremineHeight).AddressUsed;

                //Since the pre - mine will not be immediately spendable, the transactions have to be counted directly from the address.
                addressUsed.Transactions.Count().Should().Be((int)network.Consensus.PremineHeight);

                addressUsed.Transactions.Sum(s => s.Amount).Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward);

                // Mine blocks to maturity
                TestHelper.MineBlocks(minerA, (int)network.Consensus.CoinbaseMaturity + 10);

                // Get set of transaction IDs present in wallet before staking is started.
                this.transactionsBeforeStaking.Clear();
                foreach (TransactionData transactionData in this.GetTransactionsSnapshot(minerA))
                {
                    this.transactionsBeforeStaking.Add(transactionData.Id);
                }

                // Start staking on the node.
                var minter = minerA.FullNode.NodeService <IPosMinting>();
                minter.Stake(new WalletSecret()
                {
                    WalletName = "mywallet", WalletPassword = "******"
                });

                // If new transactions are appearing in the wallet, staking has been successful. Due to coin maturity settings the
                // spendable balance of the wallet actually drops after staking, so the wallet balance should not be used to
                // determine whether staking occurred.
                TestBase.WaitLoop(() =>
                {
                    List <TransactionData> transactions = this.GetTransactionsSnapshot(minerA);

                    foreach (TransactionData transactionData in transactions)
                    {
                        if (!this.transactionsBeforeStaking.Contains(transactionData.Id) && (transactionData.IsCoinStake ?? false))
                        {
                            return(true);
                        }
                    }

                    return(false);
                });

                // build a dictionary of coinstake tx's indexed by tx id.
                foreach (var tx in this.GetTransactionsSnapshot(minerA))
                {
                    this.transactionLookup[tx.Id] = tx;
                }

                TestBase.WaitLoop(() =>
                {
                    List <TransactionData> transactions = this.GetTransactionsSnapshot(minerA);

                    foreach (TransactionData transactionData in transactions)
                    {
                        if (!this.transactionsBeforeStaking.Contains(transactionData.Id) && (transactionData.IsCoinStake ?? false))
                        {
                            Transaction coinstakeTransaction = minerA.FullNode.BlockStore().GetTransactionById(transactionData.Id);
                            var balance = new Money(0);

                            // Add coinstake outputs to balance.
                            foreach (TxOut output in coinstakeTransaction.Outputs)
                            {
                                balance += output.Value;
                            }

                            //Subtract coinstake inputs from balance.
                            foreach (TxIn input in coinstakeTransaction.Inputs)
                            {
                                this.transactionLookup.TryGetValue(input.PrevOut.Hash, out TransactionData prevTransactionData);

                                if (prevTransactionData == null)
                                {
                                    continue;
                                }

                                Transaction prevTransaction = minerA.FullNode.BlockStore().GetTransactionById(prevTransactionData.Id);

                                balance -= prevTransaction.Outputs[input.PrevOut.N].Value;
                            }

                            Assert.Equal(minerA.FullNode.Network.Consensus.ProofOfStakeReward, balance);

                            return(true);
                        }
                    }

                    return(false);
                });
            }
        }
コード例 #24
0
        public async Task WalletCanReturnStakingHistoryCorrectlyAsync()
        {
            using var builder = NodeBuilder.Create(this);

            var configParameters = new NodeConfigParameters {
                { "txindex", "1" }
            };
            var network = new StraxRegTestAdjusedCoinbaseMaturity();

            // Start 2 nodes
            CoreNode miner  = builder.CreateStratisPosNode(network, "history-1-nodeA", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start();
            CoreNode syncer = builder.CreateStratisPosNode(network, "history-1-nodeB", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start();

            TestHelper.ConnectAndSync(miner, syncer);

            // Get mining address
            IEnumerable <string> miningAddresses = await $"http://localhost:{miner.ApiPort}/api"
                                                   .AppendPathSegment("wallet/unusedAddresses")
                                                   .SetQueryParams(new { walletName = "mywallet", accountName = "account 0", count = 1 })
                                                   .GetJsonAsync <IEnumerable <string> >();

            // Assert empty history call result.
            var noHistoryCall = $"http://localhost:{miner.ApiPort}/api"
                                .AppendPathSegment("wallet/history")
                                .SetQueryParams(new WalletHistoryRequest {
                WalletName = "mywallet", AccountName = "account 0"
            })
                                .GetAsync()
                                .ReceiveJson <WalletHistoryModel>().GetAwaiter().GetResult();

            Assert.Empty(noHistoryCall.AccountsHistoryModel.First().TransactionsHistory);

            // Mine some blocks to receive the premine and mature the chain.
            TestHelper.MineBlocks(miner, 20, miningAddress: miningAddresses.First());

            // Start staking on the node.
            IPosMinting minter = miner.FullNode.NodeService <IPosMinting>();

            minter.Stake(new List <WalletSecret>()
            {
                new WalletSecret()
                {
                    WalletName = "mywallet", WalletPassword = "******"
                }
            });

            // Stake to block height 30
            TestBase.WaitLoop(() => TestHelper.IsNodeSyncedAtHeight(miner, 30, 120), waitTimeSeconds: 120);

            // Stop staking.
            minter.StopStake();

            // Ensure nodes are synced.
            TestBase.WaitLoop(() => TestHelper.AreNodesSynced(miner, syncer));

            // Assert ordering
            var history = await CallHistoryAsync(miner);

            // Staking items should appear first in the result.
            var stakingTxs = history.Where(t => t.Type == TransactionItemType.Staked);

            Assert.NotEmpty(stakingTxs);
            var index = 0;

            do
            {
                var item = history[index];
                if (item.Type == TransactionItemType.Mined)
                {
                    break;
                }

                Assert.Equal(Money.Coins(9), item.Amount);
                Assert.Equal(TransactionItemType.Staked, item.Type);

                index += 1;
            } while (true);

            // Then the rest are mining txs
            for (int mIndex = index; mIndex < index + 20; mIndex++)
            {
                var item = history[mIndex];
                if ((miner.FullNode.ChainIndexer.Tip.Height - 2) == mIndex)
                {
                    Assert.Equal(Money.Coins(130_000_000), item.Amount); //premine
                }
                else
                {
                    Assert.Equal(Money.Coins(18), item.Amount);
                }

                Assert.Equal(miningAddresses.First(), item.ToAddress);
                Assert.Equal(TransactionItemType.Mined, item.Type);
            }

            // Assert Pagination and ordering
            var paging = $"http://localhost:{miner.ApiPort}/api"
                         .AppendPathSegment("wallet/history")
                         .SetQueryParams(new WalletHistoryRequest {
                WalletName = "mywallet", AccountName = "account 0", Skip = 0, Take = 10
            })
                         .GetAsync()
                         .ReceiveJson <WalletHistoryModel>().GetAwaiter().GetResult();

            Assert.Equal(10, paging.AccountsHistoryModel.First().TransactionsHistory.Count());
        }
コード例 #25
0
        public void Staking_Wont_Include_Time_Ahead_Of_Coinstake_Timestamp()
        {
            using (var builder = NodeBuilder.Create(this))
            {
                var configParameters = new NodeConfigParameters {
                    { "savetrxhex", "true" }
                };
                var network = new StratisRegTest();

                var minerA = builder.CreateStratisPosNode(network, "stake-1-minerA", configParameters: configParameters).OverrideDateTimeProvider().WithWallet().Start();

                var addressUsed = TestHelper.MineBlocks(minerA, (int)network.Consensus.PremineHeight).AddressUsed;
                var wallet      = minerA.FullNode.WalletManager().Wallets.Single(w => w.Name == "mywallet");
                var allTrx      = wallet.walletStore.GetForAddress(addressUsed.Address);

                // Since the pre-mine will not be immediately spendable, the transactions have to be counted directly from the address.
                allTrx.Count().Should().Be((int)network.Consensus.PremineHeight);

                allTrx.Sum(s => s.Amount).Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward);
                var balance = minerA.FullNode.WalletManager().GetAddressBalance(addressUsed.Address);
                balance.AmountConfirmed.Should().Be(network.Consensus.PremineReward + network.Consensus.ProofOfWorkReward);

                // Mine blocks to maturity.
                TestHelper.MineBlocks(minerA, (int)network.Consensus.CoinbaseMaturity + 1);

                // Create a transaction and set its timestamp to one that will be rejected from the block.
                Transaction tx = minerA.FullNode.WalletTransactionHandler().BuildTransaction(new TransactionBuildContext(network)
                {
                    Recipients = new List <Recipient>()
                    {
                        new Recipient
                        {
                            ScriptPubKey = addressUsed.ScriptPubKey,
                            Amount       = Money.Coins(1m)
                        }
                    },
                    AccountReference = new WalletAccountReference(minerA.WalletName, "account 0"),
                    WalletPassword   = minerA.WalletPassword,
                    Time             = (uint)minerA.FullNode.DateTimeProvider.GetAdjustedTimeAsUnixTimestamp()
                });
                minerA.AddToStratisMempool(tx);

                TestBase.WaitLoop(() => minerA.FullNode.MempoolManager().InfoAll().Count == 1);

                // Get our height right now.
                int currentHeight = minerA.FullNode.ChainIndexer.Height;

                // Start staking on the node.
                var minter = minerA.FullNode.NodeService <IPosMinting>();
                minter.Stake(new WalletSecret()
                {
                    WalletName = minerA.WalletName, WalletPassword = minerA.WalletPassword
                });

                // Ensure we've staked a block.
                TestBase.WaitLoop(() => minerA.FullNode.ChainIndexer.Height > currentHeight);

                // Get the staked block.
                ChainedHeader header = minerA.FullNode.ChainIndexer.GetHeader(currentHeight + 1);
                Block         block  = minerA.FullNode.BlockStore().GetBlock(header.HashBlock);

                // The transaction should not be in it.
                Assert.DoesNotContain(block.Transactions, x => x.GetHash() == tx.GetHash());
            }
        }