예제 #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 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;
                    }
                }
            }
        }