public static NBitcoin.Block CreateGenesis(ConsensusFactory consensusFactory, uint genesisTime, uint nonce, uint bits, int version, Money reward) { string timeStamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; var genesisOutputScript = new Script(Op.GetPushOp(Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f")), OpcodeType.OP_CHECKSIG); NBitcoin.Transaction genesisTransaction = consensusFactory.CreateTransaction(); genesisTransaction.Version = 1; genesisTransaction.AddInput(new TxIn() { ScriptSig = new Script(Op.GetPushOp(486604799), new Op() { Code = (OpcodeType)0x1, PushData = new[] { (byte)4 } }, Op.GetPushOp(Encoders.ASCII.DecodeData(timeStamp))) }); genesisTransaction.AddOutput(new TxOut() { Value = reward, ScriptPubKey = genesisOutputScript }); NBitcoin.Block genesis = consensusFactory.CreateBlock(); genesis.Header.BlockTime = Utils.UnixTimeToDateTime(genesisTime); genesis.Header.Bits = bits; genesis.Header.Nonce = nonce; genesis.Header.Version = version; genesis.Transactions.Add(genesisTransaction); genesis.Header.HashPrevBlock = uint256.Zero; genesis.UpdateMerkleRoot(); ((ISmartContractBlockHeader)genesis.Header).HashStateRoot = SmartContractBlockDefinition.StateRootEmptyTrie; return(genesis); }
protected virtual Transaction CreateOutputTransaction() { var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); var tx = new Transaction(); // Distribute funds to configured reward recipients var rewardRecipients = new List <RewardRecipient>(poolConfig.RewardRecipients); foreach (var recipient in rewardRecipients.Where(x => x.Type != RewardRecipientType.Dev && x.Percentage > 0)) { var recipientAddress = BitcoinUtils.AddressToScript(recipient.Address); var recipientReward = new Money((long)Math.Floor(recipient.Percentage / 100.0m * blockReward.Satoshi)); rewardToPool -= recipientReward; tx.AddOutput(recipientReward, recipientAddress); } // Finally distribute remaining funds to pool tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination) { Value = rewardToPool }); // validate it //var checkResult = tx.Check(); //Debug.Assert(checkResult == TransactionCheckResult.Success); return(tx); }
protected virtual Money CreateMasternodeOutputs(Transaction tx, Money reward) { if (masterNodeParameters.Masternode != null && masterNodeParameters.SuperBlocks != null) { if (!string.IsNullOrEmpty(masterNodeParameters.Masternode.Payee)) { var payeeAddress = BitcoinUtils.AddressToDestination(masterNodeParameters.Masternode.Payee); var payeeReward = masterNodeParameters.Masternode.Amount; reward -= payeeReward; rewardToPool -= payeeReward; tx.AddOutput(payeeReward, payeeAddress); } else if (masterNodeParameters.SuperBlocks.Length > 0) { foreach (var superBlock in masterNodeParameters.SuperBlocks) { var payeeAddress = BitcoinUtils.AddressToDestination(superBlock.Payee); var payeeReward = superBlock.Amount; reward -= payeeReward; rewardToPool -= payeeReward; tx.AddOutput(payeeReward, payeeAddress); } } } if (!string.IsNullOrEmpty(masterNodeParameters.Payee)) { var payeeAddress = BitcoinUtils.AddressToDestination(masterNodeParameters.Payee); var payeeReward = masterNodeParameters.PayeeAmount ?? (reward / 5); reward -= payeeReward; rewardToPool -= payeeReward; tx.AddOutput(payeeReward, payeeAddress); } return(reward); }
protected override Transaction CreateOutputTransaction() { rewardToPool = new Money(BlockTemplate.CoinbaseValue * blockRewardMultiplier, MoneyUnit.Satoshi); var tx = new Transaction(); // pool reward (t-addr) tx.AddOutput(rewardToPool, poolAddressDestination); return(tx); }
protected override Transaction CreateOutputTransaction() { rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); var tx = new Transaction(); // pool reward (t-addr) var amount = new Money(blockReward + rewardFees, MoneyUnit.Satoshi); tx.AddOutput(amount, poolAddressDestination); return(tx); }
protected virtual Transaction CreateOutputTransaction() { var blockReward = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); rewardToPool = new Money(BlockTemplate.CoinbaseValue, MoneyUnit.Satoshi); var tx = new Transaction(); // Distribute funds to configured reward recipients var rewardRecipients = new List <RewardRecipient>(poolConfig.RewardRecipients); // Tiny donation to MiningCore developer(s) if (!clusterConfig.DisableDevDonation && networkType == BitcoinNetworkType.Main && KnownAddresses.DevFeeAddresses.ContainsKey(poolConfig.Coin.Type)) { rewardRecipients.Add(new RewardRecipient { Address = KnownAddresses.DevFeeAddresses[poolConfig.Coin.Type], Percentage = 0.2m }); } foreach (var recipient in rewardRecipients.Where(x => x.Percentage > 0)) { var recipientAddress = BitcoinUtils.AddressToScript(recipient.Address); var recipientReward = new Money((long)Math.Floor(recipient.Percentage / 100.0m * blockReward.Satoshi)); rewardToPool -= recipientReward; tx.AddOutput(recipientReward, recipientAddress); } // Finally distribute remaining funds to pool tx.Outputs.Insert(0, new TxOut(rewardToPool, poolAddressDestination) { Value = rewardToPool }); // validate it //var checkResult = tx.Check(); //Debug.Assert(checkResult == TransactionCheckResult.Success); return(tx); }
public static NBitcoin.Block CreateGenesis(ConsensusFactory consensusFactory, uint genesisTime, uint nonce, uint bits, int version, Money reward) { string timeStamp = "The Times 03/Jan/2009 Chancellor on brink of second bailout for banks"; var genesisOutputScript = new Script(Op.GetPushOp(Encoders.Hex.DecodeData("04678afdb0fe5548271967f1a67130b7105cd6a828e03909a67962e0ea1f61deb649f6bc3f4cef38c4f35504e51ec112de5c384df7ba0b8d578a4c702b6bf11d5f")), OpcodeType.OP_CHECKSIG); NBitcoin.Transaction genesisTransaction = consensusFactory.CreateTransaction(); // TODO: Similar potential problem to Cirrus genesis definition if (genesisTransaction is IPosTransactionWithTime posTx) { posTx.Time = genesisTime; } genesisTransaction.Version = 1; genesisTransaction.AddInput(new TxIn() { ScriptSig = new Script(Op.GetPushOp(486604799), new Op() { Code = (OpcodeType)0x1, PushData = new[] { (byte)4 } }, Op.GetPushOp(Encoders.ASCII.DecodeData(timeStamp))) }); genesisTransaction.AddOutput(new TxOut() { Value = reward, ScriptPubKey = genesisOutputScript }); NBitcoin.Block genesis = consensusFactory.CreateBlock(); genesis.Header.BlockTime = Utils.UnixTimeToDateTime(genesisTime); genesis.Header.Bits = bits; genesis.Header.Nonce = nonce; genesis.Header.Version = version; genesis.Transactions.Add(genesisTransaction); genesis.Header.HashPrevBlock = uint256.Zero; genesis.UpdateMerkleRoot(); ((SmartContractBlockHeader)genesis.Header).HashStateRoot = new uint256("21B463E3B52F6201C0AD6C991BE0485B6EF8C092E64583FFA655CC1B171FE856"); return(genesis); }
/// <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 (target == null) { throw new ArgumentException($"Parameter '{nameof(target)}' cannot be null. Example use: new Target(new uint256(\"0000ffff00000000000000000000000000000000000000000000000000000000\"))"); } 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 (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.Time = unixTime; 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 Transaction CreateSend(BitcoinAddress bitcoinAddress, Money value) { if(bitcoinAddress.Network != Network) throw new InvalidOperationException("This bitcoin address does not belong to the network"); Transaction tx = new Transaction(); tx.AddOutput(value, bitcoinAddress); this.CompleteTx(tx); return tx; }
public bool CompleteTx(Transaction tx, Money fees, Account pool = null) { pool = pool ?? Accounts.Available; var entries = pool.GetEntriesToCover(tx.TotalOut + fees, false); if(entries == null) return false; foreach(var entry in entries) { tx.AddInput(new TxIn(entry.OutPoint)); } var surplus = entries.Sum(i => i.TxOut.Value) - fees - tx.TotalOut; if(surplus != Money.Zero) tx.AddOutput(surplus, GetKey().PubKey.ID); for(int i = 0 ; i < entries.Length ; i++) { var entry = entries[i]; var vin = tx.Inputs[i]; var key = GetKey(entry.TxOut.ScriptPubKey.GetDestination()); tx.Inputs[i].ScriptSig = new PayToPubkeyHashTemplate().GenerateScriptPubKey(key.PubKey); var hash = tx.Inputs[i].ScriptSig.SignatureHash(tx, i, SigHash.All); var sig = key.Sign(hash); tx.Inputs[i].ScriptSig = new PayToPubkeyHashTemplate().GenerateScriptSig(new TransactionSignature(sig, SigHash.All), key.PubKey); } return true; }