Exemple #1
0
 private void OnTimer(Timer timer)
 {
     if (timer.Height != context.BlockIndex || timer.ViewNumber != context.ViewNumber)
     {
         return;
     }
     Log($"timeout: height={timer.Height} view={timer.ViewNumber} state={context.State}");
     if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent))
     {
         Log($"send prepare request: height={timer.Height} view={timer.ViewNumber}");
         context.State |= ConsensusState.RequestSent;
         if (!context.State.HasFlag(ConsensusState.SignatureSent))
         {
             FillContext();
             context.Timestamp = Math.Max(DateTime.UtcNow.ToTimestamp(), context.Snapshot.GetHeader(context.PrevHash).Timestamp + 1);
             context.Signatures[context.MyIndex] = context.MakeHeader().Sign(context.KeyPair);
         }
         SignAndRelay(context.MakePrepareRequest());
         if (context.TransactionHashes.Length > 1)
         {
             foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray()))
             {
                 system.LocalNode.Tell(Message.Create("inv", payload));
             }
         }
         ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer.ViewNumber + 1)));
     }
     else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup))
     {
         RequestChangeView();
     }
 }
Exemple #2
0
        private void OnNewTasks(InvPayload payload)
        {
            if (!sessions.TryGetValue(Sender, out TaskSession session))
            {
                return;
            }
            if (payload.Type == InventoryType.TX && blockchain.Height < blockchain.HeaderHeight)
            {
                RequestTasks(session);
                return;
            }
            HashSet <UInt256> hashes = new HashSet <UInt256>(payload.Hashes);

            hashes.ExceptWith(knownHashes);
            if (payload.Type == InventoryType.Block)
            {
                session.AvailableTasks.UnionWith(hashes.Where(p => globalTasks.Contains(p)));
            }
            hashes.ExceptWith(globalTasks);
            if (hashes.Count == 0)
            {
                RequestTasks(session);
                return;
            }
            globalTasks.UnionWith(hashes);
            foreach (UInt256 hash in hashes)
            {
                session.Tasks[hash] = DateTime.UtcNow;
            }
            foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, hashes.ToArray()))
            {
                Sender.Tell(Message.Create("getdata", group));
            }
        }
Exemple #3
0
 private void OnMemPoolMessageReceived()
 {
     foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, Blockchain.Singleton.MemPool.GetVerifiedTransactions().Select(p => p.Hash).ToArray()))
     {
         Context.Parent.Tell(Message.Create("inv", payload));
     }
 }
Exemple #4
0
        private void OnNewTasks(InvPayload payload)
        {
            if (!sessions.TryGetValue(Sender, out TaskSession session))
            {
                return;
            }
            // Do not accept payload of type InventoryType.TX if not synced on best known HeaderHeight
            if (payload.Type == InventoryType.TX && Blockchain.Singleton.Height < sessions.Values.Max(p => p.LastBlockIndex))
            {
                return;
            }
            HashSet <UInt256> hashes = new HashSet <UInt256>(payload.Hashes);

            // Remove all previously processed knownHashes from the list that is being requested
            hashes.Remove(knownHashes);

            // Remove those that are already in process by other sessions
            hashes.Remove(globalTasks);
            if (hashes.Count == 0)
            {
                return;
            }

            // Update globalTasks with the ones that will be requested within this current session
            foreach (UInt256 hash in hashes)
            {
                IncrementGlobalTask(hash);
                session.InvTasks[hash] = TimeProvider.Current.UtcNow;
            }

            foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, hashes.ToArray()))
            {
                Sender.Tell(Message.Create(MessageCommand.GetData, group));
            }
        }
Exemple #5
0
        private void RequestInventoryData(InventoryType type, UInt256[] hashes, IActorRef sender)
        {
            if (hashes.Length == 0)
            {
                return;
            }

            if (hashes.Length == 1)
            {
                sender.Tell(Message.Create(MessageType.GetData, InvPayload.Create(type, hashes[0])));
            }
            else
            {
                string cmd;
                if (type == InventoryType.Block)
                {
                    cmd = MessageType.GetBlk;
                }
                else if (type == InventoryType.TX)
                {
                    cmd = MessageType.GetTxn;
                }
                else
                {
                    return;
                }

                foreach (InvPayload group in InvPayload.CreateGroup(type, hashes))
                {
                    sender.Tell(Message.Create(cmd, group));
                }
            }

            Sender.Tell(RemoteNode.NewCounterMessage(RemoteNode.CounterType.Request, type, hashes.Length));
        }
Exemple #6
0
 private void OnMemPoolMessageReceived(Message msg)
 {
     foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, blockchain.GetMemoryPool().Select(p => p.Hash).ToArray()))
     {
         Context.Parent.Tell(Message.Create(MessageType.Inv, payload));
     }
 }
Exemple #7
0
 private void OnRestartTasks(InvPayload payload)
 {
     knownHashes.ExceptWith(payload.Hashes);
     foreach (UInt256 hash in payload.Hashes)
         globalTasks.Remove(hash);
     foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, payload.Hashes))
         system.LocalNode.Tell(Message.Create(MessageCommand.GetData, group));
 }
Exemple #8
0
 private void RequestTasks(TaskSession session)
 {
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.Remove(knownHashes);
         session.AvailableTasks.RemoveWhere(p => Blockchain.Singleton.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         if (hashes.Count > 0)
         {
             foreach (UInt256 hash in hashes.ToArray())
             {
                 if (!IncrementGlobalTask(hash))
                 {
                     hashes.Remove(hash);
                 }
             }
             session.AvailableTasks.Remove(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 ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.LastBlockIndex)
     {
         session.Tasks[HeaderTaskHash] = DateTime.UtcNow;
         IncrementGlobalTask(HeaderTaskHash);
         session.RemoteNode.Tell(Message.Create("getheaders", GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash)));
     }
     else if (Blockchain.Singleton.Height < session.LastBlockIndex)
     {
         UInt256 hash = Blockchain.Singleton.CurrentBlockHash;
         for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++)
         {
             hash = Blockchain.Singleton.GetBlockHash(i);
             if (!globalTasks.ContainsKey(hash))
             {
                 hash = Blockchain.Singleton.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create("getblocks", GetBlocksPayload.Create(hash)));
     }
     else if (Blockchain.Singleton.HeaderHeight >= session.LastBlockIndex &&
              TimeProvider.Current.UtcNow.ToTimestamp() - PingCoolingOffPeriod >= Blockchain.Singleton.GetBlock(Blockchain.Singleton.CurrentHeaderHash)?.Timestamp)
     {
         session.RemoteNode.Tell(Message.Create("ping", PingPayload.Create(Blockchain.Singleton.Height)));
     }
 }
Exemple #9
0
 private void OnRestartTasks(InvPayload payload)
 {
     knownHashes.ExceptWith(payload.Hashes);
     globalTasks.ExceptWith(payload.Hashes);
     foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, payload.Hashes))
     {
         system.LocalNode.Tell(Message.Create("getdata", group));
     }
 }
Exemple #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.Singleton.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         if (hashes.Count > 0)
         {
             foreach (UInt256 hash in hashes.ToArray())
             {
                 if (!IncrementGlobalTask(hash))
                 {
                     hashes.Remove(hash);
                 }
             }
             session.AvailableTasks.ExceptWith(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(MessageCommand.GetData, group));
             }
             return;
         }
     }
     if ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.StartHeight)
     {
         session.Tasks[HeaderTaskHash] = DateTime.UtcNow;
         IncrementGlobalTask(HeaderTaskHash);
         session.RemoteNode.Tell(Message.Create(MessageCommand.GetHeaders, GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash)));
     }
     else if (Blockchain.Singleton.Height < session.StartHeight)
     {
         UInt256 hash = Blockchain.Singleton.CurrentBlockHash;
         for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++)
         {
             hash = Blockchain.Singleton.GetBlockHash(i);
             if (!globalTasks.ContainsKey(hash))
             {
                 hash = Blockchain.Singleton.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create(MessageCommand.GetBlocks, GetBlocksPayload.Create(hash)));
     }
 }
Exemple #11
0
        private void SendPrepareRequest()
        {
            Log($"send prepare request: height={context.BlockIndex} view={context.ViewNumber}");
            localNode.Tell(new LocalNode.SendDirectly {
                Inventory = context.MakePrepareRequest()
            });

            if (context.TransactionHashes.Length > 1)
            {
                foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray()))
                {
                    localNode.Tell(Message.Create("inv", payload));
                }
            }
            ChangeTimer(TimeSpan.FromSeconds((Blockchain.SecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? Blockchain.SecondsPerBlock : 0)));
        }
Exemple #12
0
        // 广播并清空缓存队列中的交易数据
        private void BroadcastRawTransactions()
        {
            if (rawtxnList.Count == 0)
            {
                return;
            }

            // 控制每组消息里的交易数量,向远程节点发送交易的清单
            foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, rawtxnList.Select(p => p.Hash).ToArray()))
            {
                system.LocalNode.Tell(Message.Create(MessageType.Inv, payload));
            }

            // 清空队列
            rawtxnList.Clear();
        }
Exemple #13
0
        private void OnNewTasks(InvPayload payload)
        {
            if (!sessions.TryGetValue(Sender, out TaskSession session))
            {
                return;
            }

            // Do not accept payload of type InventoryType.TX if not synced on HeaderHeight
            uint currentHeight = NativeContract.Ledger.CurrentIndex(system.StoreView);
            uint headerHeight  = system.HeaderCache.Last?.Index ?? currentHeight;

            if (currentHeight < headerHeight && (payload.Type == InventoryType.TX || (payload.Type == InventoryType.Block && currentHeight < session.LastBlockIndex - InvPayload.MaxHashesCount)))
            {
                RequestTasks(Sender, session);
                return;
            }

            HashSet <UInt256> hashes = new HashSet <UInt256>(payload.Hashes);

            // Remove all previously processed knownHashes from the list that is being requested
            hashes.Remove(knownHashes);
            // Add to AvailableTasks the ones, of type InventoryType.Block, that are global (already under process by other sessions)
            if (payload.Type == InventoryType.Block)
            {
                session.AvailableTasks.UnionWith(hashes.Where(p => globalInvTasks.ContainsKey(p)));
            }

            // Remove those that are already in process by other sessions
            hashes.Remove(globalInvTasks);
            if (hashes.Count == 0)
            {
                RequestTasks(Sender, session);
                return;
            }

            // Update globalTasks with the ones that will be requested within this current session
            foreach (UInt256 hash in hashes)
            {
                IncrementGlobalTask(hash);
                session.InvTasks[hash] = TimeProvider.Current.UtcNow;
            }

            foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, hashes.ToArray()))
            {
                Sender.Tell(Message.Create(MessageCommand.GetData, group));
            }
        }
Exemple #14
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)));
     }
 }
Exemple #15
0
 private void OnTimer(Timer timer)
 {
     if (context.State.HasFlag(ConsensusState.BlockSent))
     {
         return;
     }
     if (timer.Height != context.BlockIndex || timer.ViewNumber != context.ViewNumber)
     {
         return;
     }
     Log($"timeout: height={timer.Height} view={timer.ViewNumber} state={context.State}", LogLevel.Debug);
     if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent))
     {
         // 没有新的交易请求,并且没有到最长出块时间
         if (!blockchain.HasVerifiedTransaction() && TimeProvider.Current.UtcNow - block_received_time < MaxTimeSpanPerBlock)
         {
             // 等待下一次出块时间再判断是否需要出块
             ChangeTimer(Blockchain.TimePerBlock);
             return;
         }
         context.State |= ConsensusState.RequestSent;
         if (!context.State.HasFlag(ConsensusState.SignatureSent))
         {
             context.Fill();
             context.SignHeader();
         }
         Log($"send prepare request: height={timer.Height} view={timer.ViewNumber} tx={context.TransactionHashes.Length}");
         localNode.Tell(new LocalNode.SendDirectly {
             Inventory = context.MakePrepareRequest()
         });
         if (context.TransactionHashes.Length > 1)
         {
             foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray()))
             {
                 localNode.Tell(Message.Create(MessageType.Inv, payload));
             }
         }
         SetNextTimer(timer.ViewNumber + 1);
     }
     else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup))
     {
         RequestChangeView();
     }
 }
Exemple #16
0
        public void CreateGroup()
        {
            var hashes = new UInt256[InvPayload.MaxHashesCount + 1];

            for (int x = 0; x < hashes.Length; x++)
            {
                byte[] data = new byte[32];
                Array.Copy(BitConverter.GetBytes(x), data, 4);
                hashes[x] = new UInt256(data);
            }

            var array = InvPayload.CreateGroup(InventoryType.TX, hashes).ToArray();

            Assert.AreEqual(2, array.Length);
            Assert.AreEqual(InventoryType.TX, array[0].Type);
            Assert.AreEqual(InventoryType.TX, array[1].Type);
            CollectionAssert.AreEqual(hashes.Take(InvPayload.MaxHashesCount).ToArray(), array[0].Hashes);
            CollectionAssert.AreEqual(hashes.Skip(InvPayload.MaxHashesCount).ToArray(), array[1].Hashes);
        }
Exemple #17
0
        private void OnNewTasks(InvPayload payload)
        {
            if (!sessions.TryGetValue(Sender, out TaskSession session))
            {
                return;
            }
            // Do not accept payload of type InventoryType.TX if not synced on best known HeaderHeight
            if (payload.Type == InventoryType.TX && Blockchain.Singleton.Height < Blockchain.Singleton.HeaderHeight)
            {
                RequestTasks(session);
                return;
            }
            HashSet <UInt256> hashes = new HashSet <UInt256>(payload.Hashes);

            // Remove all previously processed knownHashes from the list that is being requested
            hashes.Remove(knownHashes);
            // Add to AvailableTasks the ones, of type InventoryType.Block, that are global (already under process by other sessions)
            if (payload.Type == InventoryType.Block)
            {
                session.AvailableTasks.UnionWith(hashes.Where(p => globalTasks.ContainsKey(p)));
            }

            // Remove those that are already in process by other sessions
            hashes.Remove(globalTasks);
            if (hashes.Count == 0)
            {
                RequestTasks(session);
                return;
            }

            // Update globalTasks with the ones that will be requested within this current session
            foreach (UInt256 hash in hashes)
            {
                IncrementGlobalTask(hash);
                session.Tasks[hash] = DateTime.UtcNow;
            }

            foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, hashes.ToArray()))
            {
                Sender.Tell(Message.Create(MessageCommand.GetData, group));
            }
        }
Exemple #18
0
        private void SendPrepareRequest()
        {
            Log($"Sending {nameof(PrepareRequest)}: height={context.Block.Index} view={context.ViewNumber}");
            localNode.Tell(new LocalNode.SendDirectly {
                Inventory = context.MakePrepareRequest()
            });

            if (context.Validators.Length == 1)
            {
                CheckPreparations();
            }

            if (context.TransactionHashes.Length > 0)
            {
                foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes))
                {
                    localNode.Tell(Message.Create(MessageCommand.Inv, payload));
                }
            }
            ChangeTimer(TimeSpan.FromMilliseconds((neoSystem.Settings.MillisecondsPerBlock << (context.ViewNumber + 1)) - (context.ViewNumber == 0 ? neoSystem.Settings.MillisecondsPerBlock : 0)));
        }
Exemple #19
0
 private void OnTimer(Timer timer)
 {
     if (context.State.HasFlag(ConsensusState.BlockSent))
     {
         return;
     }
     if (timer.Height != context.BlockIndex || timer.ViewNumber != context.ViewNumber)
     {
         return;
     }
     Log($"timeout: height={timer.Height} view={timer.ViewNumber} state={context.State}");
     if (context.State.HasFlag(ConsensusState.Primary) && !context.State.HasFlag(ConsensusState.RequestSent))
     {
         Log($"send prepare request: height={timer.Height} view={timer.ViewNumber}");
         context.State |= ConsensusState.RequestSent;
         if (!context.State.HasFlag(ConsensusState.SignatureSent))
         {
             context.Fill();
             context.SignHeader();
         }
         localNode.Tell(new LocalNode.SendDirectly {
             Inventory = context.MakePrepareRequest()
         });
         if (context.TransactionHashes.Length > 1)
         {
             foreach (InvPayload payload in InvPayload.CreateGroup(InventoryType.TX, context.TransactionHashes.Skip(1).ToArray()))
             {
                 localNode.Tell(Message.Create("inv", payload));
             }
         }
         ChangeTimer(TimeSpan.FromSeconds(Blockchain.SecondsPerBlock << (timer.ViewNumber + 1)));
     }
     else if ((context.State.HasFlag(ConsensusState.Primary) && context.State.HasFlag(ConsensusState.RequestSent)) || context.State.HasFlag(ConsensusState.Backup))
     {
         RequestChangeView();
     }
 }
Exemple #20
0
        private void OnNewTasks(InvPayload payload)
        {
            if (!sessions.TryGetValue(Sender, out TaskSession session))
            {
                return;
            }
            if (payload.Type == InventoryType.TX && Blockchain.Singleton.Height < Blockchain.Singleton.HeaderHeight)
            {
                RequestTasks(session);
                return;
            }
            HashSet <UInt256> hashes = new HashSet <UInt256>(payload.Hashes);

            hashes.Remove(knownHashes);
            if (payload.Type == InventoryType.Block)
            {
                session.AvailableTasks.UnionWith(hashes.Where(p => globalTasks.ContainsKey(p)));
            }

            hashes.Remove(globalTasks);
            if (hashes.Count == 0)
            {
                RequestTasks(session);
                return;
            }

            foreach (UInt256 hash in hashes)
            {
                IncrementGlobalTask(hash);
                session.Tasks[hash] = DateTime.UtcNow;
            }

            foreach (InvPayload group in InvPayload.CreateGroup(payload.Type, hashes.ToArray()))
            {
                Sender.Tell(Message.Create(MessageCommand.GetData, group));
            }
        }
Exemple #21
0
        private void RequestTasks(TaskSession session)
        {
            if (session.HasTask)
            {
                return;
            }
            // If there are pending tasks of InventoryType.Block we should process them
            if (session.AvailableTasks.Count > 0)
            {
                session.AvailableTasks.Remove(knownHashes);
                // Search any similar hash that is on Singleton's knowledge, which means, on the way or already processed
                session.AvailableTasks.RemoveWhere(p => Blockchain.Singleton.ContainsBlock(p));
                HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
                hashes.Remove(MemPoolTaskHash);
                if (hashes.Count > 0)
                {
                    foreach (UInt256 hash in hashes.ToArray())
                    {
                        if (!IncrementGlobalTask(hash))
                        {
                            hashes.Remove(hash);
                        }
                    }
                    session.AvailableTasks.Remove(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(MessageCommand.GetData, group));
                    }
                    return;
                }
            }

            // When the number of AvailableTasks is no more than 0, no pending tasks of InventoryType.Block, it should process pending the tasks of headers
            // If not HeaderTask pending to be processed it should ask for more Blocks
            if ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.LastBlockIndex)
            {
                session.Tasks[HeaderTaskHash] = DateTime.UtcNow;
                IncrementGlobalTask(HeaderTaskHash);
                session.RemoteNode.Tell(Message.Create(MessageCommand.GetHeaders, GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash)));
            }
            else if (Blockchain.Singleton.Height < session.LastBlockIndex)
            {
                UInt256 hash = Blockchain.Singleton.CurrentBlockHash;
                for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++)
                {
                    hash = Blockchain.Singleton.GetBlockHash(i);
                    if (!globalTasks.ContainsKey(hash))
                    {
                        hash = Blockchain.Singleton.GetBlockHash(i - 1);
                        break;
                    }
                }
                session.RemoteNode.Tell(Message.Create(MessageCommand.GetBlocks, GetBlocksPayload.Create(hash)));
            }
            else if (Blockchain.Singleton.HeaderHeight >= session.LastBlockIndex &&
                     TimeProvider.Current.UtcNow.ToTimestampMS() - PingCoolingOffPeriod >= Blockchain.Singleton.GetBlock(Blockchain.Singleton.CurrentHeaderHash)?.Timestamp)
            {
                if (session.AvailableTasks.Remove(MemPoolTaskHash))
                {
                    session.RemoteNode.Tell(Message.Create(MessageCommand.Mempool));
                }

                session.RemoteNode.Tell(Message.Create(MessageCommand.Ping, PingPayload.Create(Blockchain.Singleton.Height)));
            }
        }
Exemple #22
0
        private void RequestTasks(IActorRef remoteNode, TaskSession session)
        {
            if (session.HasTooManyTasks)
            {
                return;
            }

            DataCache snapshot = system.StoreView;

            // If there are pending tasks of InventoryType.Block we should process them
            if (session.AvailableTasks.Count > 0)
            {
                session.AvailableTasks.Remove(knownHashes);
                // Search any similar hash that is on Singleton's knowledge, which means, on the way or already processed
                session.AvailableTasks.RemoveWhere(p => NativeContract.Ledger.ContainsBlock(snapshot, p));
                HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
                if (hashes.Count > 0)
                {
                    foreach (UInt256 hash in hashes.ToArray())
                    {
                        if (!IncrementGlobalTask(hash))
                        {
                            hashes.Remove(hash);
                        }
                    }
                    session.AvailableTasks.Remove(hashes);
                    foreach (UInt256 hash in hashes)
                    {
                        session.InvTasks[hash] = DateTime.UtcNow;
                    }
                    foreach (InvPayload group in InvPayload.CreateGroup(InventoryType.Block, hashes.ToArray()))
                    {
                        remoteNode.Tell(Message.Create(MessageCommand.GetData, group));
                    }
                    return;
                }
            }

            uint currentHeight = NativeContract.Ledger.CurrentIndex(snapshot);
            uint headerHeight  = system.HeaderCache.Last?.Index ?? currentHeight;

            // When the number of AvailableTasks is no more than 0, no pending tasks of InventoryType.Block, it should process pending the tasks of headers
            // If not HeaderTask pending to be processed it should ask for more Blocks
            if ((!HasHeaderTask || globalInvTasks[HeaderTaskHash] < MaxConncurrentTasks) && headerHeight < session.LastBlockIndex && !system.HeaderCache.Full)
            {
                session.InvTasks[HeaderTaskHash] = DateTime.UtcNow;
                IncrementGlobalTask(HeaderTaskHash);
                remoteNode.Tell(Message.Create(MessageCommand.GetHeaders, GetBlockByIndexPayload.Create(headerHeight)));
            }
            else if (currentHeight < session.LastBlockIndex)
            {
                uint startHeight = currentHeight;
                while (globalIndexTasks.ContainsKey(++startHeight))
                {
                }
                if (startHeight > session.LastBlockIndex || startHeight >= currentHeight + InvPayload.MaxHashesCount)
                {
                    return;
                }
                uint endHeight = startHeight;
                while (!globalIndexTasks.ContainsKey(++endHeight) && endHeight <= session.LastBlockIndex && endHeight <= currentHeight + InvPayload.MaxHashesCount)
                {
                }
                uint count = Math.Min(endHeight - startHeight, InvPayload.MaxHashesCount);
                for (uint i = 0; i < count; i++)
                {
                    session.IndexTasks[startHeight + i] = TimeProvider.Current.UtcNow;
                    IncrementGlobalTask(startHeight + i);
                }
                remoteNode.Tell(Message.Create(MessageCommand.GetBlockByIndex, GetBlockByIndexPayload.Create(startHeight, (short)count)));
            }
            else if (!session.MempoolSent)
            {
                session.MempoolSent = true;
                remoteNode.Tell(Message.Create(MessageCommand.Mempool));
            }
        }
Exemple #23
0
 private void RequestTasks(TaskSession session)
 {
     if (!_expiredTimes.TryGetValue(session.RemoteNode.Path, out var expireTime) || expireTime < DateTime.UtcNow)
     {
         session.RemoteNode.Tell(Message.Create("ping", PingPayload.Create(Blockchain.Singleton.Height)));
         _expiredTimes[session.RemoteNode.Path] = DateTime.UtcNow.AddSeconds(PingCoolingOffPeriod);
     }
     if (session.HasTask)
     {
         return;
     }
     if (session.AvailableTasks.Count > 0)
     {
         session.AvailableTasks.Remove(knownHashes);
         session.AvailableTasks.RemoveWhere(p => Blockchain.Singleton.ContainsBlock(p));
         HashSet <UInt256> hashes = new HashSet <UInt256>(session.AvailableTasks);
         if (hashes.Count > 0)
         {
             foreach (UInt256 hash in hashes.ToArray())
             {
                 if (!IncrementGlobalTask(hash))
                 {
                     hashes.Remove(hash);
                 }
             }
             session.AvailableTasks.Remove(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 ((!HasHeaderTask || globalTasks[HeaderTaskHash] < MaxConncurrentTasks) && Blockchain.Singleton.HeaderHeight < session.LastBlockIndex)
     {
         session.Tasks[HeaderTaskHash] = DateTime.UtcNow;
         IncrementGlobalTask(HeaderTaskHash);
         session.RemoteNode.Tell(Message.Create("getheaders", GetBlocksPayload.Create(Blockchain.Singleton.CurrentHeaderHash)));
     }
     else if (Blockchain.Singleton.Height < session.LastBlockIndex)
     {
         UInt256 hash = Blockchain.Singleton.CurrentBlockHash;
         for (uint i = Blockchain.Singleton.Height + 1; i <= Blockchain.Singleton.HeaderHeight; i++)
         {
             hash = Blockchain.Singleton.GetBlockHash(i);
             if (!globalTasks.ContainsKey(hash))
             {
                 hash = Blockchain.Singleton.GetBlockHash(i - 1);
                 break;
             }
         }
         session.RemoteNode.Tell(Message.Create("getblocks", GetBlocksPayload.Create(hash)));
     }
     if (!HasStateRootTask)
     {
         if (Blockchain.Singleton.ExpectStateRootIndex < Blockchain.Singleton.Height)
         {
             var state_root_state = Blockchain.Singleton.GetStateRoot(Blockchain.Singleton.ExpectStateRootIndex);
             if (state_root_state is null || state_root_state.Flag == StateRootVerifyFlag.Invalid)
             {
                 return;
             }
             var start_index = Blockchain.Singleton.ExpectStateRootIndex;
             var count       = Math.Min(Blockchain.Singleton.Height - start_index, StateRootsPayload.MaxStateRootsCount);
             StateRootSyncTime = DateTime.UtcNow;
             IncrementGlobalTask(StateRootTaskHash);
             system.LocalNode.Tell(Message.Create("getroots", GetStateRootsPayload.Create(start_index, count)));
         }
     }
 }