Beispiel #1
0
 public Task Sync()
 {
     return(Task.Run(async() => {
         Log += "syncing..." + Environment.NewLine;
         OnLogChanged();
         while (true)
         {
             var(index, node) = Nodes.Aggregate((index: BlockChain.Last().Index, node: (Uri)null), (m, n) =>
                                                Task.Run(async() => {
                 HttpResponseMessage response;
                 try {
                     response = await httpClient_.PostAsync(n, new StringContent(JsonConvert.SerializeObject(
                                                                                     new GetCurrentIndex {
                         PortNumber = PortNumber
                     })));
                 } catch (HttpRequestException) {
                     return m;
                 }
                 if (!response.IsSuccessStatusCode)
                 {
                     return m;
                 }
                 var res = JsonConvert.DeserializeObject <GetCurrentIndexResponse>(await response.Content.ReadAsStringAsync());
                 if (res.CurrentIndex <= m.index)
                 {
                     return m;
                 }
                 return (index: res.CurrentIndex, node: n);
             }).Result);
             if (node == null)
             {
                 break;
             }
             if (index > BlockChain.Last().Index)
             {
                 IList <Block> branch;
                 var currentIndex = BlockChain.Last().Index;
                 {
                     HttpResponseMessage response;
                     try {
                         response = await httpClient_.PostAsync(node, new StringContent(JsonConvert.SerializeObject(
                                                                                            new GetBlocks {
                             Index = currentIndex + 1, NumBlocks = index - currentIndex
                         })));
                     } catch (HttpRequestException) {
                         continue;
                     }
                     if (!response.IsSuccessStatusCode)
                     {
                         continue;
                     }
                     var res = JsonConvert.DeserializeObject <GetBlocksResponse>(await response.Content.ReadAsStringAsync());
                     branch = res.Blocks;
                 }
                 if (branch.First().PreviousHash == LastHash)
                 {
                     var removed = false;
                     foreach (var block in branch)
                     {
                         foreach (var transaction in block.Transactions)
                         {
                             if (TransactionPool.Contains(transaction))
                             {
                                 TransactionPool.Remove(transaction);
                                 removed = true;
                             }
                         }
                     }
                     if (removed)
                     {
                         OnTransactionPoolChanged();
                     }
                     BlockChain.AddRange(branch);
                     break;
                 }
                 while (true)
                 {
                     HttpResponseMessage response;
                     try {
                         response = await httpClient_.PostAsync(node, new StringContent(JsonConvert.SerializeObject(
                                                                                            new GetBlocks {
                             Index = currentIndex, NumBlocks = 1
                         })));
                     } catch (HttpRequestException) {
                         goto con;
                     }
                     if (!response.IsSuccessStatusCode)
                     {
                         goto con;
                     }
                     var res = JsonConvert.DeserializeObject <GetBlocksResponse>(await response.Content.ReadAsStringAsync());
                     branch.Insert(0, res.Blocks.First());
                     if (BlockChain[currentIndex].PreviousHash == branch.First().PreviousHash)
                     {
                         break;
                     }
                     --currentIndex;
                 }
                 BlockChain.RemoveRange(currentIndex, BlockChain.Count - currentIndex);
                 var removed2 = false;
                 foreach (var block in branch)
                 {
                     foreach (var transaction in block.Transactions)
                     {
                         if (TransactionPool.Contains(transaction))
                         {
                             TransactionPool.Remove(transaction);
                             removed2 = true;
                         }
                     }
                 }
                 if (removed2)
                 {
                     OnTransactionPoolChanged();
                 }
                 BlockChain.AddRange(branch);
                 break;
             }
             con:;
         }
         LastHash = SerializeHash(GetHash(BlockChain.Last()));
         OnBlockChainChanged();
         Log += "sync completed." + Environment.NewLine;
         OnLogChanged();
     }));
 }
Beispiel #2
0
        public Node()
        {
            if (File.Exists(ConfigFileName))
            {
                string s;
                using (var sr = new StreamReader(ConfigFileName, Encoding)) {
                    s = sr.ReadToEnd();
                }
                var config = JsonConvert.DeserializeObject <Config>(s);
                PortNumber = config.PortNumber;
                Nodes      = config.Nodes ?? new HashSet <Uri>();
            }

            BlockChain.Add(GetGenesisBlock());
            LastHash = SerializeHash(GetHash(BlockChain.Last()));

            httpListener_.Prefixes.Add($"http://+:{PortNumber}/");
            httpListener_.Start();

            Task.Run(() => {
                while (true)
                {
                    var context = httpListener_.GetContext();
                    void respond()
                    {
                        context.Response.StatusCode = (int)HttpStatusCode.BadRequest;
                        context.Response.OutputStream.Close();
                    }
                    string requestString;
                    using (var sr = new StreamReader(context.Request.InputStream)) {
                        requestString = sr.ReadToEnd();
                    }
                    Log += $"request get: {requestString}{Environment.NewLine}";
                    OnLogChanged();
                    JObject requestJObject;
                    try {
                        requestJObject = JObject.Parse(requestString);
                    } catch (JsonReaderException) {
                        respond();
                        continue;
                    }
                    if (!requestJObject.ContainsKey("Matcha") || requestJObject["Matcha"].Type != JTokenType.String ||
                        requestJObject["Matcha"].Value <string>() != "Matcha")
                    {
                        respond();
                        continue;
                    }
                    var client = new Uri($"http://{context.Request.RemoteEndPoint.Address}"
                                         + $":{requestJObject["PortNumber"].Value<int>()}/");
                    Nodes.Add(client);
                    var response        = context.Response;
                    response.StatusCode = 200;
                    using (var sw = new StreamWriter(response.OutputStream, Encoding)) {
                        switch (requestJObject["Type"].Value <string>())
                        {
                        case nameof(Methods.GetNodes): {
                            var nodes = new HashSet <Uri>(Nodes);
                            nodes.Remove(client);
                            sw.Write(JsonConvert.SerializeObject(new GetNodesResponse {
                                    Nodes = nodes
                                }));
                            break;
                        }

                        case nameof(SendTransaction): {
                            var request = requestJObject.ToObject <SendTransaction>();
                            if (!TransactionPool.Contains(request.Transaction))
                            {
                                TransactionPool.Add(request.Transaction);
                                OnTransactionPoolChanged();
                            }
                            break;
                        }

                        case nameof(GetCurrentIndex): {
                            sw.Write(JsonConvert.SerializeObject(new GetCurrentIndexResponse {
                                    CurrentIndex = BlockChain.Last().Index
                                }));
                            break;
                        }

                        case nameof(GetBlocks): {
                            var request = requestJObject.ToObject <GetBlocks>();
                            sw.Write(JsonConvert.SerializeObject(new GetBlocksResponse {
                                    Blocks = BlockChain.Skip(request.Index).Take(request.NumBlocks).ToList()
                                }));
                            break;
                        }
                        }
                    }
                }
            });
        }
Beispiel #3
0
 public async Task <bool> Contains(Domain.Transaction tx) =>
 await TransactionPool.Contains(tx);