public void Given_NodesAreSynced_When_ABigReorgHappens_Then_TheReorgIsIgnored() { using (NodeBuilder builder = NodeBuilder.Create(this)) { CoreNode stratisMiner = builder.CreateStratisPosNode(this.posNetwork).NotInIBD(); CoreNode stratisSyncer = builder.CreateStratisPosNode(this.posNetwork).NotInIBD(); CoreNode stratisReorg = builder.CreateStratisPosNode(this.posNetwork).NotInIBD(); builder.StartAll(); stratisMiner.WithWallet(); stratisReorg.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); } }
public void PullerVsMinerRaceCondition() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // This represents local node. CoreNode stratisMinerLocal = builder.CreateStratisPosNode(this.posNetwork).NotInIBD(); // This represents remote, which blocks are received by local node using its puller. CoreNode stratisMinerRemote = builder.CreateStratisPosNode(this.posNetwork).NotInIBD(); builder.StartAll(); stratisMinerLocal.WithWallet(); stratisMinerRemote.WithWallet(); // Let's mine block Ap and Bp. TestHelper.MineBlocks(stratisMinerRemote, 2); // Wait for block repository for block sync to work. 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. TestHelper.MineBlocks(stratisMinerRemote, 1); Thread.Sleep(2000); // Now reconnect nodes and mine block C1s before C2p arrives. stratisMinerLocal.CreateRPCClient().AddNode(stratisMinerRemote.Endpoint, true); TestHelper.MineBlocks(stratisMinerLocal, 1); // Mine block Dp. uint256 dpHash = TestHelper.MineBlocks(stratisMinerRemote, 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); } }
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); } }