public List <uint256> GenerateBlocks(ReserveScript reserveScript, int generate, int maxTries, bool keepScript)
        {
            // temporary code to mine blocks while doing some simulations
            // this will be refactored to have the same logic as core with regards to
            // selecting and sorting transactions from the mempool.

            if (fullNode.Chain.Tip != fullNode.ConsensusLoop.Tip)
            {
                return(Enumerable.Empty <uint256>().ToList());
            }

            List <Block> blocks = new List <Block>();

            for (int i = 0; i < generate; i++)
            {
                uint  nonce = 0;
                Block block = new Block();
                block.Header.HashPrevBlock = fullNode.Chain.Tip.HashBlock;
                //block.Header.Bits = GetWorkRequired(fullNode.Network.Consensus,new ChainedBlock(block.Header, (uint256) null, fullNode.Chain.Tip));
                block.Header.Bits = block.Header.GetWorkRequired(fullNode.Network, fullNode.Chain.Tip);
                block.Header.UpdateTime(dateTimeProvider.GetTimeOffset(), fullNode.Network, fullNode.Chain.Tip);
                var coinbase = new Transaction();
                coinbase.AddInput(TxIn.CreateCoinbase(fullNode.Chain.Height + 1));
                coinbase.AddOutput(new TxOut(fullNode.Network.GetReward(fullNode.Chain.Height + 1), reserveScript.reserveSfullNodecript));
                block.AddTransaction(coinbase);
                //if (passedTransactions?.Any() ?? false)
                //{
                //	passedTransactions = Reorder(passedTransactions);
                //	block.Transactions.AddRange(passedTransactions);
                //}
                block.UpdateMerkleRoot();
                var retry = 0;
                while (!block.CheckProofOfWork() && !fullNode.IsDisposed && ++retry < maxTries)
                {
                    block.Header.Nonce = ++nonce;
                }
                if (fullNode.IsDisposed || retry >= maxTries)
                {
                    return(blocks.Select(b => b.GetHash()).ToList());
                }
                if (block.Header.HashPrevBlock != fullNode.Chain.Tip.HashBlock)
                {
                    i--;
                    continue;                     // a new block was found continue to look
                }
                blocks.Add(block);
                var newChain = new ChainedBlock(block.Header, block.GetHash(), fullNode.Chain.Tip);
                fullNode.Chain.SetTip(newChain);

                var blockResult = new BlockResult {
                    Block = block
                };
                fullNode.ConsensusLoop.AcceptBlock(blockResult);

                if (blockResult.ChainedBlock == null)
                {
                    break;                     //reorg
                }
                // similar logic to what's in the full node code
                if (blockResult.Error == null)
                {
                    fullNode.ChainBehaviorState.HighestValidatedPoW = fullNode.ConsensusLoop.Tip;
                    //if (fullNode.Chain.Tip.HashBlock == blockResult.ChainedBlock.HashBlock)
                    //{
                    //	var unused = cache.FlushAsync();
                    //}
                    fullNode.Signals.Blocks.Broadcast(block);
                }

                // ensure the block is written to disk
                retry = 0;
                while (++retry < maxTries && this.fullNode.BlockStoreManager.BlockRepository.GetAsync(blockResult.ChainedBlock.HashBlock).GetAwaiter().GetResult() == null)
                {
                    Thread.Sleep(100);
                }
                if (retry >= maxTries)
                {
                    return(blocks.Select(b => b.GetHash()).ToList());
                }
            }

            return(blocks.Select(b => b.GetHash()).ToList());
        }
        public List <uint256> GenerateBlocks(ReserveScript reserveScript, int generate, int maxTries, bool keepScript)
        {
            int nHeightStart = 0;
            int nHeightEnd   = 0;
            int nHeight      = 0;

            nHeightStart = this.chain.Height;
            nHeight      = nHeightStart;
            nHeightEnd   = nHeightStart + generate;
            int nExtraNonce = 0;
            var blocks      = new List <uint256>();

            if (this.chain.Tip != this.consensusLoop.Tip)
            {
                return(blocks);
            }

            while (nHeight < nHeightEnd)
            {
                var pblocktemplate = this.blockAssemblerFactory.Create().CreateNewBlock(reserveScript.reserveSfullNodecript);
                BlockAssembler.IncrementExtraNonce(pblocktemplate.Block, this.chain.Tip, nExtraNonce);
                var pblock = pblocktemplate.Block;

                while (maxTries > 0 && pblock.Header.Nonce < nInnerLoopCount && !pblock.CheckProofOfWork())
                {
                    ++pblock.Header.Nonce;
                    --maxTries;
                }

                if (maxTries == 0)
                {
                    break;
                }

                if (pblock.Header.Nonce == nInnerLoopCount)
                {
                    continue;
                }

                var newChain = new ChainedBlock(pblock.Header, pblock.GetHash(), fullNode.Chain.Tip);
                this.chain.SetTip(newChain);

                var blockResult = new BlockResult {
                    Block = pblock
                };
                fullNode.ConsensusLoop.AcceptBlock(new ContextInformation(blockResult, fullNode.Network.Consensus));

                if (blockResult.ChainedBlock == null)
                {
                    break;                     //reorg
                }
                if (blockResult.Error != null)
                {
                    return(blocks);
                }

                // similar logic to what's in the full node code
                fullNode.ChainBehaviorState.HighestValidatedPoW = fullNode.ConsensusLoop.Tip;
                fullNode.Signals.Blocks.Broadcast(pblock);

                ++nHeight;
                blocks.Add(pblock.GetHash());

                // ensure the block is written to disk
                var retry = 0;
                while (++retry < maxTries &&
                       !this.fullNode.BlockStoreManager.BlockRepository.ExistAsync(blockResult.ChainedBlock.HashBlock).GetAwaiter().GetResult())
                {
                    Thread.Sleep(100);
                }
            }

            return(blocks);
        }
        public List <uint256> GenerateBlocks(ReserveScript reserveScript, ulong generate, ulong maxTries)
        {
            ulong nHeightStart = 0;
            ulong nHeightEnd   = 0;
            ulong nHeight      = 0;

            nHeightStart = (ulong)this.chain.Height;
            nHeight      = nHeightStart;
            nHeightEnd   = nHeightStart + generate;
            int nExtraNonce = 0;
            var blocks      = new List <uint256>();


            // BlockTemplate pblocktemplate = null;

            while (nHeight < nHeightEnd)
            {
                try
                {
                    if (this.chain.Tip != this.consensusLoop.Tip)
                    {
                        Task.Delay(TimeSpan.FromMinutes(1), this.nodeLifetime.ApplicationStopping).GetAwaiter().GetResult();
                        continue;
                    }

                    var pblocktemplate = this.blockAssemblerFactory.Create().CreateNewBlock(reserveScript.reserveSfullNodecript);

                    this.IncrementExtraNonce(pblocktemplate.Block, this.chain.Tip, nExtraNonce);
                    var pblock = pblocktemplate.Block;

                    while (maxTries > 0 && pblock.Header.Nonce < InnerLoopCount && !pblock.CheckProofOfWork())
                    {
                        ++pblock.Header.Nonce;
                        --maxTries;
                    }

                    if (maxTries == 0)
                    {
                        break;
                    }

                    if (pblock.Header.Nonce == InnerLoopCount)
                    {
                        continue;
                    }

                    var newChain = new ChainedBlock(pblock.Header, pblock.GetHash(), this.chain.Tip);

                    if (newChain.ChainWork <= this.chain.Tip.ChainWork)
                    {
                        continue;
                    }

                    this.chain.SetTip(newChain);

                    var blockResult = new BlockResult {
                        Block = pblock
                    };
                    this.consensusLoop.AcceptBlock(new ContextInformation(blockResult, this.network.Consensus));

                    if (blockResult.ChainedBlock == null)
                    {
                        break;                         //reorg
                    }
                    if (blockResult.Error != null)
                    {
                        return(blocks);
                    }

                    // similar logic to what's in the full node code
                    this.chainState.HighestValidatedPoW = this.consensusLoop.Tip;
                    this.signals.Blocks.Broadcast(pblock);

                    Logs.Mining.LogInformation($"Mined new {(BlockStake.IsProofOfStake(blockResult.Block) ? "POS" : "POW")} block: {blockResult.ChainedBlock.HashBlock}");

                    ++nHeight;
                    blocks.Add(pblock.GetHash());

                    // ensure the block is written to disk
                    ulong retry = 0;
                    while (++retry < maxTries &&
                           !this.blockRepository.ExistAsync(blockResult.ChainedBlock.HashBlock).GetAwaiter().GetResult())
                    {
                        Thread.Sleep(100);
                    }

                    pblocktemplate = null;
                }
                catch (ConsensusErrorException cer)
                {
                    if (cer.ConsensusError == ConsensusErrors.InvalidPrevTip)
                    {
                        continue;
                    }

                    throw;
                }
            }

            return(blocks);
        }