public static byte[] MinerTokenToBytes(MinerToken mt) { List <byte> Databuilder = new List <byte>(); Databuilder = AddBytesToList(Databuilder, mt.MinerPKEY); Databuilder = AddBytesToList(Databuilder, BitConverter.GetBytes(mt.mUTXOP)); Databuilder = AddBytesToList(Databuilder, BitConverter.GetBytes(mt.MiningReward)); return(ListToByteArray(Databuilder)); }
} // 4 o public Block(uint index, byte[] hash, byte[] ph, List <Tx> data, uint ts, MinerToken mt, byte[] hashtarget, uint nonce) { this.Index = index; this.Hash = hash; this.previousHash = ph; this.Data = data; this.TimeStamp = ts; this.minerToken = mt; this.HashTarget = hashtarget; this.Nonce = nonce; this.DataSize = (uint)data.Count; }
public static string MineBlock(List <Tx> TXS, Block prevBlock, byte[] pKey, uint mUTXOP, string WinBlockPath, uint clock_limit) { // Merkle root is build like this : index + ph + datasize + tx + timestamp + minertoken + hashtarget uint unixTimestamp = (uint)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds; List <byte> dataBuilder = new List <byte>(); dataBuilder = AddBytesToList(dataBuilder, BitConverter.GetBytes(prevBlock.Index + 1)); dataBuilder = AddBytesToList(dataBuilder, prevBlock.Hash); dataBuilder = AddBytesToList(dataBuilder, BitConverter.GetBytes((uint)TXS.Count)); uint sum = 0; foreach (Tx TX in TXS) { dataBuilder = AddBytesToList(dataBuilder, TxToBytes(TX)); sum += TX.TxFee; } dataBuilder = AddBytesToList(dataBuilder, BitConverter.GetBytes(unixTimestamp)); uint currentMiningReward = GetMiningReward(prevBlock.Index + 1); uint MR = sum + currentMiningReward; MinerToken MT = new MinerToken(pKey, mUTXOP, MR); dataBuilder = AddBytesToList(dataBuilder, MinerTokenToBytes(MT)); byte[] HASH_TARGET; if (isNewTargetRequired(prevBlock.Index + 1)) //< will compute with the new hash target { Block earlier; if (RequestLatestBlockIndex(true) >= prevBlock.Index + 1 - TARGET_CLOCK) { earlier = GetBlockAtIndex(prevBlock.Index + 1 - TARGET_CLOCK); if (earlier == null) { Console.WriteLine("previous block was null during mining proccess."); return(""); } } else { earlier = GetBlockAtIndexInFile(prevBlock.Index + 1 - TARGET_CLOCK, WinBlockPath); if (earlier == null) { Console.WriteLine("previous block was null during mining proccess."); return(""); } } HASH_TARGET = ComputeHashTargetB(prevBlock, earlier); } else { HASH_TARGET = prevBlock.HashTarget; } dataBuilder = AddBytesToList(dataBuilder, HASH_TARGET); byte[] CLEAN_HASH_TARGET = HASH_TARGET; float water_level = Tidal.GetTidalAtSpecificTime(unixTimestamp); HASH_TARGET = ApplyTheSeaToTheCryptoPuzzle(HASH_TARGET, water_level); byte[] sha = ComputeSHA256(ListToByteArray(dataBuilder)); sha = ComputeSHA256(sha); //< double hash function to avoid collision or anniversary attack byte[] nonceByte = new byte[4]; Random rd = new Random(); rd.NextBytes(nonceByte); uint nonce = BitConverter.ToUInt32(nonceByte, 0); //uint nonce = 0; // on va dire que c'est un random uint entre 0 et uint.maxvalue Stopwatch sw = new Stopwatch(); sw.Start(); Stopwatch sw2 = new Stopwatch(); sw2.Start(); uint trycounter = 0; while (true) { List <byte> Databuilder = new List <byte>(); Databuilder = AddBytesToList(Databuilder, BitConverter.GetBytes(nonce)); Databuilder = AddBytesToList(Databuilder, sha); byte[] hash = ListToByteArray(Databuilder); hash = ComputeSHA256(hash); if (isNonceGolden(hash, HASH_TARGET)) { Print("[CONGRATS] YOU MINED A BLOCK!!"); Block WinnerBlock = new Block(prevBlock.Index + 1, sha, prevBlock.Hash, TXS, unixTimestamp, MT, CLEAN_HASH_TARGET, nonce); // reapply hash to the stuff PrintBlockData(WinnerBlock); Console.WriteLine("will write at " + WinBlockPath); arduino.SendTick("5"); // go sing the coucou arduino.HashToClock(hash); if (File.Exists(WinBlockPath)) { Console.WriteLine("will write a new fi le at " + WinBlockPath); OverWriteBytesInFile(0, WinBlockPath, BitConverter.GetBytes(WinnerBlock.Index)); AppendBytesToFile(WinBlockPath, BlockToBytes(WinnerBlock)); } else { Console.WriteLine("append bytes at " + WinBlockPath); File.WriteAllBytes(WinBlockPath, BitConverter.GetBytes(WinnerBlock.Index)); AppendBytesToFile(WinBlockPath, BlockToBytes(WinnerBlock)); } Console.WriteLine("shoud have write at " + WinBlockPath); UpdatePendingTXFile(WinnerBlock); return(WinBlockPath); } else { if (sw.Elapsed.Seconds > 5) { Console.WriteLine("______________________________________"); Console.WriteLine(" [Mining report] "); Console.WriteLine("total attempts : " + trycounter); Console.WriteLine("last hash produced :" + SHAToHex(hash, false)); Console.WriteLine("index : " + (prevBlock.Index + 1).ToString()); Console.WriteLine("previous hash : " + SHAToHex(prevBlock.Hash, false)); Console.WriteLine("hash target : " + SHAToHex(HASH_TARGET, false)); Console.WriteLine("water level : " + water_level); Console.WriteLine("______________________________________"); sw.Restart(); } if (sw2.Elapsed.Seconds > clock_limit) { Console.WriteLine("Mining time limit reached. Mining aborted for this specific new block. "); return(""); } if (nonce == uint.MaxValue) { rd.NextBytes(nonceByte); nonce = BitConverter.ToUInt32(nonceByte, 0); } trycounter++; nonce++; } } }