コード例 #1
0
        public void StartEvictionProcess(INodeLifecycleManager evictionCandidate, INodeLifecycleManager replacementCandidate)
        {
            if (_logger.IsTrace)
            {
                _logger.Trace($"Starting eviction process, evictionCandidate: {evictionCandidate.ManagedNode}, replacementCandidate: {replacementCandidate.ManagedNode}");
            }

            EvictionPair newPair = new EvictionPair
            {
                EvictionCandidate    = evictionCandidate,
                ReplacementCandidate = replacementCandidate,
            };

            EvictionPair pair = _evictionPairs.GetOrAdd(evictionCandidate.ManagedNode.IdHash, newPair);

            if (pair != newPair)
            {
                //existing eviction in process
                //TODO add queue for further evictions
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Existing eviction in process, evictionCandidate: {evictionCandidate.ManagedNode}, replacementCandidate: {replacementCandidate.ManagedNode}");
                }
                return;
            }

            evictionCandidate.OnStateChanged += OnStateChange;
            evictionCandidate.StartEvictionProcess();
        }
コード例 #2
0
        private void UpdateState(NodeLifecycleState newState)
        {
            if (newState == NodeLifecycleState.New)
            {
                //if node is just discovered we send ping to confirm it is active
                SendPing();
            }
            else if (newState == NodeLifecycleState.Active)
            {
                //TODO && !ManagedNode.IsDicoveryNode - should we exclude discovery nodes
                //received pong first time
                if (State == NodeLifecycleState.New)
                {
                    NodeAddResult result = _nodeTable.AddNode(ManagedNode);
                    if (result.ResultType == NodeAddResultType.Full)
                    {
                        INodeLifecycleManager evictionCandidate = _discoveryManager.GetNodeLifecycleManager(result.EvictionCandidate.Node);
                        if (evictionCandidate != null)
                        {
                            _evictionManager.StartEvictionProcess(evictionCandidate, this);
                        }
                    }
                }
            }
            else if (newState == NodeLifecycleState.EvictCandidate)
            {
                SendPing();
            }

            State = newState;
            OnStateChanged?.Invoke(this, State);
        }
コード例 #3
0
ファイル: DiscoveryApp.cs プロジェクト: prestwich/nethermind
        private void AddPersistedNodes(CancellationToken cancellationToken)
        {
            if (!_discoveryConfig.IsDiscoveryNodesPersistenceOn)
            {
                return;
            }

            NetworkNode[] nodes = _discoveryStorage.GetPersistedNodes();
            foreach (NetworkNode networkNode in nodes)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                Node node;
                try
                {
                    node = new Node(networkNode.NodeId, networkNode.Host, networkNode.Port);
                }
                catch (Exception)
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Error($"ERROR/DEBUG peer could not be loaded for {networkNode.NodeId}@{networkNode.Host}:{networkNode.Port}");
                    }
                    continue;
                }

                INodeLifecycleManager manager = _discoveryManager.GetNodeLifecycleManager(node, true);
                if (manager == null)
                {
                    if (_logger.IsDebug)
                    {
                        _logger.Debug($"Skiping persisted node {networkNode.NodeId}@{networkNode.Host}:{networkNode.Port}, manager couldnt be created");
                    }

                    continue;
                    ;
                }

                manager.NodeStats.CurrentPersistedNodeReputation = networkNode.Reputation;
                if (_logger.IsTrace)
                {
                    _logger.Trace($"Adding persisted node {networkNode.NodeId}@{networkNode.Host}:{networkNode.Port}");
                }
            }

            if (_logger.IsDebug)
            {
                _logger.Debug($"Added persisted discovery nodes: {nodes.Length}");
            }
        }
コード例 #4
0
        private INodeLifecycleManager CreateLifecycleManager(Node node)
        {
            INodeLifecycleManager manager = Substitute.For <INodeLifecycleManager>();

            manager.ManagedNode.Returns(node);
            manager.NodeStats.Returns(new NodeStats(node, _statsConfig, NullLogManager.Instance)
            {
                CurrentPersistedNodeReputation = node.Port
            });

            return(manager);
        }
コード例 #5
0
        private INodeLifecycleManager CreateLifecycleManager(Node node)
        {
            INodeLifecycleManager manager = Substitute.For <INodeLifecycleManager>();

            manager.ManagedNode.Returns(node);
            manager.NodeStats.Returns(new NodeStatsLight(node)
            {
                CurrentPersistedNodeReputation = node.Port
            });

            return(manager);
        }
コード例 #6
0
 public void MemoryTest()
 {
     //receiving pong to have a node in the system
     for (int a = 0; a < 255; a++)
     {
         for (int b = 0; b < 255; b++)
         {
             INodeLifecycleManager manager = _discoveryManager.GetNodeLifecycleManager(new Node($"{a}.{b}.1.1", 8000));
             manager.SendPingAsync();
             _discoveryManager.OnIncomingMessage(new PongMessage {
                 FarAddress = new IPEndPoint(IPAddress.Parse($"{a}.{b}.1.1"), _port), FarPublicKey = _publicKey
             });
         }
     }
 }
コード例 #7
0
        private void UpdateState(NodeLifecycleState newState)
        {
            if (newState == NodeLifecycleState.New)
            {
                //if node is just discovered we send ping to confirm it is active
#pragma warning disable 4014
                SendPingAsync();
#pragma warning restore 4014
            }
            else if (newState == NodeLifecycleState.Active)
            {
                //TODO && !ManagedNode.IsDiscoveryNode - should we exclude discovery nodes
                //received pong first time
                if (State == NodeLifecycleState.New)
                {
                    NodeAddResult result = _nodeTable.AddNode(ManagedNode);
                    if (result.ResultType == NodeAddResultType.Full)
                    {
                        INodeLifecycleManager evictionCandidate = _discoveryManager.GetNodeLifecycleManager(result.EvictionCandidate.Node);
                        if (evictionCandidate != null)
                        {
                            _evictionManager.StartEvictionProcess(evictionCandidate, this);
                        }
                    }
                }
            }
            else if (newState == NodeLifecycleState.EvictCandidate)
            {
                if (State == NodeLifecycleState.EvictCandidate)
                {
                    throw new InvalidOperationException("Cannot start more than one eviction process on same node.");
                }

                if (DateTime.UtcNow - _lastPingSent > TimeSpan.FromSeconds(5))
                {
#pragma warning disable 4014
                    SendPingAsync();
#pragma warning restore 4014
                }
                else
                {
                    OnStateChanged?.Invoke(this, NodeLifecycleState.Active);
                }
            }

            State = newState;
            OnStateChanged?.Invoke(this, State);
        }
コード例 #8
0
ファイル: NodesLocator.cs プロジェクト: uzbekdev1/nethermind
        private async Task <Result> SendFindNode(Node destinationNode, byte[] searchedNodeId, CancellationToken cancellationToken)
        {
            try
            {
                INodeLifecycleManager nodeManager = _discoveryManager.GetNodeLifecycleManager(destinationNode);

                nodeManager?.SendFindNode(searchedNodeId ?? _masterNode.Id.Bytes);

                return(await _discoveryManager.WasMessageReceived(destinationNode.IdHash, MessageType.Neighbors, _discoveryConfig.SendNodeTimeout)
                    ? Result.Success
                    : Result.Fail($"Did not receive Neighbors response in time from: {destinationNode.Host}"));
            }
            catch (OperationCanceledException)
            {
                return(Result.Fail("Cancelled"));
            }
        }
コード例 #9
0
        private async Task <bool> InitializeBootnodes(CancellationToken cancellationToken)
        {
            NetworkNode[] bootnodes = NetworkNode.ParseNodes(_discoveryConfig.Bootnodes, _logger);
            if (!bootnodes.Any())
            {
                if (_logger.IsWarn)
                {
                    _logger.Warn("No bootnodes specified in configuration");
                }
                return(true);
            }

            List <INodeLifecycleManager> managers = new List <INodeLifecycleManager>();

            for (int i = 0; i < bootnodes.Length; i++)
            {
                NetworkNode bootnode = bootnodes[i];
                Node        node     = bootnode.NodeId == null
                    ? new Node(bootnode.Host, bootnode.Port)
                    : new Node(bootnode.NodeId, bootnode.Host, bootnode.Port, true);
                INodeLifecycleManager manager = _discoveryManager.GetNodeLifecycleManager(node);
                if (manager != null)
                {
                    managers.Add(manager);
                }
                else
                {
                    _logger.Warn($"Bootnode config contains self: {bootnode.NodeId}");
                }
            }

            //Wait for pong message to come back from Boot nodes
            int maxWaitTime = _discoveryConfig.BootnodePongTimeout;
            int itemTime    = maxWaitTime / 100;

            for (int i = 0; i < 100; i++)
            {
                if (cancellationToken.IsCancellationRequested)
                {
                    break;
                }

                if (managers.Any(x => x.State == NodeLifecycleState.Active))
                {
                    break;
                }

                if (_discoveryManager.GetOrAddNodeLifecycleManagers(x => x.State == NodeLifecycleState.Active).Any())
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace("Was not able to connect to any of the bootnodes, but successfully connected to at least one persisted node.");
                    }
                    break;
                }

                if (_logger.IsTrace)
                {
                    _logger.Trace($"Waiting {itemTime} ms for bootnodes to respond");
                }

                try
                {
                    await Task.Delay(itemTime, cancellationToken);
                }
                catch (OperationCanceledException)
                {
                    break;
                }
            }

            int reachedNodeCounter = 0;

            for (int i = 0; i < managers.Count; i++)
            {
                INodeLifecycleManager manager = managers[i];
                if (manager.State != NodeLifecycleState.Active)
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Could not reach bootnode: {manager.ManagedNode.Host}:{manager.ManagedNode.Port}");
                    }
                }
                else
                {
                    if (_logger.IsTrace)
                    {
                        _logger.Trace($"Reached bootnode: {manager.ManagedNode.Host}:{manager.ManagedNode.Port}");
                    }
                    reachedNodeCounter++;
                }
            }

            if (_logger.IsInfo)
            {
                _logger.Info($"Connected to {reachedNodeCounter} bootnodes, {_discoveryManager.GetOrAddNodeLifecycleManagers(x => x.State == NodeLifecycleState.Active).Count} trusted/persisted nodes");
            }
            return(reachedNodeCounter > 0);
        }
コード例 #10
0
 private void CloseEvictionProcess(INodeLifecycleManager evictionCandidate)
 {
     _evictionPairs.TryRemove(evictionCandidate.ManagedNode.IdHash, out EvictionPair _);
     evictionCandidate.OnStateChanged -= OnStateChange;
 }
コード例 #11
0
        public void EvictCandidateStateLostEvictionTest()
        {
            //adding 3 active nodes
            List <INodeLifecycleManager> managers = new();

            for (int i = 0; i < 3; i++)
            {
                string host = "192.168.1." + i;
                Node   node = new(_nodeIds[i], host, _port);
                INodeLifecycleManager?manager = _discoveryManager.GetNodeLifecycleManager(node);
                if (manager is null)
                {
                    throw new Exception("Manager is null");
                }

                managers.Add(manager);
                Assert.AreEqual(NodeLifecycleState.New, manager.State);

                PongMsg msg = new (_nodeIds[i], GetExpirationTime(), new byte[32]);
                msg.FarAddress = new IPEndPoint(IPAddress.Parse(_host), _port);
                _discoveryManager.OnIncomingMsg(msg);

                Assert.AreEqual(NodeLifecycleState.Active, manager.State);
            }

            //table should contain 3 active nodes
            IEnumerable <Node> closestNodes = _nodeTable.GetClosestNodes().ToArray();

            for (int i = 0; i < 3; i++)
            {
                Assert.IsTrue(closestNodes.Count(x => x.Host == managers[0].ManagedNode.Host) == 1);
            }

            //adding 4th node - table can store only 3, eviction process should start
            Node candidateNode = new(_nodeIds[3], _host, _port);

            INodeLifecycleManager?candidateManager = _discoveryManager.GetNodeLifecycleManager(candidateNode);

            Assert.AreEqual(NodeLifecycleState.New, candidateManager?.State);

            PongMsg pongMsg = new (_nodeIds[3], GetExpirationTime(), new byte[32]);

            pongMsg.FarAddress = new IPEndPoint(IPAddress.Parse(_host), _port);
            _discoveryManager.OnIncomingMsg(pongMsg);

            //await Task.Delay(10);
            Assert.That(() => candidateManager?.State, Is.EqualTo(NodeLifecycleState.Active).After(10, 5));
            //Assert.AreEqual(NodeLifecycleState.Active, candidateManager.State);

            INodeLifecycleManager evictionCandidate = managers.First(x => x.State == NodeLifecycleState.EvictCandidate);

            //await Task.Delay(300);

            //3th node should be evicted, 4th node should be added to the table
            //Assert.AreEqual(NodeLifecycleState.Active, candidateManager.State);
            Assert.That(() => candidateManager?.State, Is.EqualTo(NodeLifecycleState.Active).After(300, 50));
            //Assert.AreEqual(NodeLifecycleState.Unreachable, evictionCandidate.State);
            Assert.That(() => evictionCandidate.State, Is.EqualTo(NodeLifecycleState.Unreachable).After(300, 50));

            closestNodes = _nodeTable.GetClosestNodes();
            Assert.That(() => managers.Where(x => x.State == NodeLifecycleState.Active).All(x => closestNodes.Any(y => y.Host == x.ManagedNode.Host)), Is.True.After(300, 50));
            Assert.That(() => closestNodes.Count(x => x.Host == evictionCandidate.ManagedNode.Host) == 0, Is.True.After(300, 50));
            Assert.That(() => closestNodes.Count(x => x.Host == candidateNode.Host) == 1, Is.True.After(300, 50));

            //Assert.IsTrue(managers.Where(x => x.State == NodeLifecycleState.Active).All(x => closestNodes.Any(y => y.Host == x.ManagedNode.Host)));
            //Assert.IsTrue(closestNodes.Count(x => x.Host == evictionCandidate.ManagedNode.Host) == 0);
            //Assert.IsTrue(closestNodes.Count(x => x.Host == candidateNode.Host) == 1);
        }
コード例 #12
0
 public Peer(INodeLifecycleManager manager)
 {
     Node = manager.ManagedNode;
     NodeLifecycleManager = manager;
     NodeStats            = manager.NodeStats;
 }
コード例 #13
0
 public NodeEventArgs(INodeLifecycleManager manager)
 {
     Manager = manager;
 }
コード例 #14
0
ファイル: DiscoveryApp.cs プロジェクト: StateProof/nethermind
        private async Task <bool> InitializeBootnodes()
        {
            var bootNodes = _configurationProvider.BootNodes;

            if (bootNodes == null || !bootNodes.Any())
            {
                if (_logger.IsWarnEnabled)
                {
                    _logger.Warn("No bootnodes specified in configuration");
                }
                return(false);
            }
            var managers = new INodeLifecycleManager[bootNodes.Length];

            for (var i = 0; i < bootNodes.Length; i++)
            {
                var bootnode = bootNodes[i];
                var node     = bootnode.NodeId == null
                    ? _nodeFactory.CreateNode(bootnode.Host, bootnode.Port)
                    : _nodeFactory.CreateNode(new NodeId(new PublicKey(new Hex(bootnode.NodeId))), bootnode.Host, bootnode.Port, true);

                var manager = _discoveryManager.GetNodeLifecycleManager(node);
                managers[i] = manager;
            }

            //Wait for pong message to come back from Boot nodes
            var maxWaitTime = _configurationProvider.BootNodePongTimeout;
            var itemTime    = maxWaitTime / 100;

            for (var i = 0; i < 100; i++)
            {
                if (managers.Any(x => x.State == NodeLifecycleState.Active))
                {
                    break;
                }

                if (_logger.IsDebugEnabled)
                {
                    _logger.Debug($"Waiting {itemTime} ms for bootnodes to respond");
                }

                await Task.Delay(1000);
            }

            var reachedNodeCounter = 0;

            for (var i = 0; i < managers.Length; i++)
            {
                var manager = managers[i];
                if (manager.State != NodeLifecycleState.Active)
                {
                    if (_logger.IsWarnEnabled)
                    {
                        _logger.Warn($"Cannot reach bootnode: {manager.ManagedNode.Host}:{manager.ManagedNode.Port}");
                    }
                }
                else
                {
                    reachedNodeCounter++;
                }
            }

            return(reachedNodeCounter > 0);
        }
コード例 #15
0
 public EvictionPair(INodeLifecycleManager evictionCandidate, INodeLifecycleManager replacementCandidate)
 {
     EvictionCandidate    = evictionCandidate;
     ReplacementCandidate = replacementCandidate;
 }