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); } } } }
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; } } }
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++; }
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}"); } }
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); }
private void OnRegister(VersionPayload version) { Context.Watch(Sender); TaskSession session = new TaskSession(Sender, version); sessions.Add(Sender, session); }
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}"); } }
private void CompleteSyncHeaderTask(TaskSession session) { if (RemoveSyncHeaderTask(session)) { session.HasHeaderTask = false; Log($"SyncHeader completed"); SyncHeader(); } }
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); } } }
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))); } }
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)); }
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; }
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(); } }
private void RestartSyncBlockTask(SyncBlockTask task, TaskSession session) { RemoveSyncBlockTask(task.Hash, task.Session, false); AddSyncBlockTask(task.Hash, task.BlockHeight, session); }
private bool RemoveSyncHeaderTask(TaskSession session) { return(syncHeaderTasks.Remove(session)); }