예제 #1
0
        public void CanGetGeneralInfoViaAPI()
        {
            using (NodeBuilder builder = NodeBuilder.Create())
            {
                try
                {
                    CoreNode nodeA = builder.CreateStratisPowNode(false, fullNodeBuilder =>
                    {
                        fullNodeBuilder
                        .UseConsensus()
                        .UseBlockStore()
                        .UseMempool()
                        .AddMining()
                        .UseWallet()
                        .UseApi()
                        .AddRPC();
                    });

                    builder.StartAll();

                    var fullNode = nodeA.FullNode;
                    var ApiURI   = fullNode.Settings.ApiUri;

                    using (client = new HttpClient())
                    {
                        client.DefaultRequestHeaders.Accept.Clear();
                        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                        var response = client.GetStringAsync(ApiURI + "api/wallet/general-info?name=test").GetAwaiter().GetResult();

                        Assert.StartsWith("{\"walletFilePath\":null,\"network\":\"RegTest\",\"creationTime\":\"", response);
                    }
                }
                finally
                {
                    this.Dispose();
                }
            }
        }
예제 #2
0
        public void CanCallRPCMethodViaRPCsCallByNameAPI()
        {
            try
            {
                using (NodeBuilder builder = NodeBuilder.Create())
                {
                    CoreNode nodeA = builder.CreateStratisPowNode(false, fullNodeBuilder =>
                    {
                        fullNodeBuilder
                        .UseConsensus()
                        .UseBlockStore()
                        .UseMempool()
                        .AddMining()
                        .UseWallet()
                        .UseApi()
                        .AddRPC();
                    });

                    builder.StartAll();

                    var fullNode = nodeA.FullNode;
                    var ApiURI   = fullNode.Settings.ApiUri;

                    using (client = new HttpClient())
                    {
                        client.DefaultRequestHeaders.Accept.Clear();
                        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                        var response = client.GetStringAsync(ApiURI + "api/rpc/callbyname?methodName=getblockhash&height=0").GetAwaiter().GetResult();

                        Assert.Equal("\"0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206\"", response);
                    }
                }
            }
            finally
            {
                this.Dispose();
            }
        }
예제 #3
0
        public void CanListRPCMethodsViaRPCsListMethodsAPI()
        {
            try
            {
                using (NodeBuilder builder = NodeBuilder.Create())
                {
                    CoreNode nodeA = builder.CreateStratisPowNode(false, fullNodeBuilder =>
                    {
                        fullNodeBuilder
                        .UseConsensus()
                        .UseBlockStore()
                        .UseMempool()
                        .AddMining()
                        .UseWallet()
                        .UseApi()
                        .AddRPC();
                    });

                    builder.StartAll();

                    var fullNode = nodeA.FullNode;
                    var ApiURI   = fullNode.Settings.ApiUri;

                    using (client = new HttpClient())
                    {
                        client.DefaultRequestHeaders.Accept.Clear();
                        client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));

                        var response = client.GetStringAsync(ApiURI + "api/rpc/listmethods").GetAwaiter().GetResult();

                        Assert.StartsWith("[\"", response);
                    }
                }
            }
            finally
            {
                this.Dispose();
            }
        }
예제 #4
0
        public void GetProofOfWorkRewardForMinedBlocksTest()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode node = builder.CreateStratisPowNode(KnownNetworks.RegTest).NotInIBD();
                builder.StartAll();

                node.SetDummyMinerSecret(new BitcoinSecret(new Key(), node.FullNode.Network));

                TestHelper.MineBlocks(node, 10);
                node.GetProofOfWorkRewardForMinedBlocks(10).Should().Be(Money.Coins(500));

                TestHelper.MineBlocks(node, 90);
                node.GetProofOfWorkRewardForMinedBlocks(100).Should().Be(Money.Coins(5000));

                TestHelper.MineBlocks(node, 100);
                node.GetProofOfWorkRewardForMinedBlocks(200).Should().Be(Money.Coins(8725));

                TestHelper.MineBlocks(node, 200);
                node.GetProofOfWorkRewardForMinedBlocks(400).Should().Be(Money.Coins((decimal)12462.50));
            }
        }
예제 #5
0
        public void MinerCreateBlockSigopsLimit1000()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode miner = builder.CreateStratisPowNode(this.network).WithDummyWallet().Start();

                TestHelper.MineBlocks(miner, 1);

                var txMempoolHelper = new TestMemPoolEntryHelper();

                // Block sigops > limit: 1000 CHECKMULTISIG + 1
                var genesis         = this.network.GetGenesis();
                var genesisCoinbase = genesis.Transactions[0];
                var tx = this.network.CreateTransaction();
                tx.AddInput(new TxIn(new OutPoint(genesisCoinbase.GetHash(), 0), new Script(new byte[] { (byte)OpcodeType.OP_0, (byte)OpcodeType.OP_0, (byte)OpcodeType.OP_0, (byte)OpcodeType.OP_NOP, (byte)OpcodeType.OP_CHECKMULTISIG, (byte)OpcodeType.OP_1 })));

                // NOTE: OP_NOP is used to force 20 SigOps for the CHECKMULTISIG
                tx.AddOutput(Money.Coins(50), new Script());
                for (int i = 0; i < 1001; ++i)
                {
                    tx.Outputs[0].Value -= Money.CENT;
                    bool spendsCoinbase = (i == 0); // only first tx spends coinbase
                                                    // If we don't set the # of sig ops in the CTxMemPoolEntry, template creation fails
                    var txMempoolEntry = txMempoolHelper.Fee(Money.CENT).Time(DateTimeProvider.Default.GetTime()).SpendsCoinbase(spendsCoinbase).FromTx(tx);
                    miner.FullNode.NodeService <ITxMempool>().AddUnchecked(tx.GetHash(), txMempoolEntry);

                    tx = this.network.CreateTransaction(tx.ToBytes());
                    tx.Inputs[0].PrevOut.Hash = tx.GetHash();
                }

                var error = Assert.Throws <ConsensusException>(() => TestHelper.MineBlocks(miner, 1));
                Assert.True(error.Message == ConsensusErrors.BadBlockSigOps.ToString());

                TestBase.WaitLoop(() => TestHelper.IsNodeSynced(miner));

                Assert.True(miner.FullNode.ConsensusManager().Tip.Height == 1);
            }
        }
        public void CanHandleReorgs()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNode = builder.CreateStratisPowNode();
                CoreNode coreNode1   = builder.CreateBitcoinCoreNode();
                CoreNode coreNode2   = builder.CreateBitcoinCoreNode();
                builder.StartAll();

                //Core1 discovers 10 blocks, sends to stratis
                Block tip = coreNode1.FindBlock(10).Last();
                stratisNode.CreateRPCClient().AddNode(coreNode1.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode1.CreateRPCClient().GetBestBlockHash());
                stratisNode.CreateRPCClient().RemoveNode(coreNode1.Endpoint);

                //Core2 discovers 20 blocks, sends to stratis
                tip = coreNode2.FindBlock(20).Last();
                stratisNode.CreateRPCClient().AddNode(coreNode2.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
                stratisNode.CreateRPCClient().RemoveNode(coreNode2.Endpoint);
                ((CachedCoinView)stratisNode.FullNode.CoinView()).FlushAsync().Wait();

                //Core1 discovers 30 blocks, sends to stratis
                tip = coreNode1.FindBlock(30).Last();
                stratisNode.CreateRPCClient().AddNode(coreNode1.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode1.CreateRPCClient().GetBestBlockHash());
                stratisNode.CreateRPCClient().RemoveNode(coreNode1.Endpoint);

                //Core2 discovers 50 blocks, sends to stratis
                tip = coreNode2.FindBlock(50).Last();
                stratisNode.CreateRPCClient().AddNode(coreNode2.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
                stratisNode.CreateRPCClient().RemoveNode(coreNode2.Endpoint);
                ((CachedCoinView)stratisNode.FullNode.CoinView()).FlushAsync().Wait();

                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode2.CreateRPCClient().GetBestBlockHash());
            }
        }
        public void MempoolReceiveFromManyNodes()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var stratisNodeSync = builder.CreateStratisPowNode();
                builder.StartAll();
                stratisNodeSync.NotInIBD();

                stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
                stratisNodeSync.GenerateStratisWithMiner(201); // coinbase maturity = 100
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop().Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.GetBlockStoreTip().HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

                var trxs = new List <Transaction>();
                foreach (var index in Enumerable.Range(1, 100))
                {
                    var block   = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(index).HashBlock).Result;
                    var prevTrx = block.Transactions.First();
                    var dest    = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network);

                    Transaction tx = stratisNodeSync.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                    tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey)));
                    tx.AddOutput(new TxOut("25", dest.PubKey.Hash));
                    tx.AddOutput(new TxOut("24", new Key().PubKey.Hash)); // 1 btc fee
                    tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false);
                    trxs.Add(tx);
                }
                var options = new ParallelOptions {
                    MaxDegreeOfParallelism = 10
                };
                Parallel.ForEach(trxs, options, transaction =>
                {
                    stratisNodeSync.Broadcast(transaction);
                });

                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 100);
            }
        }
예제 #8
0
        public void GetProofOfWorkRewardForMinedBlocksTest()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var node = builder.CreateStratisPowNode();
                builder.StartAll();
                node.NotInIBD();

                node.SetDummyMinerSecret(new BitcoinSecret(new Key(), node.FullNode.Network));

                node.GenerateStratisWithMiner(10);
                node.GetProofOfWorkRewardForMinedBlocks(10).Should().Be(Money.Coins(500));

                node.GenerateStratisWithMiner(90);
                node.GetProofOfWorkRewardForMinedBlocks(100).Should().Be(Money.Coins(5000));

                node.GenerateStratisWithMiner(100);
                node.GetProofOfWorkRewardForMinedBlocks(200).Should().Be(Money.Coins(8725));

                node.GenerateStratisWithMiner(200);
                node.GetProofOfWorkRewardForMinedBlocks(400).Should().Be(Money.Coins((decimal)12462.50));
            }
        }
예제 #9
0
        public void CanGetBlockHeaderFromRPC()
        {
            using (NodeBuilder builder = NodeBuilder.Create())
            {
                CoreNode  node = builder.CreateStratisPowNode();
                RPCClient rpc  = node.CreateRPCClient();
                builder.StartAll();

                uint256     hash           = rpc.GetBlockHash(0);
                BlockHeader expectedHeader = node.FullNode.Chain?.GetBlock(hash)?.Header;
                BlockHeader actualHeader   = rpc.GetBlockHeader(0);

                // Assert block header fields match.
                Assert.Equal(expectedHeader.Version, actualHeader.Version);
                Assert.Equal(expectedHeader.HashPrevBlock, actualHeader.HashPrevBlock);
                Assert.Equal(expectedHeader.HashMerkleRoot, actualHeader.HashMerkleRoot);
                Assert.Equal(expectedHeader.Time, actualHeader.Time);
                Assert.Equal(expectedHeader.Bits, actualHeader.Bits);
                Assert.Equal(expectedHeader.Nonce, actualHeader.Nonce);

                // Assert header hash matches genesis hash.
                Assert.Equal(Network.RegTest.GenesisHash, actualHeader.GetHash());
            }
        }
        public void MiningNodeWithOneConnectionAlwaysSynced()
        {
            string testFolderPath = Path.Combine(this.GetType().Name, nameof(MiningNodeWithOneConnectionAlwaysSynced));

            using (NodeBuilder nodeBuilder = NodeBuilder.Create(testFolderPath))
            {
                CoreNode minerNode = nodeBuilder.CreateStratisPowNode(this.powNetwork).NotInIBD();
                minerNode.Start();
                minerNode.WithWallet();

                CoreNode connectorNode = nodeBuilder.CreateStratisPowNode(this.powNetwork).NotInIBD();
                connectorNode.Start();
                connectorNode.WithWallet();

                CoreNode firstNode = nodeBuilder.CreateStratisPowNode(this.powNetwork).NotInIBD();
                firstNode.Start();
                firstNode.WithWallet();

                CoreNode secondNode = nodeBuilder.CreateStratisPowNode(this.powNetwork);
                secondNode.Start();
                secondNode.WithWallet();

                TestHelper.Connect(minerNode, connectorNode);
                TestHelper.Connect(connectorNode, firstNode);
                TestHelper.Connect(connectorNode, secondNode);
                TestHelper.Connect(firstNode, secondNode);

                List <CoreNode> nodes = new List <CoreNode> {
                    minerNode, connectorNode, firstNode, secondNode
                };

                nodes.ForEach(n =>
                {
                    TestHelper.MineBlocks(n, 1);
                    TestHelper.WaitForNodeToSync(nodes.ToArray());
                });

                int networkHeight = minerNode.FullNode.Chain.Height;
                Assert.Equal(networkHeight, nodes.Count);

                // Random node on network generates a block.
                TestHelper.MineBlocks(firstNode, 1);

                // Wait until connector get the hash of network's block.
                while ((connectorNode.FullNode.ChainBehaviorState.ConsensusTip.HashBlock != firstNode.FullNode.ChainBehaviorState.ConsensusTip.HashBlock) ||
                       (firstNode.FullNode.ChainBehaviorState.ConsensusTip.Height == networkHeight))
                {
                    Thread.Sleep(1);
                }

                Assert.Equal(connectorNode.FullNode.Chain.Tip.HashBlock, firstNode.FullNode.Chain.Tip.HashBlock);
                Assert.Equal(minerNode.FullNode.Chain.Tip.Height, networkHeight);
                Assert.Equal(connectorNode.FullNode.Chain.Tip.Height, networkHeight + 1);

                // Miner mines the block.
                TestHelper.MineBlocks(minerNode, 1);

                networkHeight++;

                Assert.Equal(connectorNode.FullNode.Chain.Tip.HashBlock, firstNode.FullNode.Chain.Tip.HashBlock);
                Assert.Equal(minerNode.FullNode.Chain.Tip.Height, networkHeight);
                Assert.Equal(connectorNode.FullNode.Chain.Tip.Height, networkHeight);

                TestHelper.MineBlocks(connectorNode, 1);
                networkHeight++;

                TestHelper.WaitForNodeToSync(nodes.ToArray());

                nodes.All(n => n.FullNode.Chain.Height == networkHeight).Should()
                .BeTrue(because: "all nodes have synced to chain height");

                Assert.Equal(firstNode.FullNode.Chain.Tip.HashBlock, minerNode.FullNode.Chain.Tip.HashBlock);
            }
        }
        public void MempoolSyncTransactions()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var stratisNodeSync = builder.CreateStratisPowNode();
                var stratisNode1    = builder.CreateStratisPowNode();
                var stratisNode2    = builder.CreateStratisPowNode();
                builder.StartAll();

                stratisNodeSync.NotInIBD();
                stratisNode1.NotInIBD();
                stratisNode2.NotInIBD();

                // generate blocks and wait for the downloader to pickup
                stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
                stratisNodeSync.GenerateStratisWithMiner(105); // coinbase maturity = 100
                // wait for block repo for block sync to work
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisNodeSync));

                // sync both nodes
                stratisNode1.CreateRPCClient().AddNode(stratisNodeSync.Endpoint, true);
                stratisNode2.CreateRPCClient().AddNode(stratisNodeSync.Endpoint, true);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisNode1, stratisNodeSync));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisNode2, stratisNodeSync));

                // create some transactions and push them to the pool
                var trxs = new List <Transaction>();
                foreach (var index in Enumerable.Range(1, 5))
                {
                    var block   = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(index).HashBlock).Result;
                    var prevTrx = block.Transactions.First();
                    var dest    = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network);

                    Transaction tx = stratisNodeSync.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                    tx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey)));
                    tx.AddOutput(new TxOut("25", dest.PubKey.Hash));
                    tx.AddOutput(new TxOut("24", new Key().PubKey.Hash)); // 1 btc fee
                    tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false);
                    trxs.Add(tx);
                }
                var options = new ParallelOptions {
                    MaxDegreeOfParallelism = 5
                };
                Parallel.ForEach(trxs, options, transaction =>
                {
                    stratisNodeSync.Broadcast(transaction);
                });

                // wait for all nodes to have all trx
                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 5);

                // the full node should be connected to both nodes
                Assert.True(stratisNodeSync.FullNode.ConnectionManager.ConnectedPeers.Count() >= 2);

                // reset the trickle timer on the full node that has the transactions in the pool
                foreach (var node in stratisNodeSync.FullNode.ConnectionManager.ConnectedPeers)
                {
                    node.Behavior <MempoolBehavior>().NextInvSend = 0;
                }

                TestHelper.WaitLoop(() => stratisNode1.CreateRPCClient().GetRawMempool().Length == 5);
                TestHelper.WaitLoop(() => stratisNode2.CreateRPCClient().GetRawMempool().Length == 5);

                // mine the transactions in the mempool
                stratisNodeSync.GenerateStratisWithMiner(1);
                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 0);

                // wait for block and mempool to change
                TestHelper.WaitLoop(() => stratisNode1.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
                TestHelper.WaitLoop(() => stratisNode2.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
                TestHelper.WaitLoop(() => stratisNode1.CreateRPCClient().GetRawMempool().Length == 0);
                TestHelper.WaitLoop(() => stratisNode2.CreateRPCClient().GetRawMempool().Length == 0);
            }
        }
        public void TxMempoolMapOrphans()
        {
            var            rand     = new Random();
            var            randByte = new byte[32];
            Func <uint256> randHash = () =>
            {
                rand.NextBytes(randByte);
                return(new uint256(randByte));
            };

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var stratisNode = builder.CreateStratisPowNode();
                builder.StartAll();

                stratisNode.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNode.FullNode.Network));

                // 50 orphan transactions:
                for (ulong i = 0; i < 50; i++)
                {
                    Transaction tx = stratisNode.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                    tx.AddInput(new TxIn(new OutPoint(randHash(), 0), new Script(OpcodeType.OP_1)));
                    tx.AddOutput(new TxOut(new Money(1 * Money.CENT), stratisNode.MinerSecret.ScriptPubKey));

                    stratisNode.FullNode.NodeService <MempoolOrphans>().AddOrphanTx(i, tx);
                }

                Assert.Equal(50, stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count);

                // ... and 50 that depend on other orphans:
                for (ulong i = 0; i < 50; i++)
                {
                    var txPrev = stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().ElementAt(rand.Next(stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count));

                    Transaction tx = stratisNode.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                    tx.AddInput(new TxIn(new OutPoint(txPrev.Tx.GetHash(), 0), new Script(OpcodeType.OP_1)));
                    tx.AddOutput(new TxOut(new Money((1 + i + 100) * Money.CENT), stratisNode.MinerSecret.ScriptPubKey));
                    stratisNode.FullNode.NodeService <MempoolOrphans>().AddOrphanTx(i, tx);
                }

                Assert.Equal(100, stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count);

                // This really-big orphan should be ignored:
                for (ulong i = 0; i < 10; i++)
                {
                    var         txPrev = stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().ElementAt(rand.Next(stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count));
                    Transaction tx     = stratisNode.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                    tx.AddOutput(new TxOut(new Money(1 * Money.CENT), stratisNode.MinerSecret.ScriptPubKey));
                    foreach (var index in Enumerable.Range(0, 2777))
                    {
                        tx.AddInput(new TxIn(new OutPoint(txPrev.Tx.GetHash(), index), new Script(OpcodeType.OP_1)));
                    }

                    Assert.False(stratisNode.FullNode.NodeService <MempoolOrphans>().AddOrphanTx(i, tx));
                }

                Assert.Equal(100, stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count);

                // Test EraseOrphansFor:
                for (ulong i = 0; i < 3; i++)
                {
                    var sizeBefore = stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count;
                    stratisNode.FullNode.NodeService <MempoolOrphans>().EraseOrphansFor(i);
                    Assert.True(stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count < sizeBefore);
                }

                // Test LimitOrphanTxSize() function:
                stratisNode.FullNode.NodeService <MempoolOrphans>().LimitOrphanTxSize(40);
                Assert.True(stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count <= 40);
                stratisNode.FullNode.NodeService <MempoolOrphans>().LimitOrphanTxSize(10);
                Assert.True(stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Count <= 10);
                stratisNode.FullNode.NodeService <MempoolOrphans>().LimitOrphanTxSize(0);
                Assert.True(!stratisNode.FullNode.NodeService <MempoolOrphans>().OrphansList().Any());
            }
        }
        public void TxMempoolBlockDoublespend()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var stratisNodeSync = builder.CreateStratisPowNode();
                builder.StartAll();
                stratisNodeSync.NotInIBD();
                stratisNodeSync.FullNode.Settings.RequireStandard = true; // make sure to test standard tx

                stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
                stratisNodeSync.GenerateStratisWithMiner(100); // coinbase maturity = 100
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop().Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.GetBlockStoreTip().HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);

                // Make sure skipping validation of transctions that were
                // validated going into the memory pool does not allow
                // double-spends in blocks to pass validation when they should not.

                var scriptPubKey = PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey);
                var genBlock     = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(1).HashBlock).Result;

                // Create a double-spend of mature coinbase txn:
                List <Transaction> spends = new List <Transaction>(2);
                foreach (var index in Enumerable.Range(1, 2))
                {
                    var trx = stratisNodeSync.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                    trx.AddInput(new TxIn(new OutPoint(genBlock.Transactions[0].GetHash(), 0), scriptPubKey));
                    trx.AddOutput(Money.Cents(11), new Key().PubKey.Hash);
                    // Sign:
                    trx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false);
                    spends.Add(trx);
                }

                // Test 1: block with both of those transactions should be rejected.
                var block = stratisNodeSync.GenerateStratis(1, spends).Single();
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop().Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
                Assert.True(stratisNodeSync.FullNode.Chain.Tip.HashBlock != block.GetHash());

                // Test 2: ... and should be rejected if spend1 is in the memory pool
                Assert.True(stratisNodeSync.AddToStratisMempool(spends[0]));
                block = stratisNodeSync.GenerateStratis(1, spends).Single();
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop().Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
                Assert.True(stratisNodeSync.FullNode.Chain.Tip.HashBlock != block.GetHash());
                stratisNodeSync.FullNode.MempoolManager().Clear().Wait();

                // Test 3: ... and should be rejected if spend2 is in the memory pool
                Assert.True(stratisNodeSync.AddToStratisMempool(spends[1]));
                block = stratisNodeSync.GenerateStratis(1, spends).Single();
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop().Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
                Assert.True(stratisNodeSync.FullNode.Chain.Tip.HashBlock != block.GetHash());
                stratisNodeSync.FullNode.MempoolManager().Clear().Wait();

                // Final sanity test: first spend in mempool, second in block, that's OK:
                List <Transaction> oneSpend = new List <Transaction>();
                oneSpend.Add(spends[0]);
                Assert.True(stratisNodeSync.AddToStratisMempool(spends[1]));
                block = stratisNodeSync.GenerateStratis(1, oneSpend).Single();
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.ConsensusLoop().Tip.HashBlock == stratisNodeSync.FullNode.Chain.Tip.HashBlock);
                Assert.True(stratisNodeSync.FullNode.Chain.Tip.HashBlock == block.GetHash());

                // spends[1] should have been removed from the mempool when the
                // block with spends[0] is accepted:
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.MempoolManager().MempoolSize().Result == 0);
            }
        }
예제 #14
0
        public void TestSegwit_MinedOnCore_ActivatedOn_StratisNode()
        {
            using (NodeBuilder builder = NodeBuilder.Create(version: "0.15.1"))
            {
                CoreNode coreNode = builder.CreateNode(false);

                coreNode.ConfigParameters.AddOrReplace("debug", "1");
                coreNode.ConfigParameters.AddOrReplace("printtoconsole", "0");
                coreNode.Start();

                CoreNode stratisNode = builder.CreateStratisPowNode(true, fullNodeBuilder =>
                {
                    fullNodeBuilder
                    .UseConsensus()
                    .UseBlockStore()
                    .UseWallet()
                    .UseMempool()
                    .AddMining()
                    .AddRPC();
                });

                RPCClient stratisNodeRpc = stratisNode.CreateRPCClient();
                RPCClient coreRpc        = coreNode.CreateRPCClient();

                coreRpc.AddNode(stratisNode.Endpoint, false);
                stratisNodeRpc.AddNode(coreNode.Endpoint, false);

                // core (in version 0.15.1) only mines segwit blocks above a certain height on regtest
                // future versions of core will change that behaviour so this test may need to be changed in the future
                // see issue for more details https://github.com/stratisproject/StratisBitcoinFullNode/issues/1028
                BIP9DeploymentsParameters prevSegwitDeployment = Network.RegTest.Consensus.BIP9Deployments[BIP9Deployments.Segwit];
                Network.RegTest.Consensus.BIP9Deployments[BIP9Deployments.Segwit] = new BIP9DeploymentsParameters(1, 0, DateTime.Now.AddDays(50).ToUnixTimestamp());

                try
                {
                    // generate 450 blocks, block 431 will be segwit activated.
                    coreRpc.Generate(450);

                    TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode.CreateRPCClient().GetBestBlockHash());

                    // segwit activation on Bitcoin regtest.
                    // - On regtest deployment state changes every 144 block, the threshold for activating a rule is 108 blocks.
                    // segwit deployment status should be:
                    // - Defined up to block 142.
                    // - Started at block 143 to block 286 .
                    // - LockedIn 287 (as segwit should already be signaled in blocks).
                    // - Active at block 431.

                    IConsensusLoop   consensusLoop       = stratisNode.FullNode.NodeService <IConsensusLoop>();
                    ThresholdState[] segwitDefinedState  = consensusLoop.NodeDeployments.BIP9.GetStates(stratisNode.FullNode.Chain.GetBlock(142));
                    ThresholdState[] segwitStartedState  = consensusLoop.NodeDeployments.BIP9.GetStates(stratisNode.FullNode.Chain.GetBlock(143));
                    ThresholdState[] segwitLockedInState = consensusLoop.NodeDeployments.BIP9.GetStates(stratisNode.FullNode.Chain.GetBlock(287));
                    ThresholdState[] segwitActiveState   = consensusLoop.NodeDeployments.BIP9.GetStates(stratisNode.FullNode.Chain.GetBlock(431));

                    // check that segwit is got activated at block 431
                    Assert.Equal(ThresholdState.Defined, segwitDefinedState.GetValue((int)BIP9Deployments.Segwit));
                    Assert.Equal(ThresholdState.Started, segwitStartedState.GetValue((int)BIP9Deployments.Segwit));
                    Assert.Equal(ThresholdState.LockedIn, segwitLockedInState.GetValue((int)BIP9Deployments.Segwit));
                    Assert.Equal(ThresholdState.Active, segwitActiveState.GetValue((int)BIP9Deployments.Segwit));
                }
                finally
                {
                    Network.RegTest.Consensus.BIP9Deployments[BIP9Deployments.Segwit] = prevSegwitDeployment;
                }
            }
        }
예제 #15
0
        public void CanRegisterSingleValueIndexFromIndexStoreSettings()
        {
            using (NodeBuilder builder = NodeBuilder.Create())
            {
                var node = builder.CreateStratisPowNode(false, fullNodeBuilder =>
                {
                    fullNodeBuilder
                    .UseConsensus()
                    .UseIndexStore(settings =>
                    {
                        settings.RegisterIndex("Output", "(t,b,n) => t.Inputs.Select((i, N) => new object[] { new object[] { i.PrevOut.Hash, i.PrevOut.N }, t.GetHash() })", false);
                    })
                    .AddRPC();
                });

                builder.StartAll();

                // Transaction has outputs
                var block           = new Block();
                var trans           = new Transaction();
                Key key             = new Key(); // generate a random private key
                var scriptPubKeyOut = PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(key.PubKey);
                trans.Outputs.Add(new TxOut(100, scriptPubKeyOut));
                block.Transactions.Add(trans);
                var hash = trans.GetHash().ToBytes();

                // Transaction has inputs (i.PrevOut)
                var block2 = new Block();
                block2.Header.HashPrevBlock = block.GetHash();
                var trans2 = new Transaction();
                trans2.Inputs.Add(new TxIn(new OutPoint(trans, 0)));
                block2.Transactions.Add(trans2);
                var hash2 = trans2.GetHash().ToBytes();

                var repository = node.FullNode.NodeService <IIndexRepository>() as IndexRepository;

                repository.PutAsync(block.GetHash(), new List <Block> {
                    block, block2
                }).GetAwaiter().GetResult();

                var indexTable   = repository.Indexes["Output"].Table;
                var expectedJSON = repository.Indexes["Output"].ToString();

                repository.Dispose();

                using (var engine = new DBreezeEngine(node.FullNode.DataFolder.IndexPath))
                {
                    var transaction = engine.GetTransaction();

                    var indexKeyRow = transaction.Select <string, string>("Common", indexTable);
                    Assert.True(indexKeyRow.Exists && indexKeyRow.Value != null);
                    Assert.Equal(expectedJSON, indexKeyRow.Value);

                    // Block 2 has been indexed?
                    var indexKey = new byte[hash.Length + 4];
                    hash.CopyTo(indexKey, 0);
                    var IndexedRow = transaction.Select <byte[], byte[]>(indexTable, indexKey);
                    Assert.True(IndexedRow.Exists);
                    // Correct value indexed?
                    var compare = new byte[32];
                    hash2.CopyTo(compare, 0);
                    Assert.Equal(compare, IndexedRow.Value);
                }
            }
        }
        public void WalletCanReorg()
        {
            // this test has 4 parts:
            // send first transaction from one wallet to another and wait for it to be confirmed
            // send a second transaction and wait for it to be confirmed
            // connected to a longer chain that couse a reorg back so the second trasnaction is undone
            // mine the second transaction back in to the main chain

            using (NodeBuilder builder = NodeBuilder.Create())
            {
                var stratisSender   = builder.CreateStratisPowNode();
                var stratisReceiver = builder.CreateStratisPowNode();
                var stratisReorg    = builder.CreateStratisPowNode();

                builder.StartAll();
                stratisSender.NotInIBD();
                stratisReceiver.NotInIBD();
                stratisReorg.NotInIBD();

                // get a key from the wallet
                var mnemonic1 = stratisSender.FullNode.WalletManager().CreateWallet("123456", "mywallet");
                var mnemonic2 = stratisReceiver.FullNode.WalletManager().CreateWallet("123456", "mywallet");
                Assert.Equal(12, mnemonic1.Words.Length);
                Assert.Equal(12, mnemonic2.Words.Length);
                var addr   = stratisSender.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
                var wallet = stratisSender.FullNode.WalletManager().GetWalletByName("mywallet");
                var key    = wallet.GetExtendedPrivateKeyForAddress("123456", addr).PrivateKey;

                stratisSender.SetDummyMinerSecret(new BitcoinSecret(key, stratisSender.FullNode.Network));
                stratisReorg.SetDummyMinerSecret(new BitcoinSecret(key, stratisSender.FullNode.Network));

                var maturity = (int)stratisSender.FullNode.Network.Consensus.Option <PowConsensusOptions>().CoinbaseMaturity;
                stratisSender.GenerateStratisWithMiner(maturity + 15);

                var currentBestHeight = maturity + 15;

                // wait for block repo for block sync to work
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));

                // the mining should add coins to the wallet
                var total = stratisSender.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                Assert.Equal(Money.COIN * currentBestHeight * 50, total);

                // sync all nodes
                stratisReceiver.CreateRPCClient().AddNode(stratisSender.Endpoint, true);
                stratisReceiver.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                stratisSender.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisReorg));

                // Build Transaction 1
                // ====================
                // send coins to the receiver
                var sendto       = stratisReceiver.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
                var transaction1 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(new WalletAccountReference("mywallet", "account 0"), "123456", sendto.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101));

                // [SENDTRANSACTION TODO] Conceptual changes had been introduced to tx sending
                // These tests don't make sense anymore
                // It must be either removed or refactored
                //// broadcast to the other node
                //stratisSender.FullNode.WalletManager().SendTransaction(transaction1.ToHex());

                //// wait for the trx to arrive
                //TestHelper.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
                //Assert.NotNull(stratisReceiver.CreateRPCClient().GetRawTransaction(transaction1.GetHash(), false));
                //TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any());

                //var receivetotal = stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                //Assert.Equal(Money.COIN * 100, receivetotal);
                //Assert.Null(stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);

                //// generate two new blocks so the trx is confirmed
                //stratisSender.GenerateStratisWithMiner(1);
                //var transaction1MinedHeight = currentBestHeight + 1;
                //stratisSender.GenerateStratisWithMiner(1);
                //currentBestHeight = currentBestHeight + 2;

                //// wait for block repo for block sync to work
                //TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisReorg));
                //Assert.Equal(currentBestHeight, stratisReceiver.FullNode.Chain.Tip.Height);
                //TestHelper.WaitLoop(() => transaction1MinedHeight == stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);

                //// Build Transaction 2
                //// ====================
                //// remove the reorg node
                //stratisReceiver.CreateRPCClient().RemoveNode(stratisReorg.Endpoint);
                //stratisSender.CreateRPCClient().RemoveNode(stratisReorg.Endpoint);
                //var forkblock = stratisReceiver.FullNode.Chain.Tip;

                //// send more coins to the wallet
                //sendto = stratisReceiver.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
                //var transaction2 = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(new WalletAccountReference("mywallet", "account 0"), "123456", sendto.ScriptPubKey, Money.COIN * 10, FeeType.Medium, 101));
                //stratisSender.FullNode.WalletManager().SendTransaction(transaction2.ToHex());
                //// wait for the trx to arrive
                //TestHelper.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
                //Assert.NotNull(stratisReceiver.CreateRPCClient().GetRawTransaction(transaction2.GetHash(), false));
                //TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any());
                //var newamount = stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                //Assert.Equal(Money.COIN * 110, newamount);
                //Assert.True(stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any(b => b.Transaction.BlockHeight == null));

                //// mine more blocks so its included in the chain

                //stratisSender.GenerateStratisWithMiner(1);
                //var transaction2MinedHeight = currentBestHeight + 1;
                //stratisSender.GenerateStratisWithMiner(1);
                //currentBestHeight = currentBestHeight + 2;
                //TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));
                //Assert.Equal(currentBestHeight, stratisReceiver.FullNode.Chain.Tip.Height);
                //TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any(b => b.Transaction.BlockHeight == transaction2MinedHeight));

                //// create a reorg by mining on two different chains
                //// ================================================
                //// advance both chains, one chin is longer
                //stratisSender.GenerateStratisWithMiner(2);
                //stratisReorg.GenerateStratisWithMiner(10);
                //currentBestHeight = forkblock.Height + 10;
                //TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisReorg));

                //// connect the reorg chain
                //stratisReceiver.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                //stratisSender.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                //// wait for the chains to catch up
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisReorg));
                //Assert.Equal(currentBestHeight, stratisReceiver.FullNode.Chain.Tip.Height);

                //// ensure wallet reorg complete
                //TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().WalletTipHash == stratisReorg.CreateRPCClient().GetBestBlockHash());
                //// check the wallet amount was rolled back
                //var newtotal = stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                //Assert.Equal(receivetotal, newtotal);
                //TestHelper.WaitLoop(() => maturity + 16 == stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);

                //// ReBuild Transaction 2
                //// ====================
                //// TODO: Investigate when a reorg happens the store needs to put the rolled back transactions back to the mempool
                //stratisSender.FullNode.WalletManager().SendTransaction(transaction2.ToHex());
                //TestHelper.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);

                //// mine the transaction again
                //stratisSender.GenerateStratisWithMiner(1);
                //transaction2MinedHeight = currentBestHeight + 1;
                //stratisSender.GenerateStratisWithMiner(1);
                //currentBestHeight = currentBestHeight + 2;

                //TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisReorg));
                //Assert.Equal(currentBestHeight, stratisReceiver.FullNode.Chain.Tip.Height);
                //var newsecondamount = stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                //Assert.Equal(newamount, newsecondamount);
                //TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any(b => b.Transaction.BlockHeight == transaction2MinedHeight));
            }
        }
        public void WalletCanReceiveAndSendCorrectly()
        {
            using (NodeBuilder builder = NodeBuilder.Create())
            {
                var stratisSender   = builder.CreateStratisPowNode();
                var stratisReceiver = builder.CreateStratisPowNode();

                builder.StartAll();
                stratisSender.NotInIBD();
                stratisReceiver.NotInIBD();

                // get a key from the wallet
                var mnemonic1 = stratisSender.FullNode.WalletManager().CreateWallet("123456", "mywallet");
                var mnemonic2 = stratisReceiver.FullNode.WalletManager().CreateWallet("123456", "mywallet");
                Assert.Equal(12, mnemonic1.Words.Length);
                Assert.Equal(12, mnemonic2.Words.Length);
                var addr   = stratisSender.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
                var wallet = stratisSender.FullNode.WalletManager().GetWalletByName("mywallet");
                var key    = wallet.GetExtendedPrivateKeyForAddress("123456", addr).PrivateKey;

                stratisSender.SetDummyMinerSecret(new BitcoinSecret(key, stratisSender.FullNode.Network));
                var maturity = (int)stratisSender.FullNode.Network.Consensus.Option <PowConsensusOptions>().CoinbaseMaturity;
                stratisSender.GenerateStratis(maturity + 5);
                // wait for block repo for block sync to work

                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));

                // the mining should add coins to the wallet
                var total = stratisSender.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                Assert.Equal(Money.COIN * 105 * 50, total);

                // sync both nodes
                stratisSender.CreateRPCClient().AddNode(stratisReceiver.Endpoint, true);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));

                // send coins to the receiver
                var sendto = stratisReceiver.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
                var trx    = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(CreateContext(new WalletAccountReference("mywallet", "account 0"), "123456", sendto.ScriptPubKey, Money.COIN * 100, FeeType.Medium, 101));

                // [SENDTRANSACTION TODO] Conceptual changes had been introduced to tx sending
                // These tests don't make sense anymore
                // It must be either removed or refactored
                //// broadcast to the other node
                //stratisSender.FullNode.WalletManager().SendTransaction(trx.ToHex());

                //// wait for the trx to arrive
                //TestHelper.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
                //TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any());

                //var receivetotal = stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount);
                //Assert.Equal(Money.COIN * 100, receivetotal);
                //Assert.Null(stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);

                //// generate two new blocks do the trx is confirmed
                //stratisSender.GenerateStratis(1, new List<Transaction>(new[] {trx.Clone()}));
                //stratisSender.GenerateStratis(1);

                //// wait for block repo for block sync to work
                //TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));
                //TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));

                //TestHelper.WaitLoop(() => maturity + 6 == stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);
            }
        }
예제 #18
0
        public void WalletCanSendOneTransactionWithManyOutputs()
        {
            using (NodeBuilder builder = NodeBuilder.Create())
            {
                CoreNode stratisSender   = builder.CreateStratisPowNode();
                CoreNode stratisReceiver = builder.CreateStratisPowNode();

                builder.StartAll();
                stratisSender.NotInIBD();
                stratisReceiver.NotInIBD();

                stratisSender.FullNode.WalletManager().CreateWallet("123456", "mywallet");
                stratisReceiver.FullNode.WalletManager().CreateWallet("123456", "mywallet");

                HdAddress addr   = stratisSender.FullNode.WalletManager().GetUnusedAddress(new WalletAccountReference("mywallet", "account 0"));
                Wallet    wallet = stratisSender.FullNode.WalletManager().GetWalletByName("mywallet");
                Key       key    = wallet.GetExtendedPrivateKeyForAddress("123456", addr).PrivateKey;

                stratisSender.SetDummyMinerSecret(new BitcoinSecret(key, stratisSender.FullNode.Network));
                int maturity = (int)stratisSender.FullNode.Network.Consensus.Option <PowConsensusOptions>().CoinbaseMaturity;
                stratisSender.GenerateStratisWithMiner(maturity + 51);

                // Wait for block repo for block sync to work.
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));

                Assert.Equal(Money.COIN * 150 * 50, stratisSender.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount));

                // Sync both nodes.
                stratisSender.CreateRPCClient().AddNode(stratisReceiver.Endpoint, true);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));

                // Get 50 unused addresses from the receiver.
                IEnumerable <HdAddress> recevierAddresses = stratisReceiver.FullNode.WalletManager()
                                                            .GetUnusedAddresses(new WalletAccountReference("mywallet", "account 0"), 50);

                List <Recipient> recipients = recevierAddresses.Select(address => new Recipient
                {
                    ScriptPubKey = address.ScriptPubKey,
                    Amount       = Money.COIN
                })
                                              .ToList();

                var transactionBuildContext = new TransactionBuildContext(
                    new WalletAccountReference("mywallet", "account 0"), recipients, "123456")
                {
                    FeeType          = FeeType.Medium,
                    MinConfirmations = 101
                };

                Transaction transaction = stratisSender.FullNode.WalletTransactionHandler().BuildTransaction(transactionBuildContext);
                Assert.Equal(51, transaction.Outputs.Count);

                // Broadcast to the other node.
                stratisSender.FullNode.NodeService <WalletController>().SendTransaction(new SendTransactionRequest(transaction.ToHex()));

                // Wait for the trx's to arrive.
                TestHelper.WaitLoop(() => stratisReceiver.CreateRPCClient().GetRawMempool().Length > 0);
                TestHelper.WaitLoop(() => stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Any());

                Assert.Equal(Money.COIN * 50, stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").Sum(s => s.Transaction.Amount));
                Assert.Null(stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);

                // Generate new blocks so the trx is confirmed.
                stratisSender.GenerateStratisWithMiner(1);

                // Wait for block repo for block sync to work.
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisSender));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReceiver, stratisSender));

                // Confirm trx's have been committed to the block.
                Assert.Equal(maturity + 52, stratisReceiver.FullNode.WalletManager().GetSpendableTransactionsInWallet("mywallet").First().Transaction.BlockHeight);
            }
        }