public MineBlockContext(ulong amountOfBlocksToMine, ulong chainHeight, ulong maxTries, ReserveScript reserveScript) { this.amountOfBlocksToMine = amountOfBlocksToMine; this.ChainHeight = chainHeight; this.CurrentHeight = chainHeight; this.MaxTries = maxTries; this.ReserveScript = reserveScript; }
///<inheritdoc/> public List <uint256> GenerateBlocks(ReserveScript reserveScript, ulong amountOfBlocksToMine, ulong maxTries) { var context = new MineBlockContext(amountOfBlocksToMine, (ulong)this.chain.Height, maxTries, reserveScript); while (context.MiningCanContinue) { if (!this.ConsensusIsAtTip(context)) { continue; } if (!this.BuildBlock(context)) { continue; } if (!this.MineBlock(context)) { break; } if (!this.ValidateMinedBlock(context)) { continue; } if (!this.ValidateAndConnectBlock(context)) { break; } if (!this.CheckValidationContextPreviousTip(context)) { continue; } this.OnBlockMined(context); } return(context.Blocks); }
/// <summary> /// Generates up to a specified number of blocks with a limited number of attempts. /// </summary> /// <param name="reserveScript"></param> /// <param name="generate">Number of blocks to generate. It is possible that less than the required number of blocks will be mined.</param> /// <param name="maxTries">Maximum number of attempts the miner will calculate PoW hash in order to find suitable ones to generate specified amount of blocks.</param> /// <returns>List with generated block's hashes</returns> 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>(); while (nHeight < nHeightEnd) { this.nodeLifetime.ApplicationStopping.ThrowIfCancellationRequested(); ChainedBlock chainTip = this.consensusLoop.Tip; if (this.chain.Tip != chainTip) { Task.Delay(TimeSpan.FromMinutes(1), this.nodeLifetime.ApplicationStopping).GetAwaiter().GetResult(); continue; } BlockTemplate pblockTemplate = this.blockAssemblerFactory.Create(chainTip).CreateNewBlock(reserveScript.reserveSfullNodecript); if (Block.BlockSignature) { // Make sure the POS consensus rules are valid. This is required for generation of blocks inside tests, // where it is possible to generate multiple blocks within one second. if (pblockTemplate.Block.Header.Time <= chainTip.Header.Time) { continue; } } this.IncrementExtraNonce(pblockTemplate.Block, chainTip, nExtraNonce); Block pblock = pblockTemplate.Block; while ((maxTries > 0) && (pblock.Header.Nonce < InnerLoopCount) && !pblock.CheckProofOfWork()) { this.nodeLifetime.ApplicationStopping.ThrowIfCancellationRequested(); ++pblock.Header.Nonce; --maxTries; } if (maxTries == 0) { break; } if (pblock.Header.Nonce == InnerLoopCount) { continue; } var newChain = new ChainedBlock(pblock.Header, pblock.GetHash(), chainTip); if (newChain.ChainWork <= chainTip.ChainWork) { continue; } var blockValidationContext = new BlockValidationContext { Block = pblock }; this.consensusLoop.AcceptBlockAsync(blockValidationContext).GetAwaiter().GetResult(); if (blockValidationContext.ChainedBlock == null) { this.logger.LogTrace("(-)[REORG-2]"); return(blocks); } if (blockValidationContext.Error != null) { if (blockValidationContext.Error == ConsensusErrors.InvalidPrevTip) { continue; } this.logger.LogTrace("(-)[ACCEPT_BLOCK_ERROR]"); return(blocks); } this.logger.LogInformation("Mined new {0} block: '{1}'.", BlockStake.IsProofOfStake(blockValidationContext.Block) ? "POS" : "POW", blockValidationContext.ChainedBlock); nHeight++; blocks.Add(pblock.GetHash()); pblockTemplate = null; } 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); this.logger.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 && nHeight == nHeightEnd && // last block !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); }
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>(); while (nHeight < nHeightEnd) { this.nodeLifetime.ApplicationStopping.ThrowIfCancellationRequested(); try { ChainedBlock chainTip = this.consensusLoop.Tip; if (this.chain.Tip != chainTip) { Task.Delay(TimeSpan.FromMinutes(1), this.nodeLifetime.ApplicationStopping).GetAwaiter().GetResult(); continue; } BlockTemplate pblockTemplate = this.blockAssemblerFactory.Create(chainTip).CreateNewBlock(reserveScript.reserveSfullNodecript); if (Block.BlockSignature) { // POS: make sure the POS consensus rules are valid if (pblockTemplate.Block.Header.Time <= chainTip.Header.Time) { continue; } } this.IncrementExtraNonce(pblockTemplate.Block, chainTip, nExtraNonce); Block pblock = pblockTemplate.Block; while ((maxTries > 0) && (pblock.Header.Nonce < InnerLoopCount) && !pblock.CheckProofOfWork()) { this.nodeLifetime.ApplicationStopping.ThrowIfCancellationRequested(); ++pblock.Header.Nonce; --maxTries; } if (maxTries == 0) { break; } if (pblock.Header.Nonce == InnerLoopCount) { continue; } var newChain = new ChainedBlock(pblock.Header, pblock.GetHash(), chainTip); if (newChain.ChainWork <= chainTip.ChainWork) { continue; } this.chain.SetTip(newChain); var blockResult = new BlockResult { Block = pblock }; this.consensusLoop.AcceptBlock(new ContextInformation(blockResult, this.network.Consensus)); this.consensusLoop.Puller.SetLocation(newChain); if (blockResult.ChainedBlock == null) { break; // Reorg. } if (blockResult.Error != null) { return(blocks); } // Push the block to disk, so it is available when peers ask for it. this.blockRepository.PutAsync(blockResult.ChainedBlock.HashBlock, new List <Block> { pblock }).GetAwaiter().GetResult(); // Similar logic to what's in the full node code. this.chainState.HighestValidatedPoW = this.consensusLoop.Tip; this.signals.SignalBlock(pblock); this.logger.LogInformation("Mined new {0} block: '{1}'.", BlockStake.IsProofOfStake(blockResult.Block) ? "POS" : "POW", blockResult.ChainedBlock); nHeight++; blocks.Add(pblock.GetHash()); pblockTemplate = null; } catch (ConsensusErrorException cer) { if (cer.ConsensusError == ConsensusErrors.InvalidPrevTip) { continue; } throw; } } return(blocks); }