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 SmartContractCoinViewRuleLogic(ConsensusRuleEngine parent)
 {
     this.refundCounter        = 1;
     this.Parent               = parent;
     this.blockTxsProcessed    = new List <Transaction>();
     this.receipts             = new List <Receipt>();
     this.ContractCoinviewRule = (ISmartContractCoinviewRule)this.Parent;
 }
        public void ConsensusManager_Reorgs_Then_Try_To_Connect_Longer_Chain__With__No_Connected_Blocks_And_Fail_Then_Revert_Back()
        {
            using (NodeBuilder builder = NodeBuilder.Create(this))
            {
                var syncerNetwork = new BitcoinOverrideRegTest();

                var minerA = builder.CreateStratisPowNode(this.powNetwork);
                var minerB = builder.CreateStratisPowNode(this.powNetwork);
                var syncer = builder.CreateStratisPowNode(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 11 of the new chain
                ConsensusRuleEngine engine = syncer.FullNode.NodeService <IConsensusRuleEngine>() as ConsensusRuleEngine;
                syncerNetwork.Consensus.FullValidationRules.Insert(1, new FailValidation(11));
                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));
            }
        }
Example #4
0
        public T RegisterRule <T>(ConsensusRuleEngine ruleEngine) where T : ConsensusRuleBase, new()
        {
            var rule = new T();

            if (rule is IHeaderValidationConsensusRule validationConsensusRule)
            {
                ruleEngine.Network.Consensus.HeaderValidationRules = new List <IHeaderValidationConsensusRule>()
                {
                    validationConsensusRule
                }
            }
            ;
            else if (rule is IIntegrityValidationConsensusRule consensusRule)
            {
                ruleEngine.Network.Consensus.IntegrityValidationRules = new List <IIntegrityValidationConsensusRule>()
                {
                    consensusRule
                }
            }
            ;
            else if (rule is IPartialValidationConsensusRule partialValidationConsensusRule)
            {
                ruleEngine.Network.Consensus.PartialValidationRules = new List <IPartialValidationConsensusRule>()
                {
                    partialValidationConsensusRule
                }
            }
            ;
            else if (rule is IFullValidationConsensusRule fullValidationConsensusRule)
            {
                ruleEngine.Network.Consensus.FullValidationRules = new List <IFullValidationConsensusRule>()
                {
                    fullValidationConsensusRule
                }
            }
            ;
            else
            {
                throw new Exception("Rule type wasn't recognized.");
            }

            ruleEngine.Register();
            return(rule);
        }
        public IActionResult DeploymentFlags()
        {
            try
            {
                ConsensusRuleEngine ruleEngine = this.ConsensusManager.ConsensusRules as ConsensusRuleEngine;

                // Ensure threshold conditions cached.
                ThresholdState[] thresholdStates = ruleEngine.NodeDeployments.BIP9.GetStates(this.ChainState.ConsensusTip.Previous);

                List <ThresholdStateModel> metrics = ruleEngine.NodeDeployments.BIP9.GetThresholdStateMetrics(this.ChainState.ConsensusTip.Previous, thresholdStates);

                return(this.Json(metrics));
            }
            catch (Exception e)
            {
                this.logger.LogError("Exception occurred: {0}", e.ToString());
                return(ErrorHelpers.BuildErrorResponse(HttpStatusCode.BadRequest, e.Message, e.ToString()));
            }
        }
Example #6
0
            public async Task InitializeAsync()
            {
                this.blockinfo = new List <Blockinfo>();
                List <long> lst = blockinfoarr.Cast <long>().ToList();

                for (int i = 0; i < lst.Count; i += 2)
                {
                    this.blockinfo.Add(new Blockinfo {
                        extranonce = (int)lst[i], nonce = (uint)lst[i + 1]
                    });
                }

                // Note that by default, these tests run with size accounting enabled.
                this.network = KnownNetworks.RegTest;
                byte[] hex = Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
                this.scriptPubKey = new Script(new[] { Op.GetPushOp(hex), OpcodeType.OP_CHECKSIG });

                this.entry        = new TestMemPoolEntryHelper();
                this.ChainIndexer = new ChainIndexer(this.network);
                this.network.Consensus.Options = new ConsensusOptions();

                IDateTimeProvider dateTimeProvider = DateTimeProvider.Default;

                var loggerFactory = ExtendedLoggerFactory.Create();

                var nodeSettings      = new NodeSettings(this.network, args: new string[] { "-checkpoints" });
                var consensusSettings = new ConsensusSettings(nodeSettings);

                var inMemoryCoinView = new InMemoryCoinView(new HashHeightPair(this.ChainIndexer.Tip));
                var nodeStats        = new NodeStats(dateTimeProvider, loggerFactory);

                this.cachedCoinView = new CachedCoinView(this.network, new Checkpoints(), inMemoryCoinView, dateTimeProvider, new LoggerFactory(), nodeStats, consensusSettings);

                var signals       = new Signals.Signals(loggerFactory, null);
                var asyncProvider = new AsyncProvider(loggerFactory, signals, new NodeLifetime());

                var deployments = new NodeDeployments(this.network, this.ChainIndexer);

                var genesis = this.network.GetGenesis();

                var chainState = new ChainState()
                {
                    BlockStoreTip = new ChainedHeader(genesis.Header, genesis.GetHash(), 0)
                };

                var consensusRulesContainer = new ConsensusRulesContainer();

                foreach (var ruleType in this.network.Consensus.ConsensusRules.HeaderValidationRules)
                {
                    consensusRulesContainer.HeaderValidationRules.Add(Activator.CreateInstance(ruleType) as HeaderValidationConsensusRule);
                }
                foreach (var ruleType in this.network.Consensus.ConsensusRules.FullValidationRules)
                {
                    FullValidationConsensusRule rule = null;
                    if (ruleType == typeof(FlushUtxosetRule))
                    {
                        rule = new FlushUtxosetRule(new Mock <IInitialBlockDownloadState>().Object);
                    }
                    else
                    {
                        rule = Activator.CreateInstance(ruleType) as FullValidationConsensusRule;
                    }

                    consensusRulesContainer.FullValidationRules.Add(rule);
                }

                this.ConsensusRules = new PowConsensusRuleEngine(this.network, loggerFactory, dateTimeProvider, this.ChainIndexer, deployments, consensusSettings,
                                                                 new Checkpoints(), this.cachedCoinView, chainState, new InvalidBlockHashStore(dateTimeProvider), nodeStats, asyncProvider, consensusRulesContainer).SetupRulesEngineParent();

                this.consensus = ConsensusManagerHelper.CreateConsensusManager(this.network, chainState: chainState, inMemoryCoinView: inMemoryCoinView, chainIndexer: this.ChainIndexer, consensusRules: this.ConsensusRules);

                await this.consensus.InitializeAsync(chainState.BlockStoreTip);

                this.entry.Fee(11);
                this.entry.Height(11);

                var dateTimeProviderSet = new DateTimeProviderSet
                {
                    time    = dateTimeProvider.GetTime(),
                    timeutc = dateTimeProvider.GetUtcNow()
                };

                this.DateTimeProvider = dateTimeProviderSet;
                this.mempool          = new TxMempool(dateTimeProvider, new BlockPolicyEstimator(new MempoolSettings(nodeSettings), loggerFactory, nodeSettings), loggerFactory, nodeSettings);
                this.mempoolLock      = new MempoolSchedulerLock();

                // We can't make transactions until we have inputs
                // Therefore, load 100 blocks :)
                this.baseheight = 0;
                var blocks = new List <Block>();

                this.txFirst = new List <Transaction>();

                this.nonce = 0;

                for (int i = 0; i < this.blockinfo.Count; ++i)
                {
                    Block block = this.network.CreateBlock();
                    block.Header.HashPrevBlock = this.consensus.Tip.HashBlock;
                    block.Header.Version       = 1;
                    block.Header.Time          = Utils.DateTimeToUnixTime(this.ChainIndexer.Tip.GetMedianTimePast()) + 1;

                    Transaction txCoinbase = this.network.CreateTransaction();
                    txCoinbase.Version = 1;
                    txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(this.blockinfo[i].extranonce), Op.GetPushOp(this.ChainIndexer.Height) })));
                    // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
                    txCoinbase.AddOutput(new TxOut(Money.Zero, new Script()));
                    block.AddTransaction(txCoinbase);

                    if (this.txFirst.Count == 0)
                    {
                        this.baseheight = this.ChainIndexer.Height;
                    }

                    if (this.txFirst.Count < 4)
                    {
                        this.txFirst.Add(block.Transactions[0]);
                    }

                    block.Header.Bits = block.Header.GetWorkRequired(this.network, this.ChainIndexer.Tip);

                    block.UpdateMerkleRoot();

                    while (!block.CheckProofOfWork())
                    {
                        block.Header.Nonce = ++this.nonce;
                    }

                    // Serialization sets the BlockSize property.
                    block = Block.Load(block.ToBytes(), this.network.Consensus.ConsensusFactory);

                    var res = await this.consensus.BlockMinedAsync(block);

                    if (res == null)
                    {
                        throw new InvalidOperationException();
                    }

                    blocks.Add(block);
                }

                // Just to make sure we can still make simple blocks
                this.newBlock = AssemblerForTest(this).Build(this.ChainIndexer.Tip, this.scriptPubKey);
                Assert.NotNull(this.newBlock);
            }
Example #7
0
        public BlockchainInfoModel GetBlockchainInfo()
        {
            var blockchainInfo = new BlockchainInfoModel
            {
                Chain                  = this.Network?.Name,
                Blocks                 = (uint)(this.ChainState?.ConsensusTip?.Height ?? 0),
                Headers                = (uint)(this.ChainIndexer?.Height ?? 0),
                BestBlockHash          = this.ChainState?.ConsensusTip?.HashBlock,
                Difficulty             = this.GetNetworkDifficulty()?.Difficulty ?? 0.0,
                MedianTime             = this.ChainState?.ConsensusTip?.GetMedianTimePast().ToUnixTimeSeconds() ?? 0,
                VerificationProgress   = 0.0,
                IsInitialBlockDownload = this.ibdState?.IsInitialBlockDownload() ?? true,
                Chainwork              = this.ChainState?.ConsensusTip?.ChainWork,
                IsPruned               = false
            };

            if (blockchainInfo.Headers > 0)
            {
                blockchainInfo.VerificationProgress = (double)blockchainInfo.Blocks / blockchainInfo.Headers;
            }

            // softfork deployments
            blockchainInfo.SoftForks = new List <SoftForks>();

            foreach (var consensusBuriedDeployment in Enum.GetValues(typeof(BuriedDeployments)))
            {
                bool active = this.ChainIndexer.Height >= this.Network.Consensus.BuriedDeployments[(BuriedDeployments)consensusBuriedDeployment];
                blockchainInfo.SoftForks.Add(new SoftForks
                {
                    Id      = consensusBuriedDeployment.ToString().ToLower(),
                    Version = (int)consensusBuriedDeployment + 2, // hack to get the deployment number similar to bitcoin core without changing the enums
                    Status  = new SoftForksStatus {
                        Status = active
                    }
                });
            }

            // softforkbip9 deployments
            blockchainInfo.SoftForksBip9 = new Dictionary <string, SoftForksBip9>();

            ConsensusRuleEngine ruleEngine = (ConsensusRuleEngine)this.ConsensusManager.ConsensusRules;

            ThresholdState[]           thresholdStates = ruleEngine.NodeDeployments.BIP9.GetStates(this.ChainIndexer.Tip.Previous);
            List <ThresholdStateModel> metrics         = ruleEngine.NodeDeployments.BIP9.GetThresholdStateMetrics(this.ChainIndexer.Tip.Previous, thresholdStates);

            foreach (ThresholdStateModel metric in metrics.Where(m => !m.DeploymentName.ToLower().Contains("test"))) // to remove the test dummy
            {
                // TODO: Deployment timeout may not be implemented yet

                // Deployments with timeout value of 0 are hidden.
                // A timeout value of 0 guarantees a softfork will never be activated.
                // This is used when softfork codes are merged without specifying the deployment schedule.
                if (metric.TimeTimeOut?.Ticks > 0)
                {
                    blockchainInfo.SoftForksBip9.Add(metric.DeploymentName, this.CreateSoftForksBip9(metric, thresholdStates[metric.DeploymentIndex]));
                }
            }

            // TODO: Implement blockchainInfo.warnings
            return(blockchainInfo);
        }
Example #8
0
 public RuleRegistrationHelper(ConsensusRuleEngine ruleEngine, ConsensusRulesContainer consensusRulesContainer)
 {
     this.ruleEngine = ruleEngine;
     this.consensusRulesContainer = consensusRulesContainer;
 }
        public static ConsensusManager CreateConsensusManager(
            Network network,
            string dataDir                     = null,
            ChainState chainState              = null,
            InMemoryCoinView inMemoryCoinView  = null,
            ConcurrentChain chain              = null,
            IRuleRegistration ruleRegistration = null,
            ConsensusRuleEngine consensusRules = null)
        {
            string[] param = dataDir == null ? new string[] {} : new string[] { $"-datadir={dataDir}" };

            var nodeSettings = new NodeSettings(network, args: param);

            ILoggerFactory    loggerFactory    = nodeSettings.LoggerFactory;
            IDateTimeProvider dateTimeProvider = DateTimeProvider.Default;

            network.Consensus.Options = new ConsensusOptions();

            if (ruleRegistration == null)
            {
                ruleRegistration = new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration();
            }

            ruleRegistration.RegisterRules(network.Consensus);

            // Dont check PoW of a header in this test.
            network.Consensus.HeaderValidationRules.RemoveAll(x => x.GetType() == typeof(CheckDifficultyPowRule));

            var consensusSettings = new ConsensusSettings(nodeSettings);

            if (chain == null)
            {
                chain = new ConcurrentChain(network);
            }

            if (inMemoryCoinView == null)
            {
                inMemoryCoinView = new InMemoryCoinView(chain.Tip.HashBlock);
            }

            var networkPeerFactory = new NetworkPeerFactory(network,
                                                            dateTimeProvider,
                                                            loggerFactory, new PayloadProvider().DiscoverPayloads(),
                                                            new SelfEndpointTracker(loggerFactory),
                                                            new Mock <IInitialBlockDownloadState>().Object,
                                                            new ConnectionManagerSettings());

            var peerAddressManager  = new PeerAddressManager(DateTimeProvider.Default, nodeSettings.DataFolder, loggerFactory, new SelfEndpointTracker(loggerFactory));
            var peerDiscovery       = new PeerDiscovery(new AsyncLoopFactory(loggerFactory), loggerFactory, network, networkPeerFactory, new NodeLifetime(), nodeSettings, peerAddressManager);
            var connectionSettings  = new ConnectionManagerSettings(nodeSettings);
            var selfEndpointTracker = new SelfEndpointTracker(loggerFactory);
            var connectionManager   = new ConnectionManager(dateTimeProvider, loggerFactory, network, networkPeerFactory, nodeSettings,
                                                            new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { },
                                                            peerDiscovery, selfEndpointTracker, connectionSettings, new VersionProvider(), new Mock <INodeStats>().Object);

            if (chainState == null)
            {
                chainState = new ChainState();
            }
            var peerBanning = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, peerAddressManager);
            var deployments = new NodeDeployments(network, chain);

            if (consensusRules == null)
            {
                consensusRules = new PowConsensusRuleEngine(network, loggerFactory, dateTimeProvider, chain, deployments, consensusSettings,
                                                            new Checkpoints(), inMemoryCoinView, chainState, new InvalidBlockHashStore(dateTimeProvider), new NodeStats(dateTimeProvider)).Register();
            }

            consensusRules.Register();

            var tree = new ChainedHeaderTree(network, loggerFactory, new HeaderValidator(consensusRules, loggerFactory), new Checkpoints(),
                                             new ChainState(), new Mock <IFinalizedBlockInfoRepository>().Object, consensusSettings, new InvalidBlockHashStore(new DateTimeProvider()));

            var consensus = new ConsensusManager(tree, network, loggerFactory, chainState, new IntegrityValidator(consensusRules, loggerFactory),
                                                 new PartialValidator(consensusRules, loggerFactory), new FullValidator(consensusRules, loggerFactory), consensusRules,
                                                 new Mock <IFinalizedBlockInfoRepository>().Object, new Signals.Signals(), peerBanning, new Mock <IInitialBlockDownloadState>().Object, chain,
                                                 new Mock <IBlockPuller>().Object, new Mock <IBlockStore>().Object, new Mock <IConnectionManager>().Object, new Mock <INodeStats>().Object, new NodeLifetime());

            return(consensus);
        }
Example #10
0
            public async Task InitializeAsync()
            {
                this.blockinfo = new List <Blockinfo>();
                List <long> lst = blockinfoarr.Cast <long>().ToList();

                for (int i = 0; i < lst.Count; i += 2)
                {
                    this.blockinfo.Add(new Blockinfo {
                        extranonce = (int)lst[i], nonce = (uint)lst[i + 1]
                    });
                }

                // Note that by default, these tests run with size accounting enabled.
                this.network = KnownNetworks.RegTest;
                byte[] hex = Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f");
                this.scriptPubKey = new Script(new[] { Op.GetPushOp(hex), OpcodeType.OP_CHECKSIG });

                this.entry = new TestMemPoolEntryHelper();
                this.chain = new ConcurrentChain(this.network);
                this.network.Consensus.Options = new ConsensusOptions();

                new FullNodeBuilderConsensusExtension.PowConsensusRulesRegistration().RegisterRules(this.network.Consensus);

                IDateTimeProvider dateTimeProvider = DateTimeProvider.Default;

                this.cachedCoinView = new CachedCoinView(new InMemoryCoinView(this.chain.Tip.HashBlock), dateTimeProvider, new LoggerFactory());

                var loggerFactory = new ExtendedLoggerFactory();

                loggerFactory.AddConsoleWithFilters();

                var nodeSettings      = new NodeSettings(args: new string[] { "-checkpoints" });
                var consensusSettings = new ConsensusSettings(nodeSettings);

                var networkPeerFactory = new NetworkPeerFactory(this.network, dateTimeProvider, loggerFactory, new PayloadProvider().DiscoverPayloads(), new SelfEndpointTracker(loggerFactory), new Mock <IInitialBlockDownloadState>().Object, new ConnectionManagerSettings());

                var peerAddressManager  = new PeerAddressManager(DateTimeProvider.Default, nodeSettings.DataFolder, loggerFactory, new SelfEndpointTracker(loggerFactory));
                var peerDiscovery       = new PeerDiscovery(new AsyncLoopFactory(loggerFactory), loggerFactory, this.network, networkPeerFactory, new NodeLifetime(), nodeSettings, peerAddressManager);
                var connectionSettings  = new ConnectionManagerSettings(nodeSettings);
                var selfEndpointTracker = new SelfEndpointTracker(loggerFactory);
                var connectionManager   = new ConnectionManager(dateTimeProvider, loggerFactory, this.network, networkPeerFactory,
                                                                nodeSettings, new NodeLifetime(), new NetworkPeerConnectionParameters(), peerAddressManager, new IPeerConnector[] { },
                                                                peerDiscovery, selfEndpointTracker, connectionSettings, new VersionProvider(), new Mock <INodeStats>().Object);

                var peerBanning = new PeerBanning(connectionManager, loggerFactory, dateTimeProvider, peerAddressManager);
                var deployments = new NodeDeployments(this.network, this.chain);

                var genesis = this.network.GetGenesis();

                var chainState = new ChainState()
                {
                    BlockStoreTip = new ChainedHeader(genesis.Header, genesis.GetHash(), 0)
                };

                this.ConsensusRules = new PowConsensusRuleEngine(this.network, loggerFactory, dateTimeProvider, this.chain, deployments, consensusSettings,
                                                                 new Checkpoints(), this.cachedCoinView, chainState, new InvalidBlockHashStore(dateTimeProvider)).Register();

                this.consensus = ConsensusManagerHelper.CreateConsensusManager(this.network);
                await this.consensus.InitializeAsync(chainState.BlockStoreTip);

                this.entry.Fee(11);
                this.entry.Height(11);

                var dateTimeProviderSet = new MemoryPoolTests.DateTimeProviderSet
                {
                    time    = dateTimeProvider.GetTime(),
                    timeutc = dateTimeProvider.GetUtcNow()
                };

                this.DateTimeProvider = dateTimeProviderSet;
                this.mempool          = new TxMempool(dateTimeProvider, new BlockPolicyEstimator(new MempoolSettings(nodeSettings), loggerFactory, nodeSettings), loggerFactory, nodeSettings);
                this.mempoolLock      = new MempoolSchedulerLock();

                // We can't make transactions until we have inputs
                // Therefore, load 100 blocks :)
                this.baseheight = 0;
                var blocks = new List <Block>();

                this.txFirst = new List <Transaction>();

                this.nonce = 0;

                for (int i = 0; i < this.blockinfo.Count; ++i)
                {
                    Block block = this.network.CreateBlock();
                    block.Header.HashPrevBlock = this.chain.Tip.HashBlock;
                    block.Header.Version       = 1;
                    block.Header.Time          = Utils.DateTimeToUnixTime(this.chain.Tip.GetMedianTimePast()) + 1;

                    Transaction txCoinbase = this.network.CreateTransaction();
                    txCoinbase.Version = 1;
                    txCoinbase.AddInput(new TxIn(new Script(new[] { Op.GetPushOp(this.blockinfo[i].extranonce), Op.GetPushOp(this.chain.Height) })));
                    // Ignore the (optional) segwit commitment added by CreateNewBlock (as the hardcoded nonces don't account for this)
                    txCoinbase.AddOutput(new TxOut(Money.Zero, new Script()));
                    block.AddTransaction(txCoinbase);

                    if (this.txFirst.Count == 0)
                    {
                        this.baseheight = this.chain.Height;
                    }

                    if (this.txFirst.Count < 4)
                    {
                        this.txFirst.Add(block.Transactions[0]);
                    }

                    block.Header.Bits = block.Header.GetWorkRequired(this.network, this.chain.Tip);

                    block.UpdateMerkleRoot();

                    while (!block.CheckProofOfWork())
                    {
                        block.Header.Nonce = ++this.nonce;
                    }

                    // Serialization sets the BlockSize property.
                    block = Block.Load(block.ToBytes(), this.network);

                    await this.consensus.BlockMinedAsync(block);

                    blocks.Add(block);
                }

                // Just to make sure we can still make simple blocks
                this.newBlock = AssemblerForTest(this).Build(this.chain.Tip, this.scriptPubKey);
                Assert.NotNull(this.newBlock);
            }