Пример #1
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);
        }
Пример #2
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);
            }
        }
Пример #3
0
        private void UpdateBlockchain()
        {
            bool  isSynced    = false;
            ulong addedBlocks = 0;

            CTemporaryBlock[] DownloadedBlock;
            CTemporaryBlock[] newBlocks;
            CHeaderChain[]    forkChains;
            CHeaderChain      bestChain;
            CBlock            lastCommonBlock;
            CTemporaryBlock   otherLastValidBlock;

            lastCommonBlock     = mPeers.DoRequest(ERequest.LastCommonValidBlock) as CBlock;    //trova l'utlimo blocco comune tra i peers
            otherLastValidBlock = mPeers.DoRequest(ERequest.LastValidBlock) as CTemporaryBlock; //trova l'ultimo blocco valido tra i peer

            if (Program.DEBUG)
            {
                if (otherLastValidBlock != null)
                {
                    CIO.DebugOut("Il numero di blocco di otherLastValidBlock è " + otherLastValidBlock.Header.BlockNumber + ".");
                }
                else
                {
                    CIO.DebugOut("Nessun otherLastValidBlock ricevuto.");
                }
            }

            if (CBlockChain.Instance.LastValidBlock.Header.BlockNumber < otherLastValidBlock?.Header.BlockNumber)
            {
                isSynced = false;
            }
            else if (otherLastValidBlock != null && CBlockChain.Instance.RetriveBlock(otherLastValidBlock.Header.BlockNumber).Header.Hash == otherLastValidBlock.Header.Hash)
            {
                isSynced = true;
            }
            else if (otherLastValidBlock != null)
            {
                isSynced = true;
                otherLastValidBlock.Sender.Disconnect();
            }
            else
            {
                isSynced = true;
            }


            //TODO potrebbero dover essere scaricati un numero maggiore di MAXINT blocchi
            while (!isSynced)
            {
                newBlocks = mPeers.DoRequest(ERequest.DownloadMissingBlock, new object[] { CBlockChain.Instance.LastValidBlock.Header.BlockNumber + 1, lastCommonBlock.Header.BlockNumber + 1 }) as CTemporaryBlock[];

                /*foreach (CTemporaryBlock block in newBlocks)
                 * {
                 *  UTXOManager.Instance.ApplyBlock(block);
                 * }*/
                CBlockChain.Instance.Add(newBlocks);
                forkChains = mPeers.DoRequest(ERequest.FindParallelChain, lastCommonBlock) as CHeaderChain[];
                if (forkChains.Length > 0)
                {
                    foreach (CHeaderChain hc in forkChains)
                    {
                        hc.DownloadHeaders();
                    }
                    bestChain = CBlockChain.Instance.BestChain(forkChains);
                    if (CValidator.ValidateHeaderChain(bestChain))
                    {
                        DownloadedBlock = CPeers.Instance.DistribuiteDownloadBlocks(bestChain.InitialIndex + 1, bestChain.FinalIndex);

                        /*foreach(CTemporaryBlock block in DownloadedBlock)
                         * {
                         *  UTXOManager.Instance.ApplyBlock(block);
                         * }*/
                        mPeers.ValidPeers(bestChain.Peers);
                        addedBlocks = CBlockChain.Instance.Add(DownloadedBlock);
                        if (addedBlocks >= bestChain.Length)    //solo se scarica tutti i blocchi
                        {
                            isSynced = true;
                        }
                    }
                    else
                    {
                        mPeers.InvalidPeers(bestChain.Peers);
                        otherLastValidBlock = mPeers.DoRequest(ERequest.LastValidBlock) as CTemporaryBlock;
                        lastCommonBlock     = mPeers.DoRequest(ERequest.LastCommonValidBlock) as CTemporaryBlock;
                    }
                }
            }
            if (Program.DEBUG)
            {
                CIO.DebugOut("Sincronizzazione Blockchain terminata!");
            }
            mPeers.CanReceiveBlock = true;
        }
Пример #4
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;
                    }
                }
            }
        }
Пример #5
0
        /// <summary>
        /// Rimane in attesa di messaggi dal peer a cui è collegato il socket mSocket.
        /// </summary>
        private void Listen()
        {
            string   tmp;
            CMessage msg;

            while (mIsConnected)    //bisogna bloccarlo in qualche modo all'uscita del programma credo
            {
                lock (mSocket)
                {
                    if (mSocket == null)
                    {
                        break;
                    }
                    //il timer viene settato cosicchè in caso non si ricevino comunicazioni venga ritornata un'eccezione, in modo che il programma vada avanti e tolga il lock al socket.
                    mSocket.ReceiveTimeout = 1000;
                    try
                    {
                        tmp = ReceiveString();
                        msg = JsonConvert.DeserializeObject <CMessage>(tmp);
                        if (CValidator.ValidateMessage(msg))
                        {
                            msg.TimeOfReceipt = DateTime.Now;
                            if (msg.Type == EMessageType.Request)
                            {
                                lock (RequestQueue)
                                {
                                    RequestQueue.Enqueue(msg);
                                }
                            }
                            else if (msg.Type == EMessageType.Data && ValidID.Contains(msg.ID))
                            {
                                lock (DataQueue)
                                {
                                    DataQueue.Enqueue(msg);
                                    ValidID.Remove(msg.ID);
                                }
                            }
                            else if (msg.Type == EMessageType.Disconnect)
                            {
                                this.Disconnect();
                                break;
                            }
                            else if (Program.DEBUG)
                            {
                                throw new ArgumentException("MessageType " + msg.Type + " non supportato.");
                            }
                        }
                        else
                        {
                            Disconnect();
                            break;
                        }
                    }
                    catch (SocketException)
                    {
                    }
                    catch (JsonSerializationException)
                    {
                        throw new Exception();
                        Disconnect();
                    }
                    //il timer viene reinpostato a defoult per non causare problemi con altre comunicazioni che potrebbero avvenire in altre parti del codice.
                    mSocket.ReceiveTimeout = 0;
                }
            }
        }