private NBitcoin.Target[] CreateTargets(int size) { var array = new NBitcoin.Target[this.size]; for (int i = 0; i < array.Length; i++) { array[i] = new NBitcoin.Target(1); } return(array); }
public Target GetWorkRequired(Network network) { // Genesis block if(Height == 0) return network.Consensus.PowLimit; var nProofOfWorkLimit = network.Consensus.PowLimit; var pindexLast = this.Previous; var height = Height; if(pindexLast == null) return nProofOfWorkLimit; // Only change once per interval if((height) % network.Consensus.DifficultyAdjustmentInterval != 0) { if(network.Consensus.PowAllowMinDifficultyBlocks) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if(this.Header.BlockTime > pindexLast.Header.BlockTime + TimeSpan.FromTicks(network.Consensus.PowTargetSpacing.Ticks * 2)) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block ChainedBlock pindex = pindexLast; while(pindex.Previous != null && (pindex.Height % network.Consensus.DifficultyAdjustmentInterval) != 0 && pindex.Header.Bits == nProofOfWorkLimit) pindex = pindex.Previous; return pindex.Header.Bits; } } return pindexLast.Header.Bits; } // Go back by what we want to be 14 days worth of blocks var pastHeight = pindexLast.Height - (network.Consensus.DifficultyAdjustmentInterval - 1); ChainedBlock pindexFirst = this.EnumerateToGenesis().FirstOrDefault(o => o.Height == pastHeight); assert(pindexFirst); // Limit adjustment step var nActualTimespan = pindexLast.Header.BlockTime - pindexFirst.Header.BlockTime; if(nActualTimespan < TimeSpan.FromTicks(network.Consensus.PowTargetTimespan.Ticks / 4)) nActualTimespan = TimeSpan.FromTicks(network.Consensus.PowTargetTimespan.Ticks / 4); if(nActualTimespan > TimeSpan.FromTicks(network.Consensus.PowTargetTimespan.Ticks * 4)) nActualTimespan = TimeSpan.FromTicks(network.Consensus.PowTargetTimespan.Ticks * 4); // Retarget var bnNew = pindexLast.Header.Bits.ToBigInteger(); bnNew *= (ulong)nActualTimespan.TotalSeconds; bnNew /= (ulong)network.Consensus.PowTargetTimespan.TotalSeconds; var newTarget = new Target(bnNew); if(newTarget > nProofOfWorkLimit) newTarget = nProofOfWorkLimit; return newTarget; }
/// <summary> /// Mines a new genesis block, to use with a new network. /// Typically, 3 such genesis blocks need to be created when bootstrapping a new coin: for Main, Test and Reg networks. /// </summary> /// <param name="consensusFactory"> /// The consensus factory used to create transactions and blocks. /// Use <see cref="PosConsensusFactory"/> for proof-of-stake based networks. /// </param> /// <param name="coinbaseText"> /// Traditionally a news headline from the day of the launch, but could be any string or link. /// This will be inserted in the input coinbase transaction script. /// It should be shorter than 92 characters. /// </param> /// <param name="target"> /// The difficulty target under which the hash of the block need to be. /// Some more details: As an example, the target for the Stratis Main network is 00000fffffffffffffffffffffffffffffffffffffffffffffffffffffffffff. /// To make it harder to mine the genesis block, have more zeros at the beginning (keeping the length the same). This will make the target smaller, so finding a number under it will be more difficult. /// To make it easier to mine the genesis block ,do the opposite. Example of an easy one: 00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff. /// Make the Test and Reg targets ones easier to find than the Main one so that you don't wait too long to mine the genesis block. /// </param> /// <param name="genesisReward"> /// Specify how many coins to put in the genesis transaction's output. These coins are unspendable. /// </param> /// <param name="version"> /// The version of the transaction and the block header set in the genesis block. /// </param> /// <example> /// The following example shows the creation of a genesis block. /// <code> /// Block genesis = MineGenesisBlock(new PosConsensusFactory(), "Some topical headline.", new Target(new uint256("000fffff00000000000000000000000000000000000000000000000000000000")), Money.Coins(50m)); /// BlockHeader header = genesis.Header; /// Console.WriteLine("Make a note of the following values:"); /// Console.WriteLine("bits: " + header.Bits); /// Console.WriteLine("nonce: " + header.Nonce); /// Console.WriteLine("time: " + header.Time); /// Console.WriteLine("version: " + header.Version); /// Console.WriteLine("hash: " + header.GetHash()); /// Console.WriteLine("merkleroot: " + header.HashMerkleRoot); /// </code> /// </example> /// <returns>A genesis block.</returns> public static Block MineGenesisBlock(ConsensusFactory consensusFactory, string coinbaseText, Target target, Money genesisReward, int version = 1) { if (consensusFactory == null) throw new ArgumentException($"Parameter '{nameof(consensusFactory)}' cannot be null. Use 'new ConsensusFactory()' for Bitcoin-like proof-of-work blockchains and 'new PosConsensusFactory()' for Stratis-like proof-of-stake blockchains."); if (string.IsNullOrEmpty(coinbaseText)) throw new ArgumentException($"Parameter '{nameof(coinbaseText)}' cannot be null. Use a news headline or any other appropriate string."); if (target == null) throw new ArgumentException($"Parameter '{nameof(target)}' cannot be null. Example use: new Target(new uint256(\"0000ffff00000000000000000000000000000000000000000000000000000000\"))"); if (coinbaseText.Length >= 92) throw new ArgumentException($"Parameter '{nameof(coinbaseText)}' should be shorter than 92 characters."); if (genesisReward == null) throw new ArgumentException($"Parameter '{nameof(genesisReward)}' cannot be null. Example use: 'Money.Coins(50m)'."); DateTimeOffset time = DateTimeOffset.Now; uint unixTime = Utils.DateTimeToUnixTime(time); Transaction txNew = consensusFactory.CreateTransaction(); txNew.Version = (uint)version; txNew.AddInput(new TxIn() { ScriptSig = new Script( Op.GetPushOp(0), new Op() { Code = (OpcodeType)0x1, PushData = new[] { (byte)42 } }, Op.GetPushOp(Encoders.ASCII.DecodeData(coinbaseText))) }); txNew.AddOutput(new TxOut() { Value = genesisReward, }); Block genesis = consensusFactory.CreateBlock(); genesis.Header.BlockTime = time; genesis.Header.Bits = target; genesis.Header.Nonce = 0; genesis.Header.Version = version; genesis.Transactions.Add(txNew); genesis.Header.HashPrevBlock = uint256.Zero; genesis.UpdateMerkleRoot(); // Iterate over the nonce until the proof-of-work is valid. // This will mean the block header hash is under the target. while (!genesis.CheckProofOfWork()) { genesis.Header.Nonce++; if (genesis.Header.Nonce == 0) genesis.Header.Time++; } return genesis; }
public Target GetWorkRequired(Network network, int height) { if(IsPartial) throw new InvalidOperationException("You can't calculate work on partial chain"); var nProofOfWorkLimit = new Target(network.ProofOfWorkLimit); var pindexLast = height == 0 ? null : GetBlock(height - 1); // Genesis block if(pindexLast == null) return nProofOfWorkLimit; // Only change once per interval if((height) % nInterval != 0) { if(network == Network.TestNet) { // Special difficulty rule for testnet: // If the new block's timestamp is more than 2* 10 minutes // then allow mining of a min-difficulty block. if(DateTimeOffset.UtcNow > pindexLast.Header.BlockTime + TimeSpan.FromTicks(nTargetSpacing.Ticks * 2)) return nProofOfWorkLimit; else { // Return the last non-special-min-difficulty-rules-block ChainedBlock pindex = pindexLast; while(pindex.Previous != null && (pindex.Height % nInterval) != 0 && pindex.Header.Bits == nProofOfWorkLimit) pindex = pindex.Previous; return pindex.Header.Bits; } } return pindexLast.Header.Bits; } // Go back by what we want to be 14 days worth of blocks var pastHeight = pindexLast.Height - nInterval + 1; ChainedBlock pindexFirst = GetBlock((int)pastHeight); assert(pindexFirst); // Limit adjustment step var nActualTimespan = pindexLast.Header.BlockTime - pindexFirst.Header.BlockTime; if(nActualTimespan < TimeSpan.FromTicks(nTargetTimespan.Ticks / 4)) nActualTimespan = TimeSpan.FromTicks(nTargetTimespan.Ticks / 4); if(nActualTimespan > TimeSpan.FromTicks(nTargetTimespan.Ticks * 4)) nActualTimespan = TimeSpan.FromTicks(nTargetTimespan.Ticks * 4); // Retarget var bnNew = pindexLast.Header.Bits.ToBigInteger(); bnNew *= (ulong)nActualTimespan.TotalSeconds; bnNew /= (ulong)nTargetTimespan.TotalSeconds; var newTarget = new Target(bnNew); if(newTarget > nProofOfWorkLimit) newTarget = nProofOfWorkLimit; return newTarget; }