Пример #1
0
        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));
        }
Пример #2
0
            }                          // 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;
            }
Пример #3
0
        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++;
                }
            }
        }