예제 #1
0
 //public CTemporaryBlock(CBlock Block, CPeer Sender) : base(Block.Header.BlockNumber, Block.Header.Hash, Block.Header.PreviousBlockHash, Block.Transiction, Block.Nonce, Block.Timestamp, Block.Difficulty)
 public CTemporaryBlock(CBlock Block, CPeer Sender) : base(Block.Header.BlockNumber, Block.Header.Hash, Block.Header.PreviousBlockHash, Block.TxLimit, Block.Nonce, Block.Timestamp, Block.Difficulty, Block.Transactions)
 {
     this.Nonce     = Block.Nonce;
     this.Timestamp = Block.Timestamp;
     mSender        = Sender;
     { }
 }
예제 #2
0
        /// <summary>
        /// Aggiunge il proof of work(l'hash) al blocco.
        /// </summary>
        /// <param name="Block">Blocco su cui calcolare il proof of work.</param>
        public static void AddProof(CBlock Block) //TODO: implementare evento per l'uscita in caso sia stato trovato un blocco parallelo. Implementare multithreading
        {
            string hash  = "";
            bool   found = false;

            while (!found)
            {
                Block.Timestamp = DateTime.Now;
                Block.Nonce++;            //incremento della nonce per cambiare hash
                hash  = HashBlock(Block); //calcola l'hash secondo il template di scrypt usato da litecoin
                found = true;
                for (int i = 0; i < Block.Difficulty && found; i++)
                {
                    if (hash[i] != '0')
                    {
                        found = false;
                    }
                }
            }
            if (Program.DEBUG)
            {
                CIO.DebugOut("Found hash for block " + Block.Header.BlockNumber + ": " + hash);
            }
            Block.Header.Hash = hash;
        }
예제 #3
0
        /// <summary>
        /// Aggiunge i blocchi presenti nel vettore e ritorna l'indice dell'ultimo blocco aggiunto.
        /// </summary>
        /// <param name="Blocks"></param>
        /// <returns></returns>
        public ulong Add(CTemporaryBlock[] Blocks)
        {
            ulong  counter  = 0;
            string filepath = PATH + "\\" + FILENAME;

            //(!) e se scarico tutta la blockchain e da un certo punto in poi sbagliata?
            foreach (CTemporaryBlock b in Blocks)
            {
                if (b == null)
                {
                    break;
                }

                if (CValidator.ValidateBlock(b, true))
                {
                    if (b.Header.BlockNumber == LastValidBlock.Header.BlockNumber)
                    {
                        break;
                    }
                    mLastValidBlock = b as CBlock;
                    counter++;
                    lock (Instance)
                    {
                        MemPool.Instance.RemoveBlock(b);
                        UTXOManager.Instance.ApplyBlock(b);
                        File.AppendAllText(filepath, (b as CBlock).Serialize() + '\n');
                    }
                }
                else
                {
                    break;
                }
            }
            return(counter);
        }
예제 #4
0
        /// <summary>
        /// Carica l'ultimo blocco della blockchain.
        /// </summary>
        private void Load()
        {
            string filepath = PATH + "\\" + FILENAME;
            string block    = "";

            mLastValidBlock = new CGenesisBlock();
            if (File.Exists(filepath))
            {
                StreamReader streamReader = new StreamReader(filepath);
                while ((block = streamReader.ReadLine()) != null)
                {
                    CBlock b = JsonConvert.DeserializeObject <CBlock>(block);
                    if (b.Header.BlockNumber > mLastValidBlock.Header.BlockNumber)
                    {
                        mLastValidBlock = b;
                    }
                }
                streamReader.Close();
            }
            else
            {
                File.WriteAllText(filepath, new CGenesisBlock().Serialize() + '\n');
                mLastValidBlock = new CGenesisBlock();
            }
        }
예제 #5
0
        public CBlock RetriveBlock(ulong index, bool searchInSidechain = false)
        {
            string filepath  = PATH + "\\" + FILENAME;
            string blockJson = "";

            lock (Instance)
            {
                StreamReader streamReader = new StreamReader(filepath);
                while ((blockJson = streamReader.ReadLine()) != null)
                {
                    CBlock block = JsonConvert.DeserializeObject <CBlock>(blockJson);
                    if (block.Header.BlockNumber == index)
                    {
                        streamReader.Close();
                        return(block);
                    }
                }
                streamReader.Close();
            }
            if (searchInSidechain)
            {
                lock (mSideChain)
                    if (LastBlock.Header.BlockNumber >= index)
                    {
                        return(mSideChain.RetriveBlock(index));
                    }
            }

            return(null);
        }
예제 #6
0
        private CHeaderChain[] FindParallelChains(CBlock startBlock)
        {
            CHeader tmp1, tmp2;
            Stack <CHeaderChain> res = new Stack <CHeaderChain>();
            int ID = 0;

            for (int i = 0; i < Peers.Length; i++)
            {
                if (Peers[i] != null)
                {
                    ID   = Peers[i].SendRequest(new CMessage(EMessageType.Request, ERequestType.GetLastHeader));
                    tmp1 = Peers[i].ReceiveHeader(ID, 5000);
                    res.Push(new CHeaderChain());
                    res.Peek().AddPeer(Peers[i]);
                    res.Peek().FinalIndex = tmp1.BlockNumber;
                    Peers[i] = null;
                    for (int j = i + 1; j < Peers.Length; j++)
                    {
                        ID   = Peers[j].SendRequest(new CMessage(EMessageType.Request, ERequestType.GetLastHeader));
                        tmp2 = Peers[j].ReceiveHeader(ID, 5000);
                        if (tmp1.Hash == tmp2.Hash)
                        {
                            res.Peek().AddPeer(Peers[j]);
                            Peers[j] = null;
                        }
                    }
                }
            }
            return(res.ToArray());
        }
예제 #7
0
        private static CBlock GenerateNextBlock(int txLimit)
        {
            short newBlockDifficulty = Miner.CalculateDifficulty();

            CBlock res = new CBlock(CBlockChain.Instance.LastBlock.Header.BlockNumber + 1, CBlockChain.Instance.LastBlock.Header.Hash, (ushort)newBlockDifficulty, 10);

            Console.WriteLine("Address: {0}", Utilities.Base64SHA2Hash(RSA.ExportPubKey(CServer.rsaKeyPair)));
            return(res);
        }
예제 #8
0
        /// <summary>
        /// Esegue una richiesta ai peer collegati.
        /// </summary>
        /// <param name="rqs">Richiesta da effettuare.</param>
        /// <param name="arg">Parametro usato per passare un valore e/o ritornare un risultato quando necessario.</param>
        /// <returns></returns>
        public object DoRequest(ERequest rqs, object arg = null)  //(!) rivedere i metodi di input/output del metodo
        {
            switch (rqs)
            {
            case ERequest.UpdatePeers:
            {
                UpdatePeers();
                break;
            }

            case ERequest.LastValidBlock:
            {
                return(RequestLastValidBlock());
            }

            case ERequest.DownloadMissingBlock:
            {
                object[] args          = arg as object[];
                ulong    startingIndex = Convert.ToUInt64(args[0]);
                ulong    finalIndex    = Convert.ToUInt64(args[1]);
                return(DistribuiteDownloadBlocks(startingIndex, finalIndex));
            }

            case ERequest.BroadcastMinedBlock:
            {
                CBlock b = arg as CBlock;
                foreach (CPeer p in Peers)
                {
                    p.SendRequest(new CMessage(EMessageType.Request, ERequestType.NewBlockMined, EDataType.Block, b.Serialize()));
                }
                break;
            }

            case ERequest.LastCommonValidBlock:
            {
                return(FindLastCommonBlocks());
            }

            case ERequest.FindParallelChain:
            {
                return(FindParallelChains(arg as CBlock));
            }

            case ERequest.BroadcastNewTransaction:
            {
                foreach (CPeer p in Peers)
                {
                    p.SendRequest(new CMessage(EMessageType.Request, ERequestType.NewTransaction, EDataType.Transaction, JsonConvert.SerializeObject(arg as Transaction)));         //TODO : implementa richiesta di invio transazione
                }
                break;
            }

            default:
                throw new ArgumentException("Invalid request: " + rqs);
            }
            return(null);
        }
예제 #9
0
        public static string HashBlock(CBlock block)
        {
            string toHash = block.Header.PreviousBlockHash + block.Nonce + block.Timestamp + block.MerkleRoot; //si concatenano vari parametri del blocco TODO: usare i parmetri giusti, quelli usati qua sono solo per dimostrazione e placeholder

            return(Utilities.ByteArrayToHexString(
                       SCrypt.ComputeDerivedKey(
                           Encoding.ASCII.GetBytes(toHash), Encoding.ASCII.GetBytes(toHash), 1024, 1, 1, 1, 32)
                       )); //calcola l'hash secondo il template di scrypt usato da litecoin
        }
예제 #10
0
 /// <summary>
 /// Inserisce le transazioni di un dato blocco nella mempool
 /// </summary>
 /// <param name="block">Il blocco da inserire</param>
 public void DumpBlock(CBlock block)
 {
     foreach (Transaction tx in block.Transactions)
     {
         if (!(tx.inputs.Count == 0))
         {
             this.AddUTX(tx);
         }
     }
 }
예제 #11
0
 /// <summary>
 /// Rimuove dalla mempool tutte le transazioni contenute in un blocco dato
 /// </summary>
 /// <param name="block"></param>
 public void RemoveBlock(CBlock block)
 {
     foreach (Transaction tx in block.Transactions)
     {
         if (this.CheckDouble(tx))
         {
             this.RemoveUTX(tx.Hash);
         }
     }
 }
예제 #12
0
 /// <summary>
 /// Calcola l'hash di un blocco e lo confronta al proof of work fornito per verificarne la validità
 /// </summary>
 /// <param name="block">Il blocco da confermare</param>
 /// <returns></returns>
 public static bool Verify(CBlock block)
 {
     if (block.Header.PreviousBlockHash == CBlockChain.Instance.RetriveBlock(block.Header.BlockNumber - 1).Header.Hash)
     {
         string toHash = block.Header.PreviousBlockHash + block.Nonce + block.Timestamp + block.MerkleRoot;
         if (block.Header.Hash == Utilities.ByteArrayToHexString(SCrypt.ComputeDerivedKey(Encoding.ASCII.GetBytes(toHash), Encoding.ASCII.GetBytes(toHash), 1024, 1, 1, 1, 32)))
         {
             return(true);
         }
     }
     return(false);
 }
예제 #13
0
        public CBlock[] RetriveBlocks(ulong initialIndex, ulong finalIndex)
        {
            CBlock[] ris = new CBlock[finalIndex - initialIndex];
            int      c   = 0;

            while (initialIndex < finalIndex)
            {
                ris[c++] = RetriveBlock(initialIndex);
                initialIndex++;
            }
            return(ris);
        }
예제 #14
0
        public ulong AverageBlockTime(CBlock start, CBlock final)
        {
            TimeSpan timespan = final.Timestamp.Subtract(start.Timestamp);
            ulong    seconds  = (ulong)timespan.TotalSeconds;
            ulong    nblock   = final.Header.BlockNumber - start.Header.BlockNumber;

            try
            {
                return(seconds / nblock);
            }
            catch
            {
                return(60);
            }
        }
예제 #15
0
 ///<summary>
 ///Dato un blocco, rimuove tutti gli UTXO dal disco in base agli input contenuti, poi crea nuovi UTXO in base agli output
 ///</summary>
 public void ApplyBlock(CBlock block)
 {
     foreach (Transaction tx in block.Transactions)
     {
         if (tx.inputs != null)
         {
             foreach (Input input in tx.inputs)
             {
                 if (input.OutputIndex != -1)
                 {
                     this.RemoveUTXO(Utilities.Base64SHA2Hash(tx.PubKey), input.TxHash, input.OutputIndex);
                 }
             }
         }
         this.AddUTXO(new UTXO(tx.Hash, tx.outputs));
     }
 }
예제 #16
0
        public static bool ValidateBlock(CBlock block, bool CheckPreviusHash = false)
        {
            int coinbaseTx = 0;

            //TODO IMPORTANTE: aggiungere verifica timestamp
            if (block.Header.Hash != Miner.HashBlock(block))
            {
                return(false);
            }
            if (CheckPreviusHash)
            {
                if (CBlockChain.Instance.RetriveBlock(block.Header.BlockNumber - 1)?.Header.Hash != block.Header.PreviousBlockHash)
                {
                    return(false);
                }
            }

            /*
             * if (block.Difficulty < Miner.CalculateDifficulty() - 1 || block.Difficulty > Miner.CalculateDifficulty() + 1)
             * {
             *  return false;
             *
             * }
             */

            if (block.MerkleRoot != block.GenerateMerkleRoot())
            {
                return(false);
            }
            foreach (Transaction tx in block.Transactions)
            {
                if (!tx.Verify())
                {
                    if (coinbaseTx == 0 && tx.inputs.Count == 1 && tx.inputs.First().TxHash == "0" && tx.inputs.First().OutputIndex == -1)
                    {
                        coinbaseTx++;
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
예제 #17
0
        private static bool ValidateRequest(CMessage Msg)
        {
            switch (Msg.RqsType)
            {
            case ERequestType.UpdPeers:
            {
                if (Msg.DataType == EDataType.NULL && Msg.Data == null)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            case ERequestType.NewBlockMined:
            {
                if (Msg.DataType == EDataType.Block && Msg.Data != null)
                {
                    try
                    {
                        CBlock.Deserialize(Msg.Data);
                        return(true);
                    }
                    catch
                    {
                        return(false);
                    }
                }
                else
                {
                    return(false);
                }
            }

            case ERequestType.ChainLength:
            {
                if (Msg.DataType == EDataType.NULL && Msg.Data == null)
                {
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            case ERequestType.GetHeader:
            {
                if (Msg.DataType == EDataType.ULong)
                {
                    try { Convert.ToInt64(Msg.Data); }
                    catch { return(false); }
                    return(true);
                }
                else
                {
                    return(false);
                }
            }

            case ERequestType.GetLastHeader:
            {
                {
                    if (Msg.DataType == EDataType.NULL && Msg.Data == null)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            case ERequestType.GetLastValid:
            {
                {
                    if (Msg.DataType == EDataType.NULL && Msg.Data == null)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }

            case ERequestType.DownloadBlock:
            {
                if (Msg.DataType == EDataType.ULong && Msg.Data != null)
                {
                    try
                    {
                        Convert.ToUInt64(Msg.Data);
                        return(true);
                    }
                    catch { return(false); }
                }
                return(false);
            }

            case ERequestType.DownloadBlocks:
            {
                if (Msg.DataType == EDataType.ULongList && Msg.Data != null)
                {
                    try
                    {
                        string[] stringToConvert = Msg.Data.Split(';');
                        if (stringToConvert.Length != 2)
                        {
                            return(false);
                        }
                        foreach (string s in stringToConvert)
                        {
                            Convert.ToUInt64(s);
                        }
                        return(true);
                    }
                    catch { return(false); }
                }
                return(false);
            }

            case ERequestType.DownloadHeaders:
            {
                if (Msg.DataType == EDataType.ULongList && Msg.Data != null)
                {
                    try
                    {
                        string[] stringToConvert = Msg.Data.Split(';');
                        if (stringToConvert.Length != 2)
                        {
                            return(false);
                        }
                        foreach (string s in stringToConvert)
                        {
                            Convert.ToUInt64(s);
                        }
                        return(true);
                    }
                    catch { return(false); }
                }
                return(false);
            }

            case ERequestType.NewTransaction:
            {
                if (Msg.DataType == EDataType.Transaction && Msg.Data != null)
                {
                    try
                    {
                        Transaction t = JsonConvert.DeserializeObject <Transaction>(Msg.Data);
                        if (MemPool.Instance.CheckDouble(t))
                        {
                            return(false);
                        }
                        if (MemPool.Instance.CheckDoubleSpending(t))
                        {
                            return(false);
                        }
                        if (CBlockChain.Instance.SideChain.CheckDouble(t))
                        {
                            return(false);
                        }
                        MemPool.Instance.AddUTX(t);
                        return(true);
                    }
                    catch { return(false); }
                }
                return(false);
            }

            default:
                return(false);
            }
        }
예제 #18
0
        private void ExecuteRequest()
        {
            CMessage rqs;

            while (mIsConnected)
            {
                Thread.Sleep(100);

                if (RequestQueue.Count > 0)
                {
                    rqs = RequestQueue.Dequeue();
                    switch (rqs.RqsType)
                    {
                    case ERequestType.UpdPeers:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("UpdPeers received by " + mIp);
                        }
                        //(!) è meglio farsi ritornare la lista e poi usare json?
                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.PeersList,
                                                 CPeers.Instance.PeersList(), rqs.ID));
                        break;
                    }

                    case ERequestType.NewBlockMined:
                    {
                        if (CPeers.Instance.CanReceiveBlock)
                        {
                            if (Program.DEBUG)
                            {
                                CIO.DebugOut("NewBlockMined received by " + mIp);
                            }

                            CTemporaryBlock newBlock = new CTemporaryBlock(CBlock.Deserialize(rqs.Data), this);
                            if (!CValidator.ValidateBlock(newBlock) && newBlock.Header.BlockNumber < CBlockChain.Instance.LastValidBlock.Header.BlockNumber)
                            {
                                Disconnect();
                                break;
                            }
                            //TODO scaricare i blocchi mancanti se ne mancano(sono al blocco 10 e mi arriva il blocco 50)
                            if (!CBlockChain.Instance.AddNewMinedBlock(newBlock))
                            {
                                Stack <CTemporaryBlock> blocks = new Stack <CTemporaryBlock>();
                                int ID = 0;
                                blocks.Push(newBlock);
                                for (ulong i = newBlock.Header.BlockNumber - 1; i > CBlockChain.Instance.LastValidBlock.Header.BlockNumber; i--)
                                {
                                    ID = SendRequest(new CMessage(EMessageType.Request, ERequestType.DownloadBlock, EDataType.ULong, Convert.ToString(i)));
                                    blocks.Push(new CTemporaryBlock(JsonConvert.DeserializeObject <CBlock>(ReceiveData(ID, 5000).Data), this));
                                    if (!CValidator.ValidateBlock(blocks.Peek()) && blocks.Peek().Header.BlockNumber < CBlockChain.Instance.LastValidBlock.Header.BlockNumber)
                                    {
                                        Disconnect();
                                        break;
                                    }
                                    if (CBlockChain.Instance.AddNewMinedBlock(blocks.Peek()))
                                    {
                                        blocks.Pop();
                                        for (int j = blocks.Count; j > 0; j--)
                                        {
                                            CBlockChain.Instance.AddNewMinedBlock(blocks.Pop());
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    }

                    case ERequestType.GetLastHeader:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("GetLastHeader received by " + mIp);
                        }
                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.Header,
                                                 JsonConvert.SerializeObject(CBlockChain.Instance.LastValidBlock.Header), rqs.ID));
                        break;
                    }

                    case ERequestType.ChainLength:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("ChainLength received by " + mIp);
                        }
                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.ULong,
                                                 Convert.ToString(CBlockChain.Instance.LastValidBlock.Header.BlockNumber), rqs.ID));
                        break;
                    }

                    case ERequestType.GetLastValid:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("GetLastValid received by " + mIp);
                        }
                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.Block,
                                                 CBlockChain.Instance.LastValidBlock.Serialize(), rqs.ID));
                        break;
                    }

                    case ERequestType.DownloadBlock:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("DownloadBlock received by " + mIp);
                        }

                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.Block,
                                                 JsonConvert.SerializeObject(CBlockChain.Instance.RetriveBlock(Convert.ToUInt64(rqs.Data), true)), rqs.ID));
                        break;
                    }

                    case ERequestType.DownloadBlocks:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("DownloadBlocks received by " + mIp);
                        }

                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.BlockList,
                                                 JsonConvert.SerializeObject(CBlockChain.Instance.RetriveBlocks(Convert.ToUInt64(rqs.Data.Split(';')[0]), Convert.ToUInt64(rqs.Data.Split(';')[1]))), rqs.ID));
                        break;
                    }

                    case ERequestType.DownloadHeaders:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("DownloadBlocks received by " + mIp);
                        }

                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.HeaderList,
                                                 JsonConvert.SerializeObject(CBlockChain.Instance.RetriveHeaders(Convert.ToUInt64(rqs.Data.Split(';')[0]), Convert.ToUInt64(rqs.Data.Split(';')[1]))), rqs.ID));
                        break;
                    }

                    case ERequestType.GetHeader:
                    {
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("GetLastHeader received by " + mIp);
                        }
                        SendRequest(new CMessage(EMessageType.Data, ERequestType.NULL, EDataType.Header,
                                                 JsonConvert.SerializeObject(CBlockChain.Instance.RetriveBlock(Convert.ToUInt64(rqs.Data)).Header), rqs.ID));
                        break;
                    }

                    case ERequestType.NewTransaction:
                    {
                        Transaction t = JsonConvert.DeserializeObject <Transaction>(rqs.Data);
                        if (t.Verify())
                        {
                            MemPool.Instance.AddUTX(t);
                        }
                        break;
                    }

                    default:
                        if (Program.DEBUG)
                        {
                            CIO.DebugOut("Ricevuto comando sconosciuto: " + rqs.RqsType + " da " + IP);
                        }
                        break;
                    }
                }
            }
        }
예제 #19
0
        private static bool ValidateData(CMessage Msg)
        {
            if (Msg.RqsType != ERequestType.NULL)
            {
                return(false);
            }
            switch (Msg.DataType)
            {
            case EDataType.PeersList:
                try
                {
                    string[] peers = Msg.Data.Split(';');
                    foreach (string rp in peers)
                    {
                        CPeer.Deserialize(rp);
                    }
                    return(true);
                }
                catch
                {
                    return(false);
                }

            case EDataType.Block:
                try
                {
                    CBlock.Deserialize(Msg.Data);
                    return(true);
                }
                catch
                {
                    return(false);
                }

            case EDataType.ULong:
                try
                {
                    Convert.ToUInt64(Msg.Data);
                    return(true);
                }
                catch
                {
                    return(false);
                }

            case EDataType.ULongList:
                try
                {
                    JsonConvert.DeserializeObject <ulong[]>(Msg.Data);
                    return(true);
                }
                catch
                {
                    return(false);
                }

            case EDataType.Header:
                try
                {
                    JsonConvert.DeserializeObject <CHeader>(Msg.Data);
                    return(true);
                }
                catch
                {
                    return(false);
                }

            case EDataType.BlockList:
                try
                {
                    JsonConvert.DeserializeObject <CBlock[]>(Msg.Data);
                    return(true);
                }
                catch
                {
                    return(false);
                }

            case EDataType.HeaderList:
                try
                {
                    JsonConvert.DeserializeObject <CHeader[]>(Msg.Data);
                    return(true);
                }
                catch
                {
                    return(false);
                }

            default:
                return(false);
            }
        }
예제 #20
0
        public static short CalculateDifficulty()
        {
            int numberOfBlocks = 300;

            CBlock lastBlock = CBlockChain.Instance.LastBlock;
            CBlock previousBlock;
            short  newBlockDifficulty = 0;
            ulong  highAverangeTimeLimit = 70, lowAverangeTimeLimit = 30;
            ulong  averangeBlockTime = 0;

            if (lastBlock.Header.BlockNumber > (ulong)numberOfBlocks)
            {
                previousBlock = CBlockChain.Instance.RetriveBlock(lastBlock.Header.BlockNumber - (ulong)numberOfBlocks, true);
            }
            else
            {
                previousBlock = CBlockChain.Instance.RetriveBlock(1, true);
            }

            if (previousBlock != null)
            {
                averangeBlockTime = CBlockChain.Instance.AverageBlockTime(previousBlock, lastBlock); //in secondi
            }
            else
            {
                averangeBlockTime = 60;
            }


            if (averangeBlockTime > highAverangeTimeLimit)
            {
                newBlockDifficulty = (short)(lastBlock.Difficulty - 1);
                if (newBlockDifficulty <= 0)
                {
                    newBlockDifficulty = 1;
                }
                if (Program.DEBUG)
                {
                    CIO.DebugOut("La nuova difficoltà è: " + newBlockDifficulty);
                    //Thread.Sleep(1000);
                }
            }
            else if (averangeBlockTime < lowAverangeTimeLimit)
            {
                newBlockDifficulty = (short)(lastBlock.Difficulty + 1);


                if (newBlockDifficulty >= 4)
                {
                    newBlockDifficulty = 4;
                }


                if (Program.DEBUG)
                {
                    CIO.DebugOut("La nuova difficoltà è: " + newBlockDifficulty);
                    //Thread.Sleep(1000);
                }
            }
            else
            {
                newBlockDifficulty = (short)lastBlock.Difficulty;
                if (Program.DEBUG)
                {
                    CIO.DebugOut("La nuova difficoltà è: " + newBlockDifficulty);
                    //Thread.Sleep(1000);
                }
            }
            return(3);
        }
예제 #21
0
        private CBlock FindLastCommonBlocks()
        {
            ulong           minLength = ulong.MaxValue, tmp = 0;
            int             rqsID   = 0;
            bool            found   = false;
            Stack <CHeader> headers = new Stack <CHeader>();
            CBlock          res     = null;

            foreach (CPeer p in Peers)
            {
                try
                {
                    rqsID = p.SendRequest(new CMessage(EMessageType.Request, ERequestType.ChainLength));
                    tmp   = p.ReceiveULong(rqsID, 5000);
                    if (tmp < minLength)
                    {
                        minLength = tmp;
                    }
                }
                catch (SocketException)
                { }
                p.Socket.ReceiveTimeout = 0;
            }
            CRange r = new CRange(CBlockChain.Instance.LastValidBlock.Header.BlockNumber, minLength);

            if (r.End != ulong.MaxValue && r.Start < r.End)
            {
                //trova l'ultimo blocco uguale tra i peer e salva l'indice di quel blocco in r.start
                int ID = 0;
                while (r.Start < r.End)
                {
                    found = true;
                    tmp   = (r.Start + r.End) / 2;
                    if (r.End - r.Start == 1)
                    {
                        tmp++;
                    }
                    foreach (CPeer p in Peers)
                    {
                        ID = p.SendRequest(new CMessage(EMessageType.Request, ERequestType.GetHeader, EDataType.ULong, Convert.ToString(tmp)));
                        headers.Push(p.ReceiveHeader(ID, 5000));
                    }
                    while (headers.Count > 1 && found)
                    {
                        if (!(headers?.Pop().Hash == headers?.Peek().Hash))
                        {
                            found = false;
                        }
                    }
                    if (headers.Count == 1)
                    {
                        headers.Pop();
                    }
                    //se tutti i blocchi sono uguali allora found=true, mentre se ce n'è qualcuno di diverso found=false
                    if (found)
                    {
                        r.Start = tmp;
                    }
                    else if (!(r.End - r.Start == 1))
                    {
                        r.End = tmp;
                    }
                    else
                    {
                        r.End--;
                    }
                }

                //controlla se l'ultimo blocco è valido?
                foreach (CPeer p in Peers)
                {
                    ID  = p.SendRequest(new CMessage(EMessageType.Request, ERequestType.DownloadBlock, EDataType.ULong, Convert.ToString(r.Start)));
                    res = p.ReceiveBlock(ID, 5000);

                    if (res != null && CValidator.ValidateBlock(res))
                    {
                        break;
                    }
                    else
                    {
                        p.Disconnect();
                    }
                    p.Socket.ReceiveTimeout = 0;
                }

                return(res);
            }
            else
            {
                return(CBlockChain.Instance.LastValidBlock);
            }
        }