static void Main(string[] args) { var time = new DateTime(2020, 10, 31, 1, 50, 0, DateTimeKind.Utc); var tx = BlockchainUtil.CreateCoinBaseTransaction(0, null, time, engrave: "Haloween - ArCana"); tx.TimeStamp = time; var txs = new List <Transaction>() { tx }; var rootHash = HashUtil.ComputeMerkleRootHash(txs.Select(x => x.Id.Bytes).ToList()); var block = new Block() { Id = new HexString("00006D930177AA974CFBA170357D202AEB22BDA7CEA348F93DF9AD9326776843"), PreviousBlockHash = new HexString(""), Nonce = 8528990852057875687, Transactions = null, MerkleRootHash = rootHash, Timestamp = time, Bits = 17, }; //Always True Console.WriteLine(Miner.HashCheck(block.ComputeId(), Difficulty.ToTargetBytes(block.Bits))); Console.WriteLine(block.Id.Equals(block.ComputeId().ToHexString())); }
public void Execute(CancellationToken token) { var txs = BlockchainManager.GetPool(); var time = DateTime.UtcNow; var subsidy = BlockchainManager.GetSubsidy(BlockchainManager.Chain.Count); var txList = txs.Where(tx => { try { token.ThrowIfCancellationRequested(); BlockchainManager.VerifyTransaction(tx, time); subsidy += tx.TransactionFee; return(true); } catch { return(false); } }).ToList(); var cbOut = new Output() { Amount = subsidy, PublicKeyHash = MinerKeyHash.Bytes }; var tb = new TransactionBuilder(new List <Output>() { cbOut }, new List <Input>()); var coinbaseTx = tb.ToTransaction(time); BlockchainManager.VerifyTransaction(coinbaseTx, time, subsidy); txList.Insert(0, coinbaseTx); var txIds = txList.Select(x => x.Id).ToList(); var block = new Block() { PreviousBlockHash = BlockchainManager.Chain.Last().Id, Transactions = txList, MerkleRootHash = HashUtil.ComputeMerkleRootHash(txIds), Bits = Difficulty.DifficultyBits }; if (!Mining(block, token)) { return; } _logger.LogInformation($"Mined"); _logger.LogInformation($"{JsonSerializer.PrettyPrint(JsonSerializer.Serialize(block))}"); //Broadcast Block }
public bool Execute(CancellationToken token, out Block block) { block = null; var txs = TransactionPool.GetPool(); var time = DateTime.UtcNow; var subsidy = BlockchainUtil.GetSubsidy(Blockchain.Chain.Count); var txList = txs.Where(tx => { if (token.IsCancellationRequested || !Blockchain.VerifyTransaction(tx, time, false, out var txFee)) { return(false); } subsidy += txFee; return(true); }).ToList(); var coinbaseOut = new Output() { Amount = subsidy, PublicKeyHash = MinerPublicKeyHash }; var tb = new TransactionBuilder(new List <Output>() { coinbaseOut }, new List <Input>()); var coinbaseTx = tb.ToTransaction(time); if (!Blockchain.VerifyTransaction(coinbaseTx, time, true, out var txFee, subsidy)) { return(false); } txList.Insert(0, coinbaseTx); var txIds = txList.Select(x => x.Id.Bytes).ToList(); var mineBlock = new Block() { Id = null, PreviousBlockHash = Blockchain.Chain.Last().Id, Transactions = null, MerkleRootHash = HashUtil.ComputeMerkleRootHash(txIds), Bits = Blockchain.GetDifficulty() }; if (!Mine(mineBlock, token)) { return(false); } mineBlock.Transactions = txList; block = mineBlock; return(true); }
public static Block MakeBlock(ulong nonce, List <Transaction> transactions) { var merkleHash = HashUtil.ComputeMerkleRootHash(transactions.Select(x => x.Id).ToList()); var lastBlock = JsonSerializer.Serialize(Chain.Last()); return(new Block() { MerkleRootHash = merkleHash, Nonce = nonce, PreviousBlockHash = new HexString(HashUtil.DoubleSHA256(lastBlock)), Timestamp = DateTime.UtcNow, Transactions = transactions }); }
public static Block CreateGenesisBlock() { var time = new DateTime(2020, 10, 31, 1, 50, 0, DateTimeKind.Utc); var tx = CreateCoinBaseTransaction(0, null, time, engrave:"Haloween - ArCana"); tx.TimeStamp = time; var txs = new List<Transaction>() { tx }; var rootHash = HashUtil.ComputeMerkleRootHash(txs.Select(x => x.Id.Bytes).ToList()); return new Block() { Id = new HexString("00006D930177AA974CFBA170357D202AEB22BDA7CEA348F93DF9AD9326776843"), PreviousBlockHash = new HexString(""), Nonce = 8528990852057875687, Transactions = txs, MerkleRootHash = rootHash, Timestamp = time, Bits = 17, }; }
public static Block CreateGenesis() { var tx = CreateCoinBaseTransaction(0, null, "ArC - A Little BlockChain by C#"); tx.TimeStamp = GenesisTime; var txs = new List <Transaction> { tx }; var rootHash = HashUtil.ComputeMerkleRootHash(txs.Select(x => x.Id).ToList()); return(new Block() { PreviousBlockHash = new HexString(""), Nonce = 2083236893, Transactions = txs, MerkleRootHash = rootHash, Timestamp = GenesisTime, Bits = 5 }); }
public void Mining() { var(privateKey, publicKey) = SignManager.GenerateKeys(); var publickKeyHash = new HexString(HashUtil.RIPEMD_SHA256(publicKey)); //Genesis Mining var genesis = BlockchainManager.CreateGenesis(); var miner = new Miner { MinerKeyHash = publickKeyHash }; Console.WriteLine("Mining"); miner.Mining(genesis, Context.CancellationToken); BlockchainManager.Chain.Add(genesis); for (var i = 0; i < 10; i++) { var gg = BlockchainManager.CreateCoinBaseTransaction(i + 1, publickKeyHash.Bytes, $"まかろに{i}"); gg.TimeStamp = DateTime.UtcNow; var txs = new List <Transaction>() { gg }; var rootHash = HashUtil.ComputeMerkleRootHash(txs.Select(x => x.Id).ToList()); var b = new Block() { PreviousBlockHash = BlockchainManager.Chain.Last().Id, Transactions = txs, MerkleRootHash = rootHash, Timestamp = DateTime.UtcNow, Bits = 1 }; miner.Mining(b, Context.CancellationToken); BlockchainManager.Chain.Add(b); Task.Delay(10).GetAwaiter().GetResult(); } //Second Block Mining Console.WriteLine($"{genesis.Transactions.Count}"); var tb = new TransactionBuilder(); var ttx = BlockchainManager.Chain.SelectMany(x => x.Transactions).First(x => x.Engraving == "まかろに0"); var input = new Input() { TransactionId = ttx.Id, OutputIndex = 0, }; var output = new Output() { Amount = 10, PublicKeyHash = publickKeyHash.Bytes }; tb.Inputs.Add(input); tb.Outputs.Add(output); var tx = tb.ToSignedTransaction(privateKey, publicKey); BlockchainManager.TransactionPool.Add(tx); miner.Start(); Console.WriteLine($"{BlockchainManager.VerifyBlockchain()} : OK"); Console.ReadLine(); }
static void Main(string[] args) { var aliceKey = new Key(); var bobKey = new Key(); //Aliceが50コイン所持しているというトランザクションが必要 var coinbaseTx = BlockchainUtil.CreateCoinBaseTransaction(0, aliceKey.PublicKeyHash, engrave: "Alice Coin"); var txBuilder = new TransactionBuilder(); txBuilder.Inputs.Add(new Input() { OutputIndex = 0, TransactionId = coinbaseTx.Id, }); txBuilder.Outputs.Add(new Output() { PublicKeyHash = bobKey.PublicKeyHash, Amount = 10 }); txBuilder.Outputs.Add(new Output() { PublicKeyHash = aliceKey.PublicKeyHash, Amount = 40 }); var tx = txBuilder.ToSignedTransaction(aliceKey.PrivateKey, aliceKey.PublicKey); var hash = tx.GetSignHash(); var input = tx.Inputs[0]; var isAliceTx = Signature.Verify(hash, input.Signature, input.PublicKey, coinbaseTx.Outputs[0].PublicKeyHash); Console.WriteLine($"Is Alice Tx ? : { isAliceTx}"); var preBlock = new Block() { Timestamp = DateTime.UtcNow, Transactions = new List <Transaction>() { coinbaseTx }, Bits = Difficulty.MinDifficultBits }; var block = new Block() { Timestamp = DateTime.UtcNow, Transactions = new List <Transaction>() { tx }, Bits = Difficulty.MinDifficultBits }; preBlock.MerkleRootHash = HashUtil.ComputeMerkleRootHash(preBlock.Transactions); block.MerkleRootHash = HashUtil.ComputeMerkleRootHash(block.Transactions); if (!Miner.Mine(preBlock, CancellationToken.None)) { return; } var blockchain = new Blockchain(); blockchain.BlockVerify(preBlock); var fee = 0ul; foreach (var transaction in block.Transactions) { var isVerified = blockchain.VerifyTransaction(transaction, block.Timestamp, false, out var txFee); if (!isVerified) { return; } fee += txFee; } var noahKey = new Key(); var noahCoinbase = BlockchainUtil.CreateCoinBaseTransaction(blockchain.Chain.Count, noahKey.PublicKeyHash, fee); block.Transactions.Insert(0, noahCoinbase); if (!Miner.Mine(block, CancellationToken.None)) { return; } Console.WriteLine("ブロック追加前----------------"); blockchain.Utxos.ForEach(x => Console.WriteLine($"{x.Output.PublicKeyHash.ToHex()} : {x.Output.Amount}")); //ブロック追加 blockchain.BlockVerify(block); Console.WriteLine("ブロック追加後----------------"); blockchain.Utxos.ForEach(x => Console.WriteLine($"{x.Output.PublicKeyHash.ToHex()} : {x.Output.Amount}")); var inputs = blockchain.Chain .SelectMany(x => x.Transactions) .SelectMany(x => x.Inputs); var outputs = blockchain.Chain .SelectMany(x => x.Transactions) .Select(x => (x.Outputs, x.Id)) .SelectMany(x => ToTxO(x.Outputs, x.Id)); var utxo = outputs.Where(opt => !inputs.Any(ipt => ipt.OutputIndex == opt.OutIndex && ipt.TransactionId.Equals(opt.TransactionId))); var alicePkh = aliceKey.PublicKeyHash; var aliceUtxo = utxo.Select(x => x.Output) .Where(x => x.PublicKeyHash?.SequenceEqual(alicePkh) ?? false) .ToList(); var coinSum = aliceUtxo .Select(x => x.Amount) .Aggregate((a, b) => a + b); Console.WriteLine($"Alice : {coinSum} coin"); //念のためにUTXOを最新にする。 blockchain.UpdateUtxos(); var coinSum2 = blockchain.Utxos .Where(x => x.Output.PublicKeyHash?.SequenceEqual(alicePkh) ?? false) .Select(x => x.Output.Amount) .Aggregate((a, b) => a + b); Console.WriteLine($"Alice : {coinSum2} coin"); var noahCoin = blockchain.Utxos .First(x => x.Output.PublicKeyHash? .SequenceEqual(noahKey.PublicKeyHash) ?? false); var noahInput = new Input() { OutputIndex = noahCoin.OutIndex, TransactionId = noahCoin.TransactionId }; var noahAmount = noahCoin.Output.Amount; var toAliceOutput = new Output() { PublicKeyHash = alicePkh, Amount = noahAmount / 2 }; var toNoahOutput = new Output() { PublicKeyHash = noahKey.PublicKeyHash, Amount = noahAmount - toAliceOutput.Amount }; var tb = new TransactionBuilder(); tb.Inputs.Add(noahInput); tb.Outputs.Add(toAliceOutput); tb.Outputs.Add(toNoahOutput); var noahTx = tb.ToSignedTransaction(noahKey.PrivateKey, noahKey.PublicKey); var node1 = new Server(new CancellationTokenSource()); var node2 = new Server(new CancellationTokenSource()); node1.StartAsync(50001).GetAwaiter().GetResult(); node2.StartAsync(50002).GetAwaiter().GetResult(); node2.MessageReceived += async(msg, ip) => { var newTx = JsonSerializer.Deserialize <NewTransaction>(msg.Payload).Transaction; Console.WriteLine($"New Transaction! : {newTx.Id.String}"); }; var localhost = IPAddress.Parse("127.0.0.1"); var txMessage = new NewTransaction() { Transaction = noahTx }; txMessage.ToMessage() .SendAsync(localhost, 50002, 50001).GetAwaiter().GetResult(); Console.ReadKey(); var target = Difficulty.ToTargetBytes(1); Console.WriteLine(target.ToHex()); byte[] data; ulong nonce = 0; do { data = HashUtil.DoubleSHA256Hash(BitConverter.GetBytes(nonce++)); Console.WriteLine(data.ToHex()); } while (!Miner.HashCheck(data, target)); var aliceNm = new NetworkManager(CancellationToken.None); var bobNm = new NetworkManager(CancellationToken.None); aliceNm.StartServerAsync(50005).GetAwaiter().GetResult(); bobNm.StartServerAsync(50006).GetAwaiter().GetResult(); }