Example #1
0
        private void CheckSyncBlockTimeout()
        {
            DateTime now = DateTime.UtcNow;

            SyncBlockTask[] timeoutTasks = syncBlockTasks.Values.SelectMany(p => p.Where(q => now >= q.ExpiryTime)).ToArray();
            foreach (SyncBlockTask task in timeoutTasks)
            {
                task.Session.Timeout++;
                task.Session.RemoteNode.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Timeout, InventoryType.Block));
                Log($"SyncBlock timeout:{task.BlockHeight}, nodeId:{task.Session.Version.NodeId}");

                if (task.BlockHeight <= blockchain.Height)
                {
                    RemoveSyncBlockTask(task);
                }
                else
                {
                    TaskSession session = GetSyncSession(task.BlockHeight, false);

                    if (session != null)
                    {
                        RestartSyncBlockTask(task, session);

                        session.RemoteNode.Tell(Message.Create(MessageType.GetData, InvPayload.Create(InventoryType.Block, task.Hash)));
                        session.RemoteNode.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Request, InventoryType.Block));
                    }
                    else
                    {
                        RemoveSyncBlockTask(task);
                    }
                }
            }
        }
Example #2
0
 private void RequestTasks(TaskSession session)
 {
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.ExceptWith(knownHashes);
         session.AvailableTasks.RemoveWhere(p => blockchain.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         hashes.ExceptWith(globalTasks);
         if (hashes.Count > 0)
         {
             session.AvailableTasks.ExceptWith(hashes);
             globalTasks.UnionWith(hashes);
             foreach (UInt256 hash in hashes)
             {
                 session.Tasks[hash] = new TaskSession.Task {
                     Type = InventoryType.Block, BeginTime = DateTime.UtcNow
                 }
             }
             ;
             RequestInventoryData(InventoryType.Block, hashes.ToArray(), session.RemoteNode);
             return;
         }
     }
 }
Example #3
0
        private void AddSyncBlockTask(UInt256 hash, uint blockHeight, TaskSession session)
        {
            if (!syncBlockTasks.TryGetValue(hash, out List <SyncBlockTask> list))
            {
                list = new List <SyncBlockTask>();

                syncBlockTasks.Add(hash, list);
            }

            SyncBlockTask task = list.Find(p => p.Session == session);

            if (task != null)
            {
                task.ExpiryTime = DateTime.UtcNow + SyncBlockTimeout;
            }
            else
            {
                list.Add(new SyncBlockTask
                {
                    Hash        = hash,
                    BlockHeight = blockHeight,
                    ExpiryTime  = DateTime.UtcNow + SyncBlockTimeout,
                    Session     = session
                });
            }

            session.SyncBlockTasks++;
        }
Example #4
0
        private void SyncHeader()
        {
            int taskCount = syncHeaderTasks.Count();

            if (taskCount >= MaxSyncHeaderTaskCount)
            {
                return;
            }

            uint currentBlockHeight  = blockchain.Height;
            uint currentHeaderHeight = blockchain.HeaderHeight;

            if (currentHeaderHeight >= currentBlockHeight + MaxHeaderForwardCount)
            {
                return;
            }

            uint nextHeaderHeight = currentHeaderHeight + 1;
            int  count            = MaxSyncHeaderTaskCount - taskCount;

            for (int i = 1; i <= count; i++)
            {
                TaskSession session = GetSyncSession(nextHeaderHeight, true);
                if (session == null)
                {
                    return;
                }

                AddSyncHeaderTask(nextHeaderHeight, session);
                session.RemoteNode.Tell(Message.Create(MessageType.GetHeaders, GetBlocksPayload.Create(blockchain.CurrentHeaderHash)));
                Log($"SyncHeader:{nextHeaderHeight}, nodeId:{session.Version.NodeId}");
            }
        }
Example #5
0
        public bool SyncBlock(uint blockHeight)
        {
            TaskSession session = GetSyncSession(blockHeight, false);

            if (session == null)
            {
                return(false);
            }

            UInt256 hash = blockchain.GetBlockHash(blockHeight);

            if (hash == null)
            {
                return(false);
            }

            if (!globalTasks.Add(hash))
            {
                return(true);
            }

            AddSyncBlockTask(hash, blockHeight, session);
            session.RemoteNode.Tell(Message.Create(MessageType.GetData, InvPayload.Create(InventoryType.Block, hash)));
            session.RemoteNode.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Request, InventoryType.Block));

            syncingBlockHeight = blockHeight;
            Log($"SyncBlock:{blockHeight}, nodeId:{session.Version.NodeId}", LogLevel.Debug);
            return(true);
        }
Example #6
0
        private void OnRegister(VersionPayload version)
        {
            Context.Watch(Sender);
            TaskSession session = new TaskSession(Sender, version);

            sessions.Add(Sender, session);
        }
Example #7
0
 private void SetSyncHeaderTaskNeverExpire(TaskSession session)
 {
     if (syncHeaderTasks.TryGetValue(session, out SyncHeaderTask task))
     {
         task.ExpiryTime = DateTime.MaxValue;
         Log($"SyncHeader received: {task.HeaderHeight}, nodeId:{session.Version.NodeId}");
     }
 }
Example #8
0
 private void CompleteSyncHeaderTask(TaskSession session)
 {
     if (RemoveSyncHeaderTask(session))
     {
         session.HasHeaderTask = false;
         Log($"SyncHeader completed");
         SyncHeader();
     }
 }
Example #9
0
        private void RemoveSyncBlockTask(UInt256 hash, TaskSession session, bool cleanup = true)
        {
            if (syncBlockTasks.TryGetValue(hash, out List <SyncBlockTask> list))
            {
                list.RemoveAll(p => p.Session == session);

                if (cleanup && list.Count() == 0)
                {
                    syncBlockTasks.Remove(hash);
                }
            }
        }
Example #10
0
 private void RequestTasks(TaskSession session)
 {
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.ExceptWith(knownHashes);
         session.AvailableTasks.RemoveWhere(p => blockchain.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         hashes.ExceptWith(globalTasks);
         if (hashes.Count > 0)
         {
             session.AvailableTasks.ExceptWith(hashes);
             globalTasks.UnionWith(hashes);
             foreach (UInt256 hash in hashes)
             {
                 session.Tasks[hash] = DateTime.UtcNow;
             }
             foreach (InvPayload group in InvPayload.CreateGroup(InventoryType.Block, hashes.ToArray()))
             {
                 session.RemoteNode.Tell(Message.Create("getdata", group));
             }
             return;
         }
     }
     if (!HeaderTask && blockchain.HeaderHeight < session.Version.StartHeight)
     {
         session.Tasks[UInt256.Zero] = DateTime.UtcNow;
         session.RemoteNode.Tell(Message.Create("getheaders", GetBlocksPayload.Create(blockchain.CurrentHeaderHash)));
     }
     else if (blockchain.Height < session.Version.StartHeight)
     {
         UInt256 hash = blockchain.CurrentBlockHash;
         for (uint i = blockchain.Height + 1; i <= blockchain.HeaderHeight; i++)
         {
             hash = blockchain.GetBlockHash(i);
             if (!globalTasks.Contains(hash))
             {
                 hash = blockchain.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create("getblocks", GetBlocksPayload.Create(hash)));
     }
 }
Example #11
0
        private int CompareSession(TaskSession ts1, TaskSession ts2)
        {
            int r = ts1.Weight.CompareTo(ts2.Weight);

            if (r != 0)
            {
                return(r);
            }

            r = ts1.Latency.CompareTo(ts2.Latency);
            if (r != 0)
            {
                return(r);
            }

            return(ts1.Version.NodeId.CompareTo(ts2.Version.NodeId));
        }
Example #12
0
        private void AddSyncHeaderTask(uint headerHeight, TaskSession session)
        {
            if (syncHeaderTasks.TryGetValue(session, out SyncHeaderTask task))
            {
                task.ExpiryTime   = DateTime.UtcNow + SyncHeaderTimeout;
                task.HeaderHeight = headerHeight;
            }
            else
            {
                syncHeaderTasks.Add(session, new SyncHeaderTask
                {
                    HeaderHeight = headerHeight,
                    ExpiryTime   = DateTime.UtcNow + SyncHeaderTimeout,
                    Session      = session
                });
            }

            session.HasHeaderTask = true;
        }
Example #13
0
        private void CompleteSyncBlockTask(UInt256 hash, TaskSession session)
        {
            if (syncBlockTasks.TryGetValue(hash, out List <SyncBlockTask> list))
            {
                SyncBlockTask task = list.Find(p => p.Session == session);

                if (task != null)
                {
                    list.Remove(task);

                    if (list.Count() == 0)
                    {
                        syncBlockTasks.Remove(hash);
                    }
                }
            }

            if (syncBlockTasks.Count() == 0)
            {
                SyncBlocks();
            }
        }
Example #14
0
        private void RestartSyncBlockTask(SyncBlockTask task, TaskSession session)
        {
            RemoveSyncBlockTask(task.Hash, task.Session, false);

            AddSyncBlockTask(task.Hash, task.BlockHeight, session);
        }
Example #15
0
 private bool RemoveSyncHeaderTask(TaskSession session)
 {
     return(syncHeaderTasks.Remove(session));
 }