internal NodeConnectionParameters CreateNodeConnectionParameters()
        {
            IPEndPoint myExternal           = Utils.EnsureIPv6(this.ExternalEndpoint);
            NodeConnectionParameters param2 = this.InboundNodeConnectionParameters.Clone();

            param2.Nonce       = this.Nonce;
            param2.Version     = this.Version;
            param2.AddressFrom = myExternal;
            return(param2);
        }
예제 #2
0
        public static Node Connect(NetworkInfo network,
                                   IPEndPoint endpoint,
                                   NodeConnectionParameters parameters)
        {
            var peer = new NetworkAddress()
            {
                Time     = DateTimeOffset.UtcNow,
                Endpoint = endpoint
            };

            return(new Node(peer, network, parameters));
        }
예제 #3
0
        private void InitDefaultBehaviors(NodeConnectionParameters parameters)
        {
            IsTrusted = parameters.IsTrusted != null ? parameters.IsTrusted.Value : Peer.Endpoint.Address.IsLocal();
            //	Advertize = parameters.Advertize;
            //	PreferredTransactionOptions = parameters.PreferredTransactionOptions;
            _ReuseBuffer = parameters.ReuseBuffer;

            _Behaviors.DelayAttach = true;
            foreach (var behavior in parameters.TemplateBehaviors)
            {
                _Behaviors.Add(behavior.Clone());
            }
            _Behaviors.DelayAttach = false;
        }
예제 #4
0
		public NodesGroup(
			Network network,
			NodeConnectionParameters connectionParameters = null,
			NodeRequirement requirements = null)
		{
			AllowSameGroup = false;
			MaximumNodeConnection = 8;
			_Network = network;
			cs = new object();
			_ConnectedNodes = new NodesCollection();
			_ConnectionParameters = connectionParameters ?? new NodeConnectionParameters();
			_ConnectionParameters = _ConnectionParameters.Clone();
			_Requirements = requirements ?? new NodeRequirement();
			_Disconnect = new CancellationTokenSource();
		}
예제 #5
0
 public NodesGroup(
     Network network,
     NodeConnectionParameters connectionParameters = null,
     NodeRequirement requirements = null)
 {
     AllowSameGroup        = false;
     MaximumNodeConnection = 8;
     _Network              = network;
     cs                    = new object();
     _ConnectedNodes       = new NodesCollection();
     _ConnectionParameters = connectionParameters ?? new NodeConnectionParameters();
     _ConnectionParameters = _ConnectionParameters.Clone();
     _Requirements         = requirements ?? new NodeRequirement();
     _Disconnect           = new CancellationTokenSource();
 }
예제 #6
0
 public NodeConnectionParameters(NodeConnectionParameters other)
 {
     Version             = other.Version;
     IsRelay             = other.IsRelay;
     Services            = other.Services;
     ConnectCancellation = other.ConnectCancellation;
     UserAgent           = other.UserAgent;
     AddressFrom         = other.AddressFrom;
     Nonce     = other.Nonce;
     Advertize = other.Advertize;
     PreferredTransactionOptions = other.PreferredTransactionOptions;
     EndpointConnector           = other.EndpointConnector.Clone();
     SocketSettings = other.SocketSettings.Clone();
     foreach (var behavior in other.TemplateBehaviors)
     {
         TemplateBehaviors.Add(behavior.Clone());
     }
 }
예제 #7
0
 public NodeConnectionParameters(NodeConnectionParameters other)
 {
     Version             = other.Version;
     IsRelay             = other.IsRelay;
     Services            = other.Services;
     ReceiveBufferSize   = other.ReceiveBufferSize;
     SendBufferSize      = other.SendBufferSize;
     ConnectCancellation = other.ConnectCancellation;
     UserAgent           = other.UserAgent;
     AddressFrom         = other.AddressFrom;
     Nonce     = other.Nonce;
     Advertize = other.Advertize;
     PreferredTransactionOptions = other.PreferredTransactionOptions;
     foreach (var behavior in other.TemplateBehaviors)
     {
         TemplateBehaviors.Add(behavior.Clone());
     }
 }
예제 #8
0
		public NodeServer(Network network, ProtocolVersion version = ProtocolVersion.PROTOCOL_VERSION,
			int internalPort = -1)
		{
			AllowLocalPeers = true;
			InboundNodeConnectionParameters = new NodeConnectionParameters();
			internalPort = internalPort == -1 ? network.DefaultPort : internalPort;
			_LocalEndpoint = new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6Ex(), internalPort);
			_Network = network;
			_ExternalEndpoint = new IPEndPoint(_LocalEndpoint.Address, Network.DefaultPort);
			_Version = version;
			var listener = new EventLoopMessageListener<IncomingMessage>(ProcessMessage);
			_MessageProducer.AddMessageListener(listener);
			OwnResource(listener);
			_ConnectedNodes = new NodesCollection();
			_ConnectedNodes.Added += _Nodes_NodeAdded;
			_ConnectedNodes.Removed += _Nodes_NodeRemoved;
			_ConnectedNodes.MessageProducer.AddMessageListener(listener);
			_Trace = new TraceCorrelation(NodeServerTrace.Trace, "Node server listening on " + LocalEndpoint);
		}
예제 #9
0
        public NodeServer(NetworkInfo network, ProtocolVersion version = ProtocolVersion.PROTOCOL_VERSION, int internalPort = -1)
        {
            AllowLocalPeers = true;
            InboundNodeConnectionParameters = new NodeConnectionParameters();
            internalPort   = internalPort == -1 ? network.DefaultPort : internalPort;
            _LocalEndpoint = new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6Ex(), internalPort);
            _Network       = network;
            //_ExternalEndpoint = new IPEndPoint(_LocalEndpoint.Address, Network.DefaultPort); //TODO
            _Version = version;
            var listener = new EventLoopMessageListener <IncomingMessage>(ProcessMessage);

            _MessageProducer.AddMessageListener(listener);
            OwnResource(listener);
            _ConnectedNodes          = new NodesCollection();
            _ConnectedNodes.Added   += _Nodes_NodeAdded;
            _ConnectedNodes.Removed += _Nodes_NodeRemoved;
            _ConnectedNodes.MessageProducer.AddMessageListener(listener);
            _Trace = new TraceCorrelation(NodeServerTrace.Trace, "Node server listening on " + LocalEndpoint);
        }
        public NodeConnectionParameters(NodeConnectionParameters other)
        {
            Version             = other.Version;
            IsRelay             = other.IsRelay;
            Services            = other.Services;
            ReceiveBufferSize   = other.ReceiveBufferSize;
            SendBufferSize      = other.SendBufferSize;
            ConnectCancellation = other.ConnectCancellation;
            UserAgent           = other.UserAgent;
            AddressFrom         = other.AddressFrom;
            IsTrusted           = other.IsTrusted;
            Nonce       = other.Nonce;
            Advertize   = other.Advertize;
            ReuseBuffer = other.ReuseBuffer;

            foreach (var behavior in other.TemplateBehaviors)
            {
                TemplateBehaviors.Add((NodeBehavior)((ICloneable)behavior).Clone());
            }
        }
예제 #11
0
        public NodeServer(Network network, uint?version = null,
                          int internalPort = -1)
        {
            AllowLocalPeers = true;
            InboundNodeConnectionParameters = new NodeConnectionParameters();
            internalPort      = internalPort == -1 ? network.DefaultPort : internalPort;
            _LocalEndpoint    = new IPEndPoint(IPAddress.Parse("0.0.0.0").MapToIPv6Ex(), internalPort);
            MaxConnections    = 125;
            _Network          = network;
            _ExternalEndpoint = new IPEndPoint(_LocalEndpoint.Address, Network.DefaultPort);
            _Version          = version == null ? network.MaxP2PVersion : version.Value;
            var listener = new EventLoopMessageListener <IncomingMessage>(ProcessMessage);

            _MessageProducer.AddMessageListener(listener);
            OwnResource(listener);
            _ConnectedNodes          = new NodesCollection();
            _ConnectedNodes.Added   += _Nodes_NodeAdded;
            _ConnectedNodes.Removed += _Nodes_NodeRemoved;
            _ConnectedNodes.MessageProducer.AddMessageListener(listener);
        }
예제 #12
0
		public NodeConnectionParameters(NodeConnectionParameters other)
		{
			Version = other.Version;
			IsRelay = other.IsRelay;
			Services = other.Services;
			ReceiveBufferSize = other.ReceiveBufferSize;
			SendBufferSize = other.SendBufferSize;
			ConnectCancellation = other.ConnectCancellation;
			UserAgent = other.UserAgent;
			AddressFrom = other.AddressFrom;
			IsTrusted = other.IsTrusted;
			Nonce = other.Nonce;
			Advertize = other.Advertize;
			ReuseBuffer = other.ReuseBuffer;

			foreach(var behavior in other.TemplateBehaviors)
			{
				TemplateBehaviors.Add((NodeBehavior)((ICloneable)behavior).Clone());
			}
		}
        public NodeConnectionParameters(NodeConnectionParameters other)
        {
            this.Version             = other.Version;
            this.IsRelay             = other.IsRelay;
            this.Services            = other.Services;
            this.ReceiveBufferSize   = other.ReceiveBufferSize;
            this.SendBufferSize      = other.SendBufferSize;
            this.ConnectCancellation = other.ConnectCancellation;
            this.UserAgent           = other.UserAgent;
            this.AddressFrom         = other.AddressFrom;
            this.Nonce       = other.Nonce;
            this.Advertize   = other.Advertize;
            this.ReuseBuffer = other.ReuseBuffer;
            this.PreferredTransactionOptions = other.PreferredTransactionOptions;

            foreach (INodeBehavior behavior in other.TemplateBehaviors)
            {
                this.TemplateBehaviors.Add(behavior.Clone());
            }
        }
예제 #14
0
 internal Node(NetworkAddress peer, NetworkInfo network, NodeConnectionParameters parameters, Socket socket, VersionPayload peerVersion)
 {
     _RemoteSocketAddress = ((IPEndPoint)socket.RemoteEndPoint).Address;
     _RemoteSocketPort    = ((IPEndPoint)socket.RemoteEndPoint).Port;
     Inbound      = true;
     _Behaviors   = new NodeBehaviorsCollection(this);
     _MyVersion   = parameters.CreateVersion(peer.Endpoint, network);
     Network      = network;
     _Peer        = peer;
     _Connection  = new NodeConnection(this, socket);
     _PeerVersion = peerVersion;
     LastSeen     = peer.Time;
     ConnectedAt  = DateTimeOffset.UtcNow;
     TraceCorrelation.LogInside(() =>
     {
         NodeServerTrace.Information("Connected to advertised node " + _Peer.Endpoint);
         State = NodeState.Connected;
     });
     InitDefaultBehaviors(parameters);
     _Connection.BeginListen();
 }
예제 #15
0
 /// <summary>
 /// Connect to a random node on the network
 /// </summary>
 /// <param name="network">The network to connect to</param>
 /// <param name="addrman">The addrman used for finding peers</param>
 /// <param name="parameters">The parameters used by the found node</param>
 /// <param name="connectedAddresses">The already connected addresses, the new address will be select outside of existing groups</param>
 /// <returns></returns>
 public static Node Connect(NetworkInfo network, AddressManager addrman, NodeConnectionParameters parameters = null, IPAddress[] connectedAddresses = null)
 {
     parameters = parameters ?? new NodeConnectionParameters();
     AddressManagerBehavior.SetAddrman(parameters, addrman);
     return(Connect(network, parameters, connectedAddresses));
 }
예제 #16
0
 public static NodesGroup GetNodeGroup(NodeConnectionParameters parameters)
 {
     return(GetNodeGroup(parameters.TemplateBehaviors));
 }
예제 #17
0
 /// <summary>
 /// Connect to the node of this machine
 /// </summary>
 /// <param name="network"></param>
 /// <param name="parameters"></param>
 /// <returns></returns>
 public static Node ConnectToLocal(NetworkInfo network,
                                   NodeConnectionParameters parameters)
 {
     return(Connect(network, Utils.ParseIpEndpoint("localhost", network.DefaultPort), parameters));
 }
예제 #18
0
        internal Node(NetworkAddress peer, NetworkInfo network, NodeConnectionParameters parameters)
        {
            parameters = parameters ?? new NodeConnectionParameters();
            var addrman = AddressManagerBehavior.GetAddrman(parameters);

            Inbound    = false;
            _Behaviors = new NodeBehaviorsCollection(this);
            _MyVersion = parameters.CreateVersion(peer.Endpoint, network);
            Network    = network;
            _Peer      = peer;
            LastSeen   = peer.Time;

            var socket = new Socket(AddressFamily.InterNetworkV6, SocketType.Stream, ProtocolType.Tcp);

            socket.SetSocketOption(SocketOptionLevel.IPv6, SocketOptionName.IPv6Only, false);

            _Connection = new NodeConnection(this, socket);
            socket.ReceiveBufferSize = parameters.ReceiveBufferSize;
            socket.SendBufferSize    = parameters.SendBufferSize;
            using (TraceCorrelation.Open())
            {
                try
                {
                    var completed = new ManualResetEvent(false);
                    var args      = new SocketAsyncEventArgs();
                    args.RemoteEndPoint = peer.Endpoint;
                    args.Completed     += (s, a) =>
                    {
                        Utils.SafeSet(completed);
                    };
                    if (!socket.ConnectAsync(args))
                    {
                        completed.Set();
                    }
                    WaitHandle.WaitAny(new WaitHandle[] { completed, parameters.ConnectCancellation.WaitHandle });
                    parameters.ConnectCancellation.ThrowIfCancellationRequested();
                    if (args.SocketError != SocketError.Success)
                    {
                        throw new SocketException((int)args.SocketError);
                    }
                    var remoteEndpoint = (IPEndPoint)(socket.RemoteEndPoint ?? args.RemoteEndPoint);
                    _RemoteSocketAddress = remoteEndpoint.Address;
                    _RemoteSocketPort    = remoteEndpoint.Port;
                    State       = NodeState.Connected;
                    ConnectedAt = DateTimeOffset.UtcNow;
                    NodeServerTrace.Information("Outbound connection successfull");
                    if (addrman != null)
                    {
                        addrman.Attempt(Peer);
                    }
                }
                catch (OperationCanceledException)
                {
                    Utils.SafeCloseSocket(socket);
                    NodeServerTrace.Information("Connection to node cancelled");
                    State = NodeState.Offline;
                    if (addrman != null)
                    {
                        addrman.Attempt(Peer);
                    }
                    throw;
                }
                catch (Exception ex)
                {
                    Utils.SafeCloseSocket(socket);
                    NodeServerTrace.Error("Error connecting to the remote endpoint ", ex);
                    DisconnectReason = new NodeDisconnectReason()
                    {
                        Reason    = "Unexpected exception while connecting to socket",
                        Exception = ex
                    };
                    State = NodeState.Failed;
                    if (addrman != null)
                    {
                        addrman.Attempt(Peer);
                    }
                    throw;
                }
                InitDefaultBehaviors(parameters);
                _Connection.BeginListen();
            }
        }
예제 #19
0
파일: spv_tests.cs 프로젝트: vebin/NBitcoin
		private static NodesGroup CreateGroup(NodeServerTester servers, int connections)
		{
			AddressManagerBehavior behavior = new AddressManagerBehavior(new AddressManager());
			if(connections == 1)
			{
				behavior.AddressManager.Add(new NetworkAddress(servers.Server1.ExternalEndpoint), IPAddress.Parse("127.0.0.1"));
			}
			if(connections > 1)
			{
				behavior.AddressManager.Add(new NetworkAddress(servers.Server2.ExternalEndpoint), IPAddress.Parse("127.0.0.1"));
			}
			NodeConnectionParameters parameters = new NodeConnectionParameters();
			parameters.TemplateBehaviors.Add(behavior);
			Wallet.ConfigureDefaultNodeConnectionParameters(parameters);
			parameters.IsTrusted = true;
			NodesGroup connected = new NodesGroup(Network.TestNet, parameters);
			connected.AllowSameGroup = true;
			connected.MaximumNodeConnection = connections;
			return connected;
		}
예제 #20
0
		public void CanMaintainConnectionToNodes()
		{
			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				servers.Server1.InboundNodeConnectionParameters.Services = NodeServices.Network;
				AddressManagerBehavior behavior = new AddressManagerBehavior(new AddressManager());
				behavior.AddressManager.Add(new NetworkAddress(servers.Server1.ExternalEndpoint), IPAddress.Parse("127.0.0.1"));
				NodeConnectionParameters parameters = new NodeConnectionParameters();
				parameters.TemplateBehaviors.Add(behavior);
				NodesGroup connected = new NodesGroup(Network.TestNet, parameters, new NodeRequirement()
				{
					RequiredServices = NodeServices.Network
				});
				connected.AllowSameGroup = true;
				connected.MaximumNodeConnection = 2;
				connected.Connect();

				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 2);

				//Server crash abruptly
				servers.Server1.ConnectedNodes.First().Disconnect();
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);

				//Reconnect ?
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 2);

				//Client crash abruptly
				connected.ConnectedNodes.First().Disconnect();
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);

				//Reconnect ?
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 2);
			}
		}
예제 #21
0
 public static Node Connect(NetworkInfo network,
                            NetworkAddress endpoint,
                            NodeConnectionParameters parameters)
 {
     return(new Node(endpoint, network, parameters));
 }
예제 #22
0
        internal void DiscoverPeers(Network network, NodeConnectionParameters parameters, int peerToFind)
        {
            TimeSpan backoff = TimeSpan.Zero;

            Logs.NodeServer.LogTrace("Discovering nodes");

            int found = 0;

            {
                while (found < peerToFind)
                {
                    Thread.Sleep(backoff);
                    backoff = backoff == TimeSpan.Zero ? TimeSpan.FromSeconds(1.0) : TimeSpan.FromSeconds(backoff.TotalSeconds * 2);
                    if (backoff > TimeSpan.FromSeconds(10.0))
                    {
                        backoff = TimeSpan.FromSeconds(10.0);
                    }

                    parameters.ConnectCancellation.ThrowIfCancellationRequested();

                    Logs.NodeServer.LogTrace("Remaining peer to get {remainingPeerCount}", (-found + peerToFind));

                    List <NetworkAddress> peers = new List <NetworkAddress>();
                    peers.AddRange(this.GetAddr());
                    if (peers.Count == 0)
                    {
                        PopulateTableWithDNSNodes(network, peers).GetAwaiter().GetResult();
                        PopulateTableWithHardNodes(network, peers);
                        peers = new List <NetworkAddress>(peers.OrderBy(a => RandomUtils.GetInt32()));
                        if (peers.Count == 0)
                        {
                            return;
                        }
                    }

                    CancellationTokenSource peerTableFull = new CancellationTokenSource();
                    CancellationToken       loopCancel    = CancellationTokenSource.CreateLinkedTokenSource(peerTableFull.Token, parameters.ConnectCancellation).Token;
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken      = loopCancel,
                        }, p =>
                        {
                            using (CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5)))
                                using (var cancelConnection = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, loopCancel))
                                {
                                    Node n = null;
                                    try
                                    {
                                        var param2 = parameters.Clone();
                                        param2.ConnectCancellation = cancelConnection.Token;
                                        var addrman = param2.TemplateBehaviors.Find <AddressManagerBehavior>();
                                        param2.TemplateBehaviors.Clear();
                                        param2.TemplateBehaviors.Add(addrman);
                                        n = Node.Connect(network, p.Endpoint, param2);
                                        n.VersionHandshake(cancelConnection.Token);
                                        n.MessageReceived += (s, a) =>
                                        {
                                            var addr = (a.Message.Payload as AddrPayload);
                                            if (addr != null)
                                            {
                                                Interlocked.Add(ref found, addr.Addresses.Length);
                                                backoff = TimeSpan.FromSeconds(0);
                                                if (found >= peerToFind)
                                                {
                                                    peerTableFull.Cancel();
                                                }
                                            }
                                        };
                                        n.SendMessageAsync(new GetAddrPayload());
                                        loopCancel.WaitHandle.WaitOne(2000);
                                    }
                                    catch
                                    {
                                    }
                                    finally
                                    {
                                        if (n != null)
                                        {
                                            n.DisconnectAsync();
                                        }
                                    }
                                }
                            if (found >= peerToFind)
                            {
                                peerTableFull.Cancel();
                            }
                            else
                            {
                                Logs.NodeServer.LogInformation("Need {neededPeerCount} more peers", (-found + peerToFind));
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                        if (parameters.ConnectCancellation.IsCancellationRequested)
                        {
                            throw;
                        }
                    }
                }
            }
        }
예제 #23
0
파일: Wallet.cs 프로젝트: vebin/NBitcoin
		public static void ConfigureDefaultNodeConnectionParameters(NodeConnectionParameters parameters)
		{
			parameters = parameters ?? new NodeConnectionParameters();
			parameters.IsTrusted = false; //Connecting to the wild

			//Optimize for small device
			parameters.ReuseBuffer = false;
			parameters.SendBufferSize = 1024 * 100;
			parameters.ReceiveBufferSize = 1024 * 100;
			parameters.IsRelay = false;

			parameters.TemplateBehaviors.FindOrCreate<PingPongBehavior>();	//Ping Pong
		}
예제 #24
0
파일: Wallet.cs 프로젝트: vebin/NBitcoin
		/// <summary>
		/// Configure the components of the wallet
		/// </summary>
		/// <param name="parameters">The parameters to the connection</param>
		public void Configure(NodeConnectionParameters parameters)
		{
			if(parameters == null)
				throw new ArgumentNullException("parameters");
			Configure(new NodesGroup(_Parameters.Network, parameters));
		}
예제 #25
0
파일: Wallet.cs 프로젝트: vebin/NBitcoin
		/// <summary>
		/// Configure the components of the wallet
		/// </summary>
		/// <param name="chain">The chain to keep in sync, if not provided the whole chain will be downloaded on the network (more than 30MB)</param>
		/// <param name="addrman">The Address Manager for speeding up peer discovery</param>
		/// <param name="tracker">The tracker responsible for providing bloom filters</param>
		public void Configure(ConcurrentChain chain = null,
							AddressManager addrman = null,
							Tracker tracker = null)
		{
			if(State != WalletState.Created)
				throw new InvalidOperationException("The wallet is already connecting or connected");

			var parameters = new NodeConnectionParameters();
			ConfigureDefaultNodeConnectionParameters(parameters);


			//Pick the behaviors
			if(addrman != null)
				parameters.TemplateBehaviors.Add(new AddressManagerBehavior(addrman));	//Listen addr, help for node discovery
			if(chain != null)
				parameters.TemplateBehaviors.Add(new ChainBehavior(chain));	//Keep chain in sync
			if(tracker != null)
				parameters.TemplateBehaviors.Add(new TrackerBehavior(tracker, chain)); //Set bloom filters and scan the blockchain

			Configure(parameters);
		}
예제 #26
0
		/// <summary>
		/// Connect the wallet with the given connection parameters
		/// </summary>
		/// <param name="parameters"></param>
		public void Connect(NodeConnectionParameters parameters)
		{
			if(State != WalletState.Created)
				throw new InvalidOperationException("The wallet is already connecting or connected");
			var group = NodesGroup.GetNodeGroup(parameters);
			if(group == null)
			{
				group = new NodesGroup(_Parameters.Network, parameters);
			}
			parameters = group.NodeConnectionParameters;
			group.Requirements.MinVersion = ProtocolVersion.PROTOCOL_VERSION;
			group.Requirements.RequiredServices = NodeServices.Network;

			var chain = parameters.TemplateBehaviors.Find<ChainBehavior>();
			if(chain == null)
			{
				chain = new ChainBehavior(new ConcurrentChain(_Parameters.Network));
				parameters.TemplateBehaviors.Add(chain);
			}
			if(chain.Chain.Genesis.HashBlock != _Parameters.Network.GetGenesis().GetHash())
				throw new InvalidOperationException("ChainBehavior with invalid network chain detected");

			var addrman = parameters.TemplateBehaviors.Find<AddressManagerBehavior>();
			if(addrman == null)
			{
				addrman = new AddressManagerBehavior(new AddressManager());
				parameters.TemplateBehaviors.Add(addrman);
			}

			var tracker = parameters.TemplateBehaviors.Find<TrackerBehavior>();
			if(tracker == null)
			{
				tracker = new TrackerBehavior(new Tracker(), chain.Chain);
				parameters.TemplateBehaviors.Add(tracker);
			}

			_Chain = chain.Chain;
			_AddressManager = addrman.AddressManager;
			_Tracker = tracker.Tracker;
			_TrackerBehavior = tracker;
			_Group = group;
			if(AddKnownScriptToTracker())
				_Group.Purge("Bloom filter renew");
			_State = WalletState.Disconnected;
			_Group.Connect();
			_Group.ConnectedNodes.Added += ConnectedNodes_Added;
			_Group.ConnectedNodes.Removed += ConnectedNodes_Added;
			foreach(var node in _Group.ConnectedNodes)
			{
				node.Behaviors.Find<TrackerBehavior>().Scan(_ScanLocation, Created);
			}
		}
예제 #27
0
		public void CanSyncWalletCore(WalletCreation creation)
		{
			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				var chainBuilder = new BlockchainBuilder();

				//Simulate SPV compatible server
				servers.Server1.InboundNodeConnectionParameters.Services = NodeServices.Network;
				servers.Server1.InboundNodeConnectionParameters.TemplateBehaviors.Add(new ChainBehavior(chainBuilder.Chain)
				{
					AutoSync = false
				});
				servers.Server1.InboundNodeConnectionParameters.TemplateBehaviors.Add(new SPVBehavior(chainBuilder));
				/////////////

				//The SPV client does not verify the chain and keep one connection alive with Server1
				NodeConnectionParameters parameters = new NodeConnectionParameters();
				Wallet.ConfigureDefaultNodeConnectionParameters(parameters);
				parameters.IsTrusted = true;
				AddressManagerBehavior addrman = new AddressManagerBehavior(new AddressManager());
				addrman.AddressManager.Add(new NetworkAddress(servers.Server1.ExternalEndpoint), IPAddress.Parse("127.0.0.1"));
				parameters.TemplateBehaviors.Add(addrman);
				NodesGroup connected = new NodesGroup(Network.TestNet, parameters);
				connected.AllowSameGroup = true;
				connected.MaximumNodeConnection = 1;
				/////////////

				Wallet wallet = new Wallet(creation, keyPoolSize: 11);
				Assert.True(wallet.State == WalletState.Created);
				wallet.Connect(connected);
				Assert.True(wallet.State == WalletState.Disconnected);
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);
				Assert.True(wallet.State == WalletState.Connected);

				chainBuilder.FindBlock();
				TestUtils.Eventually(() => wallet.Chain.Height == 1);
				for(int i = 0 ; i < 9 ; i++)
				{
					wallet.GetNextScriptPubKey();
				}
				wallet.GetNextScriptPubKey(); //Should provoke purge
				TestUtils.Eventually(() => wallet.State == WalletState.Disconnected && wallet.ConnectedNodes == 0);
				TestUtils.Eventually(() => wallet.ConnectedNodes == 1);
				TestUtils.Eventually(() => servers.Server1.ConnectedNodes.Count == 1);
				var spv = servers.Server1.ConnectedNodes.First().Behaviors.Find<SPVBehavior>();
				TestUtils.Eventually(() => spv._Filter != null);

				var k = wallet.GetNextScriptPubKey();
				Assert.Equal(creation.UseP2SH, k.GetDestinationAddress(Network.TestNet) is BitcoinScriptAddress);
				chainBuilder.GiveMoney(k, Money.Coins(1.0m));
				TestUtils.Eventually(() => wallet.GetTransactions().Count == 1);
				chainBuilder.FindBlock();
				TestUtils.Eventually(() => wallet.GetTransactions().Where(t => t.BlockInformation != null).Count() == 1);

				chainBuilder.Broadcast = false;
				chainBuilder.GiveMoney(k, Money.Coins(1.5m));
				chainBuilder.Broadcast = true;
				chainBuilder.FindBlock();
				TestUtils.Eventually(() => wallet.GetTransactions().Summary.Confirmed.TransactionCount == 2);

				chainBuilder.Broadcast = false;
				for(int i = 0 ; i < 30 ; i++)
				{
					chainBuilder.FindBlock();
				}
				chainBuilder.GiveMoney(k, Money.Coins(0.001m));
				chainBuilder.FindBlock();
				chainBuilder.Broadcast = true;
				chainBuilder.FindBlock();
				//Sync automatically
				TestUtils.Eventually(() => wallet.GetTransactions().Summary.Confirmed.TransactionCount == 3);

				MemoryStream ms = new MemoryStream();
				wallet.Save(ms);
				ms.Position = 0;
				var wallet2 = Wallet.Load(ms);
				wallet2.Connect(connected);
				Assert.Equal(wallet.Created, wallet2.Created);
				Assert.Equal(wallet.GetNextScriptPubKey(), wallet2.GetNextScriptPubKey());
				Assert.True(wallet.GetKnownScripts().Length == wallet2.GetKnownScripts().Length);

				var fork = wallet.Chain.FindFork(wallet2._ScanLocation);
				Assert.True(fork.Height == chainBuilder.Chain.Height - 5);
			}
		}
예제 #28
0
 public static Node Connect(NetworkInfo network,
                            string endpoint, NodeConnectionParameters parameters)
 {
     return(Connect(network, Utils.ParseIpEndpoint(endpoint, network.DefaultPort), parameters));
 }
예제 #29
0
		internal void DiscoverPeers(Network network, NodeConnectionParameters parameters)
		{
			int peerToFind = 1000;
			TraceCorrelation traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
			int found = 0;

			using(traceCorrelation.Open())
			{
				while(found < peerToFind)
				{
					parameters.ConnectCancellation.ThrowIfCancellationRequested();
					NodeServerTrace.PeerTableRemainingPeerToGet(-found + peerToFind);
					List<NetworkAddress> peers = new List<NetworkAddress>();
					peers.AddRange(this.GetAddr());
					if(peers.Count == 0)
					{
						PopulateTableWithDNSNodes(network, peers);
						PopulateTableWithHardNodes(network, peers);
						peers = new List<NetworkAddress>(peers.OrderBy(a => RandomUtils.GetInt32()));
					}


					CancellationTokenSource peerTableFull = new CancellationTokenSource();
					CancellationToken loopCancel = CancellationTokenSource.CreateLinkedTokenSource(peerTableFull.Token, parameters.ConnectCancellation).Token;
					try
					{
						Parallel.ForEach(peers, new ParallelOptions()
						{
							MaxDegreeOfParallelism = 5,
							CancellationToken = loopCancel,
						}, p =>
						{
							CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
							var cancelConnection = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, loopCancel);
							Node n = null;
							try
							{
								var param2 = parameters.Clone();
								param2.ConnectCancellation = cancelConnection.Token;
								var addrman = param2.TemplateBehaviors.Find<AddressManagerBehavior>();
								param2.TemplateBehaviors.Clear();
								param2.TemplateBehaviors.Add(addrman);
								n = Node.Connect(network, p.Endpoint, param2);
								n.VersionHandshake(cancelConnection.Token);
								n.MessageReceived += (s, a) =>
								{
									var addr = (a.Message.Payload as AddrPayload);
									if(addr != null)
									{
										Interlocked.Add(ref found, addr.Addresses.Length);
										if(found >= peerToFind)
											peerTableFull.Cancel();
									}
								};
								n.SendMessageAsync(new GetAddrPayload());
								loopCancel.WaitHandle.WaitOne(2000);
							}
							catch
							{
							}
							finally
							{
								if(n != null)
									n.DisconnectAsync();
							}
							if(found >= peerToFind)
								peerTableFull.Cancel();
							else
								NodeServerTrace.Information("Need " + (-found + peerToFind) + " more peers");
						});
					}
					catch(OperationCanceledException)
					{
						if(parameters.ConnectCancellation.IsCancellationRequested)
							throw;
					}
				}
			}
		}
예제 #30
0
        public void DiscoverPeers(Network network, NodeConnectionParameters parameters, int peerToFind)
        {
            TraceCorrelation traceCorrelation = new TraceCorrelation(NodeServerTrace.Trace, "Discovering nodes");
            int found = 0;

            using (traceCorrelation.Open())
            {
                while (found < peerToFind)
                {
                    parameters.ConnectCancellation.ThrowIfCancellationRequested();
                    NodeServerTrace.PeerTableRemainingPeerToGet(-found + peerToFind);
                    List <NetworkAddress> peers = new List <NetworkAddress>();
                    peers.AddRange(this.GetAddr());
                    if (peers.Count == 0)
                    {
                        PopulateTableWithDNSNodes(network, peers);
                        PopulateTableWithHardNodes(network, peers);
                        peers = new List <NetworkAddress>(peers.OrderBy(a => RandomUtils.GetInt32()));
                        if (peers.Count == 0)
                        {
                            return;
                        }
                    }


                    CancellationTokenSource peerTableFull = new CancellationTokenSource();
                    CancellationToken       loopCancel    = CancellationTokenSource.CreateLinkedTokenSource(peerTableFull.Token, parameters.ConnectCancellation).Token;
                    try
                    {
                        Parallel.ForEach(peers, new ParallelOptions()
                        {
                            MaxDegreeOfParallelism = 5,
                            CancellationToken      = loopCancel,
                        }, p =>
                        {
                            CancellationTokenSource timeout = new CancellationTokenSource(TimeSpan.FromSeconds(5));
                            var cancelConnection            = CancellationTokenSource.CreateLinkedTokenSource(timeout.Token, loopCancel);
                            Node n = null;
                            try
                            {
                                var param2 = parameters.Clone();
                                param2.ConnectCancellation = cancelConnection.Token;
                                var addrman = param2.TemplateBehaviors.Find <AddressManagerBehavior>();
                                param2.TemplateBehaviors.Clear();
                                param2.TemplateBehaviors.Add(addrman);
                                n = Node.Connect(network, p.Endpoint, param2);
                                n.VersionHandshake(cancelConnection.Token);
                                n.MessageReceived += (s, a) =>
                                {
                                    var addr = (a.Message.Payload as AddrPayload);
                                    if (addr != null)
                                    {
                                        Interlocked.Add(ref found, addr.Addresses.Length);
                                        if (found >= peerToFind)
                                        {
                                            peerTableFull.Cancel();
                                        }
                                    }
                                };
                                n.SendMessageAsync(new GetAddrPayload());
                                loopCancel.WaitHandle.WaitOne(2000);
                            }
                            catch
                            {
                            }
                            finally
                            {
                                if (n != null)
                                {
                                    n.DisconnectAsync();
                                }
                            }
                            if (found >= peerToFind)
                            {
                                peerTableFull.Cancel();
                            }
                            else
                            {
                                NodeServerTrace.Information("Need " + (-found + peerToFind) + " more peers");
                            }
                        });
                    }
                    catch (OperationCanceledException)
                    {
                        if (parameters.ConnectCancellation.IsCancellationRequested)
                        {
                            throw;
                        }
                    }
                }
            }
        }
예제 #31
0
		public static NodesGroup GetNodeGroup(NodeConnectionParameters parameters)
		{
			return GetNodeGroup(parameters.TemplateBehaviors);
		}
예제 #32
0
		public void CanConnectToRandomNode()
		{
			Stopwatch watch = new Stopwatch();
			NodeConnectionParameters parameters = new NodeConnectionParameters();
			var addrman = GetCachedAddrMan("addrmancache.dat");
			parameters.TemplateBehaviors.Add(new AddressManagerBehavior(addrman));
			watch.Start();
			using(var node = Node.Connect(Network.Main, parameters))
			{
				var timeToFind = watch.Elapsed;
				node.VersionHandshake();
				node.Dispose();
				watch.Restart();
				using(var node2 = Node.Connect(Network.Main, parameters))
				{
					var timeToFind2 = watch.Elapsed;
				}
			}
			addrman.SavePeerFile("addrmancache.dat", Network.Main);
		}