예제 #1
0
        public void MinerCreateBlockCoinbaseMempoolTemplateCreationFails()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode miner = builder.CreateStratisPowNode(this.network);

                builder.StartAll();
                miner.NotInIBD();
                miner.SetDummyMinerSecret(new BitcoinSecret(new Key(), miner.FullNode.Network));
                miner.GenerateStratisWithMiner(1);

                // Create an invalid coinbase transaction to be added to the mempool.
                var duplicateCoinbase = this.network.CreateTransaction();
                duplicateCoinbase.AddInput(new TxIn());
                duplicateCoinbase.AddOutput(new TxOut());
                duplicateCoinbase.Inputs[0].PrevOut   = new OutPoint();
                duplicateCoinbase.Inputs[0].ScriptSig = new Script(OpcodeType.OP_0, OpcodeType.OP_1);
                duplicateCoinbase.Outputs[0].Value    = 0;

                var txMempoolHelper = new TestMemPoolEntryHelper();
                var txMempoolEntry  = txMempoolHelper.Fee(Money.CENT).Time(DateTimeProvider.Default.GetTime()).SpendsCoinbase(false).FromTx(duplicateCoinbase);
                miner.FullNode.NodeService <ITxMempool>().AddUnchecked(duplicateCoinbase.GetHash(), txMempoolEntry);

                var error = Assert.Throws <ConsensusException>(() => miner.GenerateStratisWithMiner(1));
                Assert.True(error.Message == ConsensusErrors.BadMultipleCoinbase.Message);

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

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

                stratisNode.NotInIBD();

                Block     tip = coreNode.FindBlock(10).Last();
                RPCClient stratisNodeRpcClient = stratisNode.CreateRPCClient();
                stratisNodeRpcClient.AddNode(coreNode.Endpoint, true);
                RPCClient coreNodeRpcClient = coreNode.CreateRPCClient();
                TestHelper.WaitLoop(() => stratisNodeRpcClient.GetBestBlockHash() == coreNodeRpcClient.GetBestBlockHash());
                uint256 bestBlockHash = stratisNodeRpcClient.GetBestBlockHash();
                Assert.Equal(tip.GetHash(), bestBlockHash);

                stratisNodeRpcClient.RemoveNode(coreNode.Endpoint);
                TestHelper.WaitLoop(() => coreNodeRpcClient.GetPeersInfo()
                                    .All(pi => pi.Address.MapToIpv6().ToString() != coreNode.Endpoint.MapToIpv6().ToString()));

                tip = coreNode.FindBlock(10).Last();
                coreNodeRpcClient.AddNode(stratisNode.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNodeRpcClient.GetBestBlockHash() == coreNodeRpcClient.GetBestBlockHash());
                bestBlockHash = stratisNodeRpcClient.GetBestBlockHash();
                Assert.Equal(tip.GetHash(), bestBlockHash);
            }
        }
        public void CanStratisSyncFromStratis()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNode     = builder.CreateStratisPowNode();
                CoreNode stratisNodeSync = builder.CreateStratisPowNode();
                CoreNode coreCreateNode  = builder.CreateBitcoinCoreNode();
                builder.StartAll();

                stratisNode.NotInIBD();
                stratisNodeSync.NotInIBD();

                // first seed a core node with blocks and sync them to a stratis node
                // and wait till the stratis node is fully synced
                Block tip = coreCreateNode.FindBlock(5).Last();
                stratisNode.CreateRPCClient().AddNode(coreCreateNode.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreCreateNode.CreateRPCClient().GetBestBlockHash());
                uint256 bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
                Assert.Equal(tip.GetHash(), bestBlockHash);

                // add a new stratis node which will download
                // the blocks using the GetData payload
                stratisNodeSync.CreateRPCClient().AddNode(stratisNode.Endpoint, true);

                // wait for download and assert
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == stratisNodeSync.CreateRPCClient().GetBestBlockHash());
                bestBlockHash = stratisNodeSync.CreateRPCClient().GetBestBlockHash();
                Assert.Equal(tip.GetHash(), bestBlockHash);
            }
        }
예제 #4
0
        public void CanStratisSyncFromCore()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNode = builder.CreateStratisPowNode();
                CoreNode coreNode    = builder.CreateBitcoinCoreNode();
                builder.StartAll();

                stratisNode.NotInIBD();

                Block tip = coreNode.FindBlock(10).Last();
                stratisNode.CreateRPCClient().AddNode(coreNode.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode.CreateRPCClient().GetBestBlockHash());
                uint256 bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
                Assert.Equal(tip.GetHash(), bestBlockHash);

                //Now check if Core connect to stratis
                stratisNode.CreateRPCClient().RemoveNode(coreNode.Endpoint);
                TestHelper.WaitLoop(() => coreNode.CreateRPCClient().GetPeersInfo().Length == 0);

                tip = coreNode.FindBlock(10).Last();
                coreNode.CreateRPCClient().AddNode(stratisNode.Endpoint, true);
                TestHelper.WaitLoop(() => stratisNode.CreateRPCClient().GetBestBlockHash() == coreNode.CreateRPCClient().GetBestBlockHash());
                bestBlockHash = stratisNode.CreateRPCClient().GetBestBlockHash();
                Assert.Equal(tip.GetHash(), bestBlockHash);
            }
        }
예제 #5
0
        public void PullerVsMinerRaceCondition()
        {
            // Temporary fix so the Network static initialize will not break.
            Network m = Network.Main;

            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // This represents local node.
                CoreNode stratisMinerLocal = builder.CreateStratisPosNode();

                // This represents remote, which blocks are received by local node using its puller.
                CoreNode stratisMinerRemote = builder.CreateStratisPosNode();

                builder.StartAll();
                stratisMinerLocal.NotInIBD();
                stratisMinerRemote.NotInIBD();

                stratisMinerLocal.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisMinerLocal.FullNode.Network));
                stratisMinerRemote.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisMinerRemote.FullNode.Network));

                // Let's mine block Ap and Bp.
                stratisMinerRemote.GenerateStratisWithMiner(2);

                // Wait for block repository for block sync to work.
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisMinerRemote));
                stratisMinerLocal.CreateRPCClient().AddNode(stratisMinerRemote.Endpoint, true);

                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMinerLocal, stratisMinerRemote));

                // Now disconnect the peers and mine block C2p on remote.
                stratisMinerLocal.CreateRPCClient().RemoveNode(stratisMinerRemote.Endpoint);
                TestHelper.WaitLoop(() => !TestHelper.IsNodeConnected(stratisMinerRemote));

                // Mine block C2p.
                stratisMinerRemote.GenerateStratisWithMiner(1);
                Thread.Sleep(2000);

                // Now reconnect nodes and mine block C1s before C2p arrives.
                stratisMinerLocal.CreateRPCClient().AddNode(stratisMinerRemote.Endpoint, true);
                stratisMinerLocal.GenerateStratisWithMiner(1);

                // Mine block Dp.
                uint256 dpHash = stratisMinerRemote.GenerateStratisWithMiner(1)[0];

                // Now we wait until the local node's chain tip has correct hash of Dp.
                TestHelper.WaitLoop(() => stratisMinerLocal.FullNode.Chain.Tip.HashBlock.Equals(dpHash));

                // Then give it time to receive the block from the puller.
                Thread.Sleep(2500);

                // Check that local node accepted the Dp as consensus tip.
                Assert.Equal(stratisMinerLocal.FullNode.ChainBehaviorState.ConsensusTip.HashBlock, dpHash);
            }
        }
예제 #6
0
        public void PullerVsMinerRaceCondition()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                // This represents local node.
                CoreNode stratisMinerLocal = builder.CreateStratisPosNode(this.posNetwork);

                // This represents remote, which blocks are received by local node using its puller.
                CoreNode stratisMinerRemote = builder.CreateStratisPosNode(this.posNetwork);

                builder.StartAll();
                stratisMinerLocal.NotInIBD().WithWallet(walletPassword, walletName, walletPassphrase);
                stratisMinerRemote.NotInIBD().WithWallet(walletPassword, walletName, walletPassphrase);

                // Let's mine block Ap and Bp.
                TestHelper.MineBlocks(stratisMinerRemote, walletName, walletPassword, walletAccount, 2);

                // Wait for block repository for block sync to work.
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisMinerRemote));
                stratisMinerLocal.CreateRPCClient().AddNode(stratisMinerRemote.Endpoint, true);

                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMinerLocal, stratisMinerRemote));

                // Now disconnect the peers and mine block C2p on remote.
                stratisMinerLocal.CreateRPCClient().RemoveNode(stratisMinerRemote.Endpoint);
                TestHelper.WaitLoop(() => !TestHelper.IsNodeConnected(stratisMinerRemote));

                // Mine block C2p.
                stratisMinerRemote.GenerateStratisWithMiner(1);
                Thread.Sleep(2000);

                // Now reconnect nodes and mine block C1s before C2p arrives.
                stratisMinerLocal.CreateRPCClient().AddNode(stratisMinerRemote.Endpoint, true);
                TestHelper.MineBlocks(stratisMinerLocal, walletName, walletPassword, walletAccount, 1);

                // Mine block Dp.
                uint256 dpHash = TestHelper.MineBlocks(stratisMinerRemote, walletName, walletPassword, walletAccount, 1).BlockHashes[0];

                // Now we wait until the local node's chain tip has correct hash of Dp.
                TestHelper.WaitLoop(() => stratisMinerLocal.FullNode.Chain.Tip.HashBlock.Equals(dpHash));

                // Then give it time to receive the block from the puller.
                Thread.Sleep(2500);

                // Check that local node accepted the Dp as consensus tip.
                Assert.Equal(stratisMinerLocal.FullNode.ChainBehaviorState.ConsensusTip.HashBlock, dpHash);
            }
        }
예제 #7
0
        public void Miner_Create_Block_Whilst_Disconnected_Syncs()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode miner  = builder.CreateStratisPowNode(KnownNetworks.RegTest);
                CoreNode syncer = builder.CreateStratisPowNode(KnownNetworks.RegTest);

                builder.StartAll();
                miner.NotInIBD();
                syncer.NotInIBD();

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

                miner.GenerateStratisWithMiner(1);

                miner.CreateRPCClient().AddNode(syncer.Endpoint, true);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(miner, syncer));
            }
        }
예제 #8
0
        public void MinerCreateBlockSigopsLimit1000()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode miner = builder.CreateStratisPowNode(this.network);

                builder.StartAll();
                miner.NotInIBD();
                miner.SetDummyMinerSecret(new BitcoinSecret(new Key(), miner.FullNode.Network));
                miner.GenerateStratisWithMiner(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>(() => miner.GenerateStratisWithMiner(1));
                Assert.True(error.Message == ConsensusErrors.BadBlockSigOps.Message);

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

                Assert.True(miner.FullNode.ConsensusManager().Tip.Height == 1);
            }
        }
        public void AddToMempoolTrxSpendingTwoOutputFromSameTrx()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNodeSync = builder.CreateStratisPowNode();
                builder.StartAll();
                stratisNodeSync.NotInIBD();

                stratisNodeSync.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network));
                stratisNodeSync.GenerateStratis(105); // 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);

                Block       block   = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(4).HashBlock).Result;
                Transaction prevTrx = block.Transactions.First();
                var         dest1   = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network);
                var         dest2   = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network);

                Transaction parentTx = stratisNodeSync.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                parentTx.AddInput(new TxIn(new OutPoint(prevTrx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(stratisNodeSync.MinerSecret.PubKey)));
                parentTx.AddOutput(new TxOut("25", dest1.PubKey.Hash));
                parentTx.AddOutput(new TxOut("24", dest2.PubKey.Hash)); // 1 btc fee
                parentTx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false);
                stratisNodeSync.Broadcast(parentTx);
                // wiat for the trx to enter the pool
                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 1);
                // mine the transactions in the mempool
                stratisNodeSync.GenerateStratis(1, stratisNodeSync.FullNode.MempoolManager().InfoAllAsync().Result.Select(s => s.Trx).ToList());
                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 0);

                //create a new trx spending both outputs
                Transaction tx = stratisNodeSync.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                tx.AddInput(new TxIn(new OutPoint(parentTx.GetHash(), 0), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(dest1.PubKey)));
                tx.AddInput(new TxIn(new OutPoint(parentTx.GetHash(), 1), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(dest2.PubKey)));
                tx.AddOutput(new TxOut("48", new Key().PubKey.Hash)); // 1 btc fee
                Transaction signed = new TransactionBuilder(stratisNodeSync.FullNode.Network).AddKeys(dest1, dest2).AddCoins(parentTx.Outputs.AsCoins()).SignTransaction(tx);

                stratisNodeSync.Broadcast(signed);
                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 1);
            }
        }
        public void MempoolAddNodeWithOrphans()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNodeSync = builder.CreateStratisPowNode();
                builder.StartAll();
                stratisNodeSync.NotInIBD();

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

                Block       block   = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(1).HashBlock).Result;
                Transaction prevTrx = block.Transactions.First();
                var         dest    = new BitcoinSecret(new Key(), stratisNodeSync.FullNode.Network);

                var         key = new Key();
                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", key.PubKey.Hash)); // 1 btc fee
                tx.Sign(stratisNodeSync.FullNode.Network, stratisNodeSync.MinerSecret, false);

                Transaction txOrphan = stratisNodeSync.FullNode.Network.Consensus.ConsensusFactory.CreateTransaction();
                txOrphan.AddInput(new TxIn(new OutPoint(tx.GetHash(), 1), PayToPubkeyHashTemplate.Instance.GenerateScriptPubKey(key.PubKey)));
                txOrphan.AddOutput(new TxOut("10", new Key().PubKey.Hash));
                txOrphan.Sign(stratisNodeSync.FullNode.Network, key.GetBitcoinSecret(stratisNodeSync.FullNode.Network), false);

                // broadcast the orphan
                stratisNodeSync.Broadcast(txOrphan);
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.NodeService <MempoolOrphans>().OrphansList().Count == 1);
                // broadcast the parent
                stratisNodeSync.Broadcast(tx);
                TestHelper.WaitLoop(() => stratisNodeSync.FullNode.NodeService <MempoolOrphans>().OrphansList().Count == 0);
                // wait for orphan to get in the pool
                TestHelper.WaitLoop(() => stratisNodeSync.CreateRPCClient().GetRawMempool().Length == 2);
            }
        }
        public void MempoolReceiveFromManyNodes()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode 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 (int index in Enumerable.Range(1, 100))
                {
                    Block       block   = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(index).HashBlock).Result;
                    Transaction 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);
            }
        }
예제 #12
0
        public void GetProofOfWorkRewardForMinedBlocksTest()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode 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));
            }
        }
예제 #13
0
        public void NodesCanConnectToEachOthers()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode node1 = builder.CreateStratisPowNode(this.powNetwork);
                CoreNode node2 = builder.CreateStratisPowNode(this.powNetwork);
                builder.StartAll();
                node1.NotInIBD();
                node2.NotInIBD();
                Assert.Empty(node1.FullNode.ConnectionManager.ConnectedPeers);
                Assert.Empty(node2.FullNode.ConnectionManager.ConnectedPeers);
                RPCClient rpc1 = node1.CreateRPCClient();
                rpc1.AddNode(node2.Endpoint, true);
                Assert.Single(node1.FullNode.ConnectionManager.ConnectedPeers);
                Assert.Single(node2.FullNode.ConnectionManager.ConnectedPeers);

                var behavior = node1.FullNode.ConnectionManager.ConnectedPeers.First().Behaviors.Find <IConnectionManagerBehavior>();
                Assert.False(behavior.Inbound);
                Assert.True(behavior.OneTry);
                behavior = node2.FullNode.ConnectionManager.ConnectedPeers.First().Behaviors.Find <IConnectionManagerBehavior>();
                Assert.True(behavior.Inbound);
                Assert.False(behavior.OneTry);
            }
        }
예제 #14
0
        public void Given_NodesAreSynced_When_ABigReorgHappens_Then_TheReorgIsIgnored()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisMiner  = builder.CreateStratisPosNode(this.posNetwork);
                CoreNode stratisSyncer = builder.CreateStratisPosNode(this.posNetwork);
                CoreNode stratisReorg  = builder.CreateStratisPosNode(this.posNetwork);

                builder.StartAll();
                stratisMiner.NotInIBD().WithWallet();
                stratisSyncer.NotInIBD();
                stratisReorg.NotInIBD().WithWallet();

                TestHelper.MineBlocks(stratisMiner, 1);

                // wait for block repo for block sync to work
                stratisMiner.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                stratisMiner.CreateRPCClient().AddNode(stratisSyncer.Endpoint, true);

                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisSyncer));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisReorg));

                // create a reorg by mining on two different chains
                // ================================================

                stratisMiner.CreateRPCClient().RemoveNode(stratisReorg.Endpoint);
                stratisSyncer.CreateRPCClient().RemoveNode(stratisReorg.Endpoint);
                TestHelper.WaitLoop(() => !TestHelper.IsNodeConnected(stratisReorg));

                TestHelper.MineBlocks(stratisMiner, 11);
                TestHelper.MineBlocks(stratisReorg, 12);

                // make sure the nodes are actually on different chains.
                Assert.NotEqual(stratisMiner.FullNode.Chain.GetBlock(2).HashBlock, stratisReorg.FullNode.Chain.GetBlock(2).HashBlock);

                TestHelper.TriggerSync(stratisSyncer);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisSyncer));

                // The hash before the reorg node is connected.
                uint256 hashBeforeReorg = stratisMiner.FullNode.Chain.Tip.HashBlock;

                // connect the reorg chain
                stratisMiner.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                stratisSyncer.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);

                // trigger nodes to sync
                TestHelper.TriggerSync(stratisMiner);
                TestHelper.TriggerSync(stratisReorg);
                TestHelper.TriggerSync(stratisSyncer);

                // wait for the synced chain to get headers updated.
                TestHelper.WaitLoop(() => !stratisReorg.FullNode.ConnectionManager.ConnectedPeers.Any());

                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisSyncer));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReorg, stratisMiner) == false);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReorg, stratisSyncer) == false);

                // check that a reorg did not happen.
                Assert.Equal(hashBeforeReorg, stratisSyncer.FullNode.Chain.Tip.HashBlock);
            }
        }
예제 #15
0
        public void MiningNodeWithOneConnectionAlwaysSynced()
        {
            string testFolderPath = Path.Combine(this.GetType().Name, nameof(MiningNodeWithOneConnectionAlwaysSynced));

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

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

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

                CoreNode secondNode = nodeBuilder.CreateStratisPowNode(this.powNetwork);
                secondNode.Start();
                secondNode.NotInIBD().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 Given_NodesAreSynced_When_ABigReorgHappens_Then_TheReorgIsIgnored()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisMiner  = builder.CreateStratisPosNode();
                CoreNode stratisSyncer = builder.CreateStratisPosNode();
                CoreNode stratisReorg  = builder.CreateStratisPosNode();

                builder.StartAll();
                stratisMiner.NotInIBD();
                stratisSyncer.NotInIBD();
                stratisReorg.NotInIBD();

                // TODO: set the max allowed reorg threshold here
                // assume a reorg of 10 blocks is not allowed.
                stratisMiner.FullNode.ChainBehaviorState.MaxReorgLength  = 10;
                stratisSyncer.FullNode.ChainBehaviorState.MaxReorgLength = 10;
                stratisReorg.FullNode.ChainBehaviorState.MaxReorgLength  = 10;

                stratisMiner.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisMiner.FullNode.Network));
                stratisReorg.SetDummyMinerSecret(new BitcoinSecret(new Key(), stratisReorg.FullNode.Network));

                stratisMiner.GenerateStratisWithMiner(1);

                // wait for block repo for block sync to work
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisMiner));
                stratisMiner.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                stratisMiner.CreateRPCClient().AddNode(stratisSyncer.Endpoint, true);

                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisSyncer));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisReorg));

                // create a reorg by mining on two different chains
                // ================================================

                stratisMiner.CreateRPCClient().RemoveNode(stratisReorg.Endpoint);
                stratisSyncer.CreateRPCClient().RemoveNode(stratisReorg.Endpoint);
                TestHelper.WaitLoop(() => !TestHelper.IsNodeConnected(stratisReorg));

                Task <List <uint256> > t1 = Task.Run(() => stratisMiner.GenerateStratisWithMiner(11));
                Task <List <uint256> > t2 = Task.Delay(1000).ContinueWith(t => stratisReorg.GenerateStratisWithMiner(12));
                Task.WaitAll(t1, t2);
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisMiner));
                TestHelper.WaitLoop(() => TestHelper.IsNodeSynced(stratisReorg));

                // make sure the nodes are actually on different chains.
                Assert.NotEqual(stratisMiner.FullNode.Chain.GetBlock(2).HashBlock, stratisReorg.FullNode.Chain.GetBlock(2).HashBlock);

                TestHelper.TriggerSync(stratisSyncer);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisSyncer));

                // The hash before the reorg node is connected.
                uint256 hashBeforeReorg = stratisMiner.FullNode.Chain.Tip.HashBlock;

                // connect the reorg chain
                stratisMiner.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);
                stratisSyncer.CreateRPCClient().AddNode(stratisReorg.Endpoint, true);

                // trigger nodes to sync
                TestHelper.TriggerSync(stratisMiner);
                TestHelper.TriggerSync(stratisReorg);
                TestHelper.TriggerSync(stratisSyncer);

                // wait for the synced chain to get headers updated.
                TestHelper.WaitLoop(() => !stratisReorg.FullNode.ConnectionManager.ConnectedPeers.Any());

                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisMiner, stratisSyncer));
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReorg, stratisMiner) == false);
                TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(stratisReorg, stratisSyncer) == false);

                // check that a reorg did not happen.
                Assert.Equal(hashBeforeReorg, stratisSyncer.FullNode.Chain.Tip.HashBlock);
            }
        }
        public void TxMempoolBlockDoublespend()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNodeSync = builder.CreateStratisPowNode();
                builder.StartAll();
                stratisNodeSync.NotInIBD();
                stratisNodeSync.FullNode.NodeService <MempoolSettings>().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.

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

                // Create a double-spend of mature coinbase txn:
                var spends = new List <Transaction>(2);
                foreach (int index in Enumerable.Range(1, 2))
                {
                    Transaction 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.
                Block 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:
                var 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);
            }
        }
예제 #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);
            }
        }
        public void MempoolSyncTransactions()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                CoreNode stratisNodeSync = builder.CreateStratisPowNode();
                CoreNode stratisNode1    = builder.CreateStratisPowNode();
                CoreNode 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 (int index in Enumerable.Range(1, 5))
                {
                    Block       block   = stratisNodeSync.FullNode.BlockStoreManager().BlockRepository.GetAsync(stratisNodeSync.FullNode.Chain.GetBlock(index).HashBlock).Result;
                    Transaction 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);

                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);
            }
        }