Exemple #1
0
		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;
		}
Exemple #2
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);
			}
		}
Exemple #3
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);
			}
		}
Exemple #4
0
		/// <summary>
		/// Configure the components of the wallet
		/// </summary>
		/// <param name="group">The group to use</param>
		public void Configure(NodesGroup group)
		{
			if(group == null)
				throw new ArgumentNullException("group");

			var 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);
			}
			var wallet = FindWalletBehavior(parameters.TemplateBehaviors);
			if(wallet == null)
			{
				wallet = new WalletBehavior(this);
				parameters.TemplateBehaviors.Add(wallet);
			}
			var broadcast = parameters.TemplateBehaviors.Find<BroadcastHubBehavior>();
			if(broadcast == null)
			{
				broadcast = new BroadcastHubBehavior();
				parameters.TemplateBehaviors.Add(broadcast);
			}

			_Group = group;
			if(_ListenedTracker != null)
			{
				_ListenedTracker.NewOperation -= _ListenerTracked_NewOperation;
			}
			_ListenedTracker = tracker.Tracker;
			_ListenedTracker.NewOperation += _ListenerTracked_NewOperation;
		}
Exemple #5
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);
			}
		}
Exemple #6
0
		/// <summary>
		/// Connect the wallet by using the group's parameters
		/// </summary>
		/// <param name="group"></param>
		public void Connect(NodesGroup group)
		{
			Connect(group.NodeConnectionParameters);
		}