From 8009545b4086da725b21d61e1a4968b76bf53a61 Mon Sep 17 00:00:00 2001 From: Jeremy Bokobza Date: Fri, 7 Dec 2018 12:35:46 +0000 Subject: [PATCH] Setup of FederatedPegTest (#221) * Use SmartContractPoAConsensusFactory for genesis block generation * No genesis reward for sidechains * Find (real) Genesis Block for FederatedPegTest * Increase Console input limit * Use RegTest for the local sidechain network * Add mining FedPubKeys and additional network fields * updtae to ports to be like Stratis+1 * Update FederatedPegTest.cs * premine reward back to 20 000 000 * Update FederatedPegTest.cs --- GenesisMiner.cs | 91 +++++++++++++++++++++++++++++++++++++++++-------- Program.cs | 8 ++++- 2 files changed, 84 insertions(+), 15 deletions(-) diff --git a/GenesisMiner.cs b/GenesisMiner.cs index fc284dec759..8189d87ff56 100644 --- a/GenesisMiner.cs +++ b/GenesisMiner.cs @@ -2,7 +2,8 @@ using System.Collections.Generic; using System.Text; using NBitcoin; -using Stratis.Bitcoin.Features.PoA; +using NBitcoin.DataEncoders; +using Stratis.Bitcoin.Features.SmartContracts.PoA; using Xunit; using Xunit.Abstractions; @@ -22,12 +23,12 @@ public GenesisMiner(ITestOutputHelper output = null) [Fact(Skip = "This is not a test, it is meant to be run upon creating a network")] public void Run_MineGenesis() { - var consensusFactory = new PoAConsensusFactory(); + var consensusFactory = new SmartContractPoAConsensusFactory(); string coinbaseText = "https://www.coindesk.com/apple-co-founder-backs-dorsey-bitcoin-become-webs-currency/"; this.output.WriteLine(this.MineGenesisBlocks(consensusFactory, coinbaseText)); } - public string MineGenesisBlocks(ConsensusFactory consensusFactory, string coinbaseText) + public string MineGenesisBlocks(SmartContractPoAConsensusFactory consensusFactory, string coinbaseText) { var output = new StringBuilder(); @@ -41,38 +42,100 @@ public string MineGenesisBlocks(ConsensusFactory consensusFactory, string coinba { new uint256("7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"), "-- RegTest network --" } }; - BlockHeader header = null; - foreach (KeyValuePair target in targets) { - header = this.GeneterateBlock(consensusFactory, coinbaseText, target.Key); - output.AppendLine(this.NetworkOutput(header, target.Value)); + Block genesisBlock = this.GeneterateBlock(consensusFactory, coinbaseText, target.Key); + output.AppendLine(this.NetworkOutput(genesisBlock, target.Value, coinbaseText)); } return output.ToString(); } - private BlockHeader GeneterateBlock(ConsensusFactory consensusFactory, string coinbaseText, uint256 target) + private Block GeneterateBlock(SmartContractPoAConsensusFactory consensusFactory, string coinbaseText, uint256 target) { - Block genesis = Network.MineGenesisBlock(consensusFactory, coinbaseText, new Target(target), Money.Coins(50m)); - - return genesis.Header; + return MineGenesisBlock(consensusFactory, coinbaseText, new Target(target), Money.Zero); } - private string NetworkOutput(BlockHeader header, string network) + private string NetworkOutput(Block genesisBlock, string network, string coinbaseText) { - var output = new StringBuilder(); + SmartContractPoABlockHeader header = (SmartContractPoABlockHeader) genesisBlock.Header; + var output = new StringBuilder(); output.AppendLine(network); output.AppendLine("bits: " + header.Bits); output.AppendLine("nonce: " + header.Nonce); output.AppendLine("time: " + header.Time); output.AppendLine("version: " + header.Version); - output.AppendLine("hash: " + header.GetHash()); + output.AppendLine("hash: " + genesisBlock.GetHash()); output.AppendLine("merkleroot: " + header.HashMerkleRoot); + output.AppendLine("coinbase text: " + coinbaseText); + output.AppendLine("hash state root: " + header.HashStateRoot); output.AppendLine(Environment.NewLine); return output.ToString(); } + + public static Block MineGenesisBlock(SmartContractPoAConsensusFactory 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.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(); + + ((SmartContractPoABlockHeader)genesis.Header).HashStateRoot = new uint256("21B463E3B52F6201C0AD6C991BE0485B6EF8C092E64583FFA655CC1B171FE856"); // Set StateRoot to empty trie. + + // 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; + } } } \ No newline at end of file diff --git a/Program.cs b/Program.cs index acacdb1d5c3..961f404711c 100644 --- a/Program.cs +++ b/Program.cs @@ -6,6 +6,7 @@ using NBitcoin.DataEncoders; using Stratis.Bitcoin.Configuration; using Stratis.Bitcoin.Features.PoA; +using Stratis.Bitcoin.Features.SmartContracts.PoA; using Stratis.Bitcoin.Networks; using Stratis.Sidechains.Networks; @@ -27,6 +28,11 @@ class Program static void Main(string[] args) { + Console.SetIn(new StreamReader(Console.OpenStandardInput(), + Console.InputEncoding, + false, + bufferSize: 1024)); + // Start with the banner and the help message. FederationSetup.OutputHeader(); FederationSetup.OutputMenu(); @@ -79,7 +85,7 @@ static void Main(string[] args) if (string.IsNullOrEmpty(text)) throw new ArgumentException("Please specify the text to be included in the genesis block."); - Console.WriteLine(new GenesisMiner().MineGenesisBlocks(new PoAConsensusFactory(), text)); + Console.WriteLine(new GenesisMiner().MineGenesisBlocks(new SmartContractPoAConsensusFactory(), text)); FederationSetup.OutputSuccess(); }