public void ConsensusManager_Connect_New_Block_Failed() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var syncerNetwork = new StratisOverrideRegTest(); var minerA = builder.CreateStratisPosNode(this.posNetwork); var syncer = builder.CreateStratisPosNode(syncerNetwork); builder.StartAll(); minerA.NotInIBD().WithWallet(); syncer.NotInIBD(); // Miner A mines to height 11. TestHelper.MineBlocks(minerA, 11); // Inject a rule that will fail at block 11 of the new chain ConsensusRuleEngine engine = syncer.FullNode.NodeService <IConsensusRuleEngine>() as ConsensusRuleEngine; syncerNetwork.Consensus.FullValidationRules.Insert(1, new FailValidation(11)); engine.Register(); // Connect syncer to Miner A, reorg should fail. TestHelper.Connect(syncer, minerA); // Syncer should disconnect from miner A after the failed block. TestHelper.WaitLoop(() => !TestHelper.IsNodeConnectedTo(syncer, minerA)); // Make sure syncer rolled back Assert.True(syncer.FullNode.ConsensusManager().Tip.Height == 10); } }
public void ColdStakingActivatedOnStratisNode() { using (NodeBuilder builder = NodeBuilder.Create(this)) { // Create separate network parameters for this test. var network = new StratisOverrideRegTest(); // Set the date ranges such that ColdStaking will 'Start' immediately after the initial confirmation window. network.Consensus.BIP9Deployments[StratisBIP9Deployments.ColdStaking] = new BIP9DeploymentsParameters(1, 0, DateTime.Now.AddDays(50).ToUnixTimestamp()); // Set a small confirmation window to reduce time taken by this test. network.Consensus.MinerConfirmationWindow = 10; // Minimum number of 'votes' required within the conformation window to reach 'LockedIn' state. network.Consensus.RuleChangeActivationThreshold = 8; CoreNode stratisNode = builder.CreateStratisPosNode(network).WithWallet(); stratisNode.Start(); // ColdStaking activation: // - Deployment state changes every 'MinerConfirmationWindow' blocks. // - Remains in 'Defined' state until 'startedHeight'. // - Changes to 'Started' state at 'startedHeight'. // - Changes to 'LockedIn' state at 'lockedInHeight' (as coldstaking should already be signaled in blocks). // - Changes to 'Active' state at 'activeHeight'. int startedHeight = network.Consensus.MinerConfirmationWindow - 1; int lockedInHeight = startedHeight + network.Consensus.MinerConfirmationWindow; int activeHeight = lockedInHeight + network.Consensus.MinerConfirmationWindow; // Generate enough blocks to cover all state changes. TestHelper.MineBlocks(stratisNode, activeHeight + 1); // Check that coldstaking states got updated as expected. ThresholdConditionCache cache = (stratisNode.FullNode.NodeService <IConsensusRuleEngine>() as ConsensusRuleEngine).NodeDeployments.BIP9; Assert.Equal(ThresholdState.Defined, cache.GetState(stratisNode.FullNode.Chain.GetBlock(startedHeight - 1), StratisBIP9Deployments.ColdStaking)); Assert.Equal(ThresholdState.Started, cache.GetState(stratisNode.FullNode.Chain.GetBlock(startedHeight), StratisBIP9Deployments.ColdStaking)); Assert.Equal(ThresholdState.LockedIn, cache.GetState(stratisNode.FullNode.Chain.GetBlock(lockedInHeight), StratisBIP9Deployments.ColdStaking)); Assert.Equal(ThresholdState.Active, cache.GetState(stratisNode.FullNode.Chain.GetBlock(activeHeight), StratisBIP9Deployments.ColdStaking)); // Verify that the block created before activation does not have the 'CheckColdStakeVerify' flag set. var rulesEngine = stratisNode.FullNode.NodeService <IConsensusRuleEngine>(); ChainedHeader prevHeader = stratisNode.FullNode.Chain.GetBlock(activeHeight - 1); DeploymentFlags flags1 = (rulesEngine as ConsensusRuleEngine).NodeDeployments.GetFlags(prevHeader); Assert.Equal(0, (int)(flags1.ScriptFlags & ScriptVerify.CheckColdStakeVerify)); // Verify that the block created after activation has the 'CheckColdStakeVerify' flag set. DeploymentFlags flags2 = (rulesEngine as ConsensusRuleEngine).NodeDeployments.GetFlags(stratisNode.FullNode.Chain.Tip); Assert.NotEqual(0, (int)(flags2.ScriptFlags & ScriptVerify.CheckColdStakeVerify)); } }
public void ConsensusManager_Reorgs_Then_Try_To_Connect_Longer_Chain__With_Connected_Blocks_And_Fail_Then_Revert_Back() { using (NodeBuilder builder = NodeBuilder.Create(this)) { var syncerNetwork = new StratisOverrideRegTest(); var minerA = builder.CreateStratisPosNode(this.posNetwork); var minerB = builder.CreateStratisPosNode(this.posNetwork); var syncer = builder.CreateStratisPosNode(syncerNetwork); builder.StartAll(); minerA.NotInIBD().WithWallet(); minerB.NotInIBD().WithWallet(); syncer.NotInIBD(); // MinerA mines to height 10. TestHelper.MineBlocks(minerA, 10); // Sync the network to height 10. TestHelper.ConnectAndSync(syncer, minerA, minerB); // Disable syncer from sending blocks to miner B TestHelper.DisableBlockPropagation(syncer, minerB); // Miner A and syncer continues to mine to height 20. TestHelper.MineBlocks(minerA, 10); TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(syncer, minerA)); // Inject a rule that will fail at block 15 of the new chain. ConsensusRuleEngine engine = syncer.FullNode.NodeService <IConsensusRuleEngine>() as ConsensusRuleEngine; syncerNetwork.Consensus.FullValidationRules.Insert(1, new FailValidation(15)); engine.Register(); // Miner B continues to mine to height 30 on a new and longer chain. TestHelper.MineBlocks(minerB, 20); // check miner B at height 30. Assert.True(minerB.FullNode.ConsensusManager().Tip.Height == 30); // Miner B should become disconnected. TestHelper.WaitLoop(() => !TestHelper.IsNodeConnectedTo(syncer, minerB)); // Make sure syncer rolled back. Assert.True(syncer.FullNode.ConsensusManager().Tip.Height == 20); // Check syncer is still synced with Miner A. TestHelper.WaitLoop(() => TestHelper.AreNodesSynced(syncer, minerA)); } }