/// <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); }
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); } }
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; } } } }