Beispiel #1
0
        public void CanRespondToPong()
        {
            if (pos_RPCClientTests.noClient)
            {
                return;
            }

            using (var tester = new NodeServerTester())
            {
                var toS2 = tester.Node1;
                toS2.VersionHandshake();
                var ping = new PingPayload();
                CancellationTokenSource cancel = new CancellationTokenSource();
                cancel.CancelAfter(10000);
                using (var list = toS2.CreateListener())
                {
                    toS2.SendMessageAsync(ping);
                    while (true)
                    {
                        var pong = list.ReceivePayload <PongPayload>(cancel.Token);
                        if (ping.Nonce == pong.Nonce)
                        {
                            break;
                        }
                    }
                }
            }
        }
Beispiel #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);
            }
        }
Beispiel #3
0
        public void CanConnectMultipleTimeToServer()
        {
            using (var tester = new NodeServerTester())
            {
                int nodeCount = 0;
                tester.Server1.NodeAdded   += (s, a) => nodeCount++;
                tester.Server1.NodeRemoved += (s, a) => nodeCount--;

                var n1 = Node.Connect(tester.Server1.Network, tester.Server1.ExternalEndpoint);
                n1.VersionHandshake();
                Thread.Sleep(100);
                Assert.Equal(1, nodeCount);
                n1.PingPong();
                var n2 = Node.Connect(tester.Server1.Network, tester.Server1.ExternalEndpoint);
                n2.VersionHandshake();
                Thread.Sleep(100);
                Assert.Equal(2, nodeCount);
                n2.PingPong();
                n1.PingPong();
                Assert.Throws <ProtocolException>(() => n2.VersionHandshake());
                Thread.Sleep(100);
                n2.PingPong();
                Assert.Equal(2, nodeCount);
                n2.Disconnect();
                Thread.Sleep(100);
                Assert.Equal(1, nodeCount);
            }
        }
Beispiel #4
0
        public void CanExchangeFastPingPong()
        {
            using (var tester = new NodeServerTester())
            {
                var n1 = tester.Node1;
                n1.Behaviors.Add(new PingPongBehavior()
                {
                    PingInterval    = TimeSpan.FromSeconds(0.1),
                    TimeoutInterval = TimeSpan.FromSeconds(0.8)
                });

                n1.VersionHandshake();
                Assert.Equal(NodeState.HandShaked, n1.State);
                Assert.True(!n1.Inbound);

                var n2 = tester.Node2;
                n2.Behaviors.Add(new PingPongBehavior()
                {
                    PingInterval    = TimeSpan.FromSeconds(0.1),
                    TimeoutInterval = TimeSpan.FromSeconds(0.5)
                });
                Assert.Equal(NodeState.HandShaked, n2.State);
                Assert.True(n2.Inbound);
                Thread.Sleep(2000);
                Assert.Equal(NodeState.HandShaked, n2.State);
                n1.Behaviors.Clear();
                Thread.Sleep(1200);
                Assert.True(n2.State == NodeState.Disconnecting || n2.State == NodeState.Offline);
                Assert.StartsWith("Pong timeout", n2.DisconnectReason.Reason, StringComparison.Ordinal);
            }
        }
Beispiel #5
0
 public void CanMaintainChainWithChainBehavior()
 {
     using (var node = Node.ConnectToLocal(Network.TestNet))
     {
         var chain = node.GetChain(uint256.Parse("00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70"));
         Assert.True(chain.Height == 500);
         using (var tester = new NodeServerTester(Network.TestNet))
         {
             var n1 = tester.Node1;
             n1.Behaviors.Add(new ChainBehavior(chain));
             n1.VersionHandshake();
             Assert.True(n1.MyVersion.StartHeight == 500);
             var n2 = tester.Node2;
             Assert.True(n2.MyVersion.StartHeight == 0);
             Assert.True(n2.PeerVersion.StartHeight == 500);
             Assert.True(n1.State == NodeState.HandShaked);
             Assert.True(n2.State == NodeState.HandShaked);
             var behavior = new ChainBehavior(new ConcurrentChain(Network.TestNet));
             n2.Behaviors.Add(behavior);
             TestUtils.Eventually(() => behavior.Chain.Height == 500);
             var chain2 = n2.GetChain(uint256.Parse("00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70"));
             Assert.True(chain2.Height == 500);
             var chain1 = n1.GetChain(uint256.Parse("00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70"));
             Assert.True(chain1.Height == 500);
             chain1 = n1.GetChain(uint256.Parse("000000008cd4b1bdaa1278e3f1708258f862da16858324e939dc650627cd2e27"));
             Assert.True(chain1.Height == 499);
             Thread.Sleep(5000);
         }
     }
 }
Beispiel #6
0
        public void MaxConnectionLimit()
        {
            using (var tester = new NodeServerTester())
            {
                tester.Server1.MaxConnections = 4;
                Node.Connect(tester.Network, tester.Server1.ExternalEndpoint).VersionHandshake();
                Node.Connect(tester.Network, tester.Server1.ExternalEndpoint).VersionHandshake();
                Node.Connect(tester.Network, tester.Server1.ExternalEndpoint).VersionHandshake();
                Node.Connect(tester.Network, tester.Server1.ExternalEndpoint).VersionHandshake();

                TestUtils.Eventually(() => tester.Server1.ConnectedNodes.Count == 4);

                var connect = Node.Connect(tester.Network, tester.Server1.ExternalEndpoint);
                try
                {
                    connect.VersionHandshake();
                }
                catch
                {
                }

                TestUtils.Eventually(() => tester.Server1.ConnectedNodes.Count == 4);
                TestUtils.Eventually(() => connect.IsConnected == false);
            }
        }
Beispiel #7
0
        public void CanMaintainConnectionToNodes()
        {
            using (NodeServerTester servers = new NodeServerTester(Network.TestNet))
            {
                NodesGroup connected = CreateGroup(servers, 2);
                connected.Connect();
                TestUtils.Eventually(() => connected.ConnectedNodes.Count == 2);

                //Server crash abruptly
                servers.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);
                connected.Disconnect();
                TestUtils.Eventually(() => connected.ConnectedNodes.Count == 0);
            }
        }
Beispiel #8
0
 public void CanMaintainChainWithChainBehavior()
 {
     using (var builder = NodeBuilder.Create())
     {
         var node = builder.CreateNode(true).CreateNodeClient();
         builder.Nodes[0].Generate(600);
         var rpc   = builder.Nodes[0].CreateRPCClient();
         var chain = node.GetChain(rpc.GetBlockHash(500));
         Assert.True(chain.Height == 500);
         using (var tester = new NodeServerTester(Network.RegTest))
         {
             var n1 = tester.Node1;
             n1.Behaviors.Add(new ChainBehavior(chain));
             n1.VersionHandshake();
             Assert.True(n1.MyVersion.StartHeight == 500);
             var n2 = tester.Node2;
             Assert.True(n2.MyVersion.StartHeight == 0);
             Assert.True(n2.PeerVersion.StartHeight == 500);
             Assert.True(n1.State == NodeState.HandShaked);
             Assert.True(n2.State == NodeState.HandShaked);
             var behavior = new ChainBehavior(new ConcurrentChain(Network.RegTest));
             n2.Behaviors.Add(behavior);
             TestUtils.Eventually(() => behavior.Chain.Height == 500);
             var chain2 = n2.GetChain(rpc.GetBlockHash(500));
             Assert.True(chain2.Height == 500);
             var chain1 = n1.GetChain(rpc.GetBlockHash(500));
             Assert.True(chain1.Height == 500);
             chain1 = n1.GetChain(rpc.GetBlockHash(499));
             Assert.True(chain1.Height == 499);
             Thread.Sleep(5000);
         }
     }
 }
Beispiel #9
0
 public void CanReceiveHandshake()
 {
     using (var tester = new NodeServerTester())
     {
         var toS2 = tester.Server1.GetNodeByEndpoint(tester.Server2.ExternalEndpoint);
         toS2.VersionHandshake();
         Assert.Equal(NodeState.HandShaked, toS2.State);
         Thread.Sleep(100);                 //Let the time to Server2 to add the new node, else the test was failing sometimes.
         Assert.Equal(NodeState.HandShaked, tester.Server2.GetNodeByEndpoint(toS2.MyVersion.AddressFrom).State);
     }
 }
Beispiel #10
0
 public void CantConnectToYourself()
 {
     using (var tester = new NodeServerTester())
     {
         tester.Server2.Nonce = tester.Server1.Nonce;
         Assert.Throws(typeof(InvalidOperationException), () =>
         {
             tester.Server1.GetNodeByEndpoint(tester.Server2.ExternalEndpoint).VersionHandshake();
         });
     }
 }
Beispiel #11
0
 public void CanReceiveHandshake()
 {
     using (var tester = new NodeServerTester())
     {
         var toS2 = tester.Node1;
         toS2.VersionHandshake();
         Assert.Equal(NodeState.HandShaked, toS2.State);
         Thread.Sleep(100);                 //Let the time to Server2 to add the new node, else the test was failing sometimes.
         Assert.Equal(NodeState.HandShaked, tester.Node2.State);
     }
 }
Beispiel #12
0
 public void CantConnectToYourself()
 {
     using (var tester = new NodeServerTester())
     {
         tester.Server2.Nonce = tester.Server1.Nonce;
         Assert.Throws <InvalidOperationException>(() =>
         {
             tester.Node1.VersionHandshake();
         });
     }
 }
Beispiel #13
0
        public void UseFilterAddIfKeyPoolSizeIsZero()
        {
            using (NodeServerTester servers = new NodeServerTester())
            {
                var chainBuilder = new BlockchainBuilder();
                chainBuilder.RealPoW = true;
                SetupSPVBehavior(servers, chainBuilder);

                var connected = CreateGroup(servers, 1);

                Wallet wallet = new Wallet(new WalletCreation()
                {
                    Network  = servers.Network,
                    RootKeys = new[] { new ExtKey().Neuter() },
                    UseP2SH  = true
                }, keyPoolSize: 0);
                Assert.True(wallet.State == WalletState.Created);
                wallet.Configure(connected);
                wallet.Connect();
                Assert.True(wallet.State == WalletState.Disconnected);
                TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);
                Assert.True(wallet.State == WalletState.Connected);

                var script = wallet.GetNextScriptPubKey(new KeyPath("0/1/2"));
                Thread.Sleep(1000);
                chainBuilder.GiveMoney(script, Money.Coins(0.001m));
                TestUtils.Eventually(() => wallet.GetTransactions().Count == 1);
                wallet.Disconnect();
                TestUtils.Eventually(() => connected.ConnectedNodes.Count == 0);

                MemoryStream ms = new MemoryStream();
                wallet.Save(ms);
                ms.Position = 0;
                var wallet2 = Wallet.Load(ms);
                wallet2.Configure(connected);
                wallet2.Connect();

                var script2 = wallet2.GetNextScriptPubKey(new KeyPath("0/1/2"));
                Thread.Sleep(1000);
                Assert.NotEqual(script, script2);
                Assert.NotNull(wallet2.GetRedeemScript(script));
                Assert.NotNull(wallet2.GetRedeemScript(script2));
                TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);
                var spv = servers.Server1.ConnectedNodes.First().Behaviors.Find <SPVBehavior>();
                TestUtils.Eventually(() => spv._Filter != null);
                chainBuilder.GiveMoney(script2, Money.Coins(0.001m));
                TestUtils.Eventually(() => wallet.GetTransactions().Count == 2);
                chainBuilder.GiveMoney(script, Money.Coins(0.002m));
                TestUtils.Eventually(() => wallet.GetTransactions().Count == 3);
                chainBuilder.FindBlock();
                TestUtils.Eventually(() => wallet.GetTransactions().Count == 3 && wallet.GetTransactions().All(t => t.BlockInformation != null));
            }
        }
Beispiel #14
0
 public void CanRespondToPong()
 {
     using (var tester = new NodeServerTester())
     {
         var toS2 = tester.Server1.GetNodeByEndpoint(tester.Server2.ExternalEndpoint);
         toS2.VersionHandshake();
         var ping = new PingPayload();
         toS2.SendMessage(ping);
         var pong = toS2.RecieveMessage <PongPayload>(TimeSpan.FromSeconds(10.0));
         Assert.Equal(ping.Nonce, pong.Nonce);
     }
 }
Beispiel #15
0
 private static void SetupSPVBehavior(NodeServerTester servers, BlockchainBuilder chainBuilder)
 {
     foreach (var server in new[] { servers.Server1, servers.Server2 })
     {
         server.InboundNodeConnectionParameters.Services = NodeServices.Network;
         //Simulate SPV compatible server
         server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new ChainBehavior(chainBuilder.Chain)
         {
             AutoSync = false
         });
         server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new SPVBehavior(chainBuilder));
         /////////////
     }
 }
Beispiel #16
0
 public void ServerDisconnectCorrectlyFromDroppingClient()
 {
     using (var tester = new NodeServerTester())
     {
         var to2 = tester.Server1.GetNodeByEndpoint(tester.Server2.ExternalEndpoint);
         to2.VersionHandshake();
         Assert.True(tester.Server1.IsConnectedTo(tester.Server2.ExternalEndpoint));
         Thread.Sleep(500);
         Assert.True(tester.Server2.IsConnectedTo(tester.Server1.ExternalEndpoint));
         to2.Disconnect();
         Assert.False(tester.Server1.IsConnectedTo(tester.Server2.ExternalEndpoint));
         Thread.Sleep(500);
         Assert.False(tester.Server2.IsConnectedTo(tester.Server1.ExternalEndpoint));
     }
 }
Beispiel #17
0
        public void CantConnectToYourself()
        {
            if (pos_RPCClientTests.noClient)
            {
                return;
            }

            using (var tester = new NodeServerTester())
            {
                tester.Server2.Nonce = tester.Server1.Nonce;
                Assert.Throws(typeof(InvalidOperationException), () =>
                {
                    tester.Node1.VersionHandshake();
                });
            }
        }
Beispiel #18
0
        private static void SetupSPVBehavior(NodeServerTester servers, BlockchainBuilder chainBuilder)
        {
            List <Node> nodes = new List <Node>();
            ConcurrentDictionary <uint256, Transaction> receivedTxs = new ConcurrentDictionary <uint256, Transaction>();

            foreach (var server in new[] { servers.Server1, servers.Server2 })
            {
                server.InboundNodeConnectionParameters.Services = NodeServices.Network | NodeServices.NODE_BLOOM;
                //Simulate SPV compatible server
                server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new ChainBehavior(chainBuilder.Chain)
                {
                    AutoSync = false
                });
                server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new SPVBehavior(chainBuilder)
                {
                    Nodes = nodes,
                    _ReceivedTransactions = receivedTxs
                });
                /////////////
            }
        }
Beispiel #19
0
        public void ServerDisconnectCorrectlyFromDroppingClient()
        {
            if (pos_RPCClientTests.noClient)
            {
                return;
            }

            using (var tester = new NodeServerTester())
            {
                var to2 = tester.Node1;
                to2.VersionHandshake();
                Assert.True(tester.Server1.IsConnectedTo(tester.Server2.ExternalEndpoint));
                Thread.Sleep(100);
                Assert.True(tester.Server2.IsConnectedTo(tester.Server1.ExternalEndpoint));
                to2.Disconnect();
                Thread.Sleep(100);
                Assert.False(tester.Server1.IsConnectedTo(tester.Server2.ExternalEndpoint));
                Thread.Sleep(100);
                Assert.False(tester.Server2.IsConnectedTo(tester.Server1.ExternalEndpoint));
            }
        }
Beispiel #20
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);
        }
Beispiel #21
0
		public void UseFilterAddIfKeyPoolSizeIsZero()
		{
			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				var chainBuilder = new BlockchainBuilder();
				SetupSPVBehavior(servers, chainBuilder);

				var connected = CreateGroup(servers, 1);

				Wallet wallet = new Wallet(new WalletCreation()
				{
					Network = Network.TestNet,
					RootKeys = new[] { new ExtKey().Neuter() },
					UseP2SH = true
				}, keyPoolSize: 0);
				Assert.True(wallet.State == WalletState.Created);
				wallet.Configure(connected);
				wallet.Connect();
				Assert.True(wallet.State == WalletState.Disconnected);
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);
				Assert.True(wallet.State == WalletState.Connected);

				var script = wallet.GetNextScriptPubKey(new KeyPath("0/1/2"));
				Thread.Sleep(1000);
				chainBuilder.GiveMoney(script, Money.Coins(0.001m));
				TestUtils.Eventually(() => wallet.GetTransactions().Count == 1);
				wallet.Disconnect();
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 0);

				MemoryStream ms = new MemoryStream();
				wallet.Save(ms);
				ms.Position = 0;
				var wallet2 = Wallet.Load(ms);
				wallet2.Configure(connected);
				wallet2.Connect();

				var script2 = wallet2.GetNextScriptPubKey(new KeyPath("0/1/2"));
				Thread.Sleep(1000);
				Assert.NotEqual(script, script2);
				Assert.NotNull(wallet2.GetRedeemScript(script));
				Assert.NotNull(wallet2.GetRedeemScript(script2));
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 1);
				var spv = servers.Server1.ConnectedNodes.First().Behaviors.Find<SPVBehavior>();
				TestUtils.Eventually(() => spv._Filter != null);
				chainBuilder.GiveMoney(script2, Money.Coins(0.001m));
				TestUtils.Eventually(() => wallet.GetTransactions().Count == 2);
				chainBuilder.GiveMoney(script, Money.Coins(0.002m));
				TestUtils.Eventually(() => wallet.GetTransactions().Count == 3);
				chainBuilder.FindBlock();
				TestUtils.Eventually(() => wallet.GetTransactions().Count == 3 && wallet.GetTransactions().All(t => t.BlockInformation != null));
			}
		}
Beispiel #22
0
		public void CanMaintainConnectionToNodes()
		{

			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				NodesGroup connected = CreateGroup(servers, 2);
				connected.Connect();
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 2);

				//Server crash abruptly
				servers.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);
				connected.Disconnect();
				TestUtils.Eventually(() => connected.ConnectedNodes.Count == 0);
			}

		}
Beispiel #23
0
		private static void SetupSPVBehavior(NodeServerTester servers, BlockchainBuilder chainBuilder)
		{
			List<Node> nodes = new List<Node>();
			ConcurrentDictionary<uint256, Transaction> receivedTxs = new ConcurrentDictionary<uint256, Transaction>();

			foreach(var server in new[] { servers.Server1, servers.Server2 })
			{
				server.InboundNodeConnectionParameters.Services = NodeServices.Network;
				//Simulate SPV compatible server
				server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new ChainBehavior(chainBuilder.Chain)
				{
					AutoSync = false
				});
				server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new SPVBehavior(chainBuilder)
				{
					Nodes = nodes,
					_ReceivedTransactions = receivedTxs
				});
				/////////////
			}
		}
Beispiel #24
0
		public void CanBroadcastTransaction()
		{
			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				var notifiedTransactions = new List<WalletTransaction>();
				var chainBuilder = new BlockchainBuilder();
				SetupSPVBehavior(servers, chainBuilder);
				var tx = new Transaction();
				Wallet wallet = new Wallet(new WalletCreation()
				{
					Network = Network.TestNet,
					RootKeys = new[] { new ExtKey().Neuter() },
					UseP2SH = false
				}, keyPoolSize: 11);
				NodesGroup connected = CreateGroup(servers, 2);
				wallet.Configure(connected);
				wallet.Connect();

				AutoResetEvent evt = new AutoResetEvent(false);
				bool passed = false;
				bool rejected = false;
				var broadcasting = wallet.BroadcastTransactionAsync(tx);
				wallet.TransactionBroadcasted += (t) =>
				{
					evt.Set();
					passed = true;
				};
				wallet.TransactionRejected += (t, r) =>
				{
					evt.Set();
					rejected = true;
				};
				BroadcastHub hub = BroadcastHub.GetBroadcastHub(connected.NodeConnectionParameters);
				BroadcastHubBehavior behavior = null;
				while(behavior == null || behavior.AttachedNode.State != NodeState.HandShaked)
				{
					behavior = connected.ConnectedNodes.Select(n => n.Behaviors.Find<BroadcastHubBehavior>()).FirstOrDefault();
					Thread.Sleep(1);
				}
				Assert.Equal(1, behavior.Broadcasts.Count());
				Assert.Equal(1, hub.BroadcastingTransactions.Count());
				Assert.True(evt.WaitOne(20000));
				Assert.True(passed);
				evt.Reset();
				Assert.Equal(0, behavior.Broadcasts.Count());
				Assert.Equal(0, hub.BroadcastingTransactions.Count());
				Assert.Null(broadcasting.Result);

				broadcasting = wallet.BroadcastTransactionAsync(tx);
				Assert.Equal(1, behavior.Broadcasts.Count());
				Assert.True(evt.WaitOne(20000));
				Assert.True(rejected);
				Assert.Equal(0, behavior.Broadcasts.Count());
				Assert.Equal(0, hub.BroadcastingTransactions.Count());
				Assert.NotNull(broadcasting.Result);
			}
		}
Beispiel #25
0
        public void CanBroadcastTransaction()
        {
            using (NodeServerTester servers = new NodeServerTester(Network.TestNet))
            {
                var notifiedTransactions = new List <WalletTransaction>();
                var chainBuilder         = new BlockchainBuilder();
                SetupSPVBehavior(servers, chainBuilder);
                var    tx     = new Transaction();
                Wallet wallet = new Wallet(new WalletCreation()
                {
                    Network  = Network.TestNet,
                    RootKeys = new[] { new ExtKey().Neuter() },
                    UseP2SH  = false
                }, keyPoolSize: 11);
                NodesGroup connected = CreateGroup(servers, 2);
                wallet.Configure(connected);
                wallet.Connect();

                AutoResetEvent evt          = new AutoResetEvent(false);
                bool           passed       = false;
                bool           rejected     = false;
                var            broadcasting = wallet.BroadcastTransactionAsync(tx);
                wallet.TransactionBroadcasted += (t) =>
                {
                    passed = true;
                    evt.Set();
                };
                wallet.TransactionRejected += (t, r) =>
                {
                    rejected = true;
                    evt.Set();
                };
                BroadcastHub         hub      = BroadcastHub.GetBroadcastHub(connected.NodeConnectionParameters);
                BroadcastHubBehavior behavior = null;
                while (behavior == null || behavior.AttachedNode.State != NodeState.HandShaked)
                {
                    behavior = connected.ConnectedNodes.Select(n => n.Behaviors.Find <BroadcastHubBehavior>()).FirstOrDefault();
                    Thread.Sleep(1);
                }
                if (broadcasting.Status != TaskStatus.RanToCompletion)
                {
                    Assert.Equal(1, behavior.Broadcasts.Count());
                    Assert.Equal(1, hub.BroadcastingTransactions.Count());
                }
                Assert.True(evt.WaitOne(20000));
                Assert.True(broadcasting.Status == TaskStatus.RanToCompletion);
                Assert.True(passed);
                evt.Reset();
                Assert.Equal(0, behavior.Broadcasts.Count());
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.Null(broadcasting.Result);

                broadcasting = wallet.BroadcastTransactionAsync(tx);
                if (broadcasting.Status != TaskStatus.RanToCompletion)
                {
                    Assert.Equal(1, behavior.Broadcasts.Count());
                }
                Assert.True(evt.WaitOne(20000));
                Assert.True(rejected);
                Assert.Equal(0, behavior.Broadcasts.Count());
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.NotNull(broadcasting.Result);
            }
        }
Beispiel #26
0
        //[Trait("UnitTest", "UnitTest")]
        public void CanBroadcastTransaction()
        {
            using (NodeServerTester servers = new NodeServerTester())
            {
                var notifiedTransactions = new List <WalletTransaction>();
                var chainBuilder         = new BlockchainBuilder();
                SetupSPVBehavior(servers, chainBuilder);
                var    tx     = new Transaction();
                Wallet wallet = new Wallet(new WalletCreation()
                {
                    Network  = servers.Network,
                    RootKeys = new[] { new ExtKey().Neuter() },
                    UseP2SH  = false
                }, keyPoolSize: 11);
                NodesGroup connected = CreateGroup(servers, 2);
                wallet.Configure(connected);
                wallet.Connect();

                AutoResetEvent evt      = new AutoResetEvent(false);
                bool           passed   = false;
                bool           rejected = false;
                BroadcastHub   hub      = BroadcastHub.GetBroadcastHub(wallet.Group.NodeConnectionParameters);
                hub.ManualBroadcast = true;
                var broadcasting = wallet.BroadcastTransactionAsync(tx);
                wallet.TransactionBroadcasted += (t) =>
                {
                    passed = true;
                    evt.Set();
                };
                wallet.TransactionRejected += (t, r) =>
                {
                    rejected = true;
                    evt.Set();
                };
                while (connected.ConnectedNodes.Count != 2 && connected.ConnectedNodes.All(n => n.State == NodeState.HandShaked))
                {
                    Thread.Sleep(10);
                }

                var behaviors = connected.ConnectedNodes.Select(n => n.Behaviors.Find <BroadcastHubBehavior>()).ToArray();

                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 1));
                Assert.Equal(1, hub.BroadcastingTransactions.Count());
                hub.BroadcastTransactions();
                Assert.True(evt.WaitOne(20000));
                Assert.True(broadcasting.Wait(2000));
                Assert.True(passed);
                evt.Reset();


                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 0));
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.Null(broadcasting.Result);

                broadcasting = wallet.BroadcastTransactionAsync(tx);

                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 1));
                hub.BroadcastTransactions();
                Assert.True(evt.WaitOne(20000));
                Assert.True(broadcasting.Wait(2000));
                Assert.True(rejected);
                TestUtils.Eventually(() => behaviors.All(b => b.Broadcasts.Count() == 0));
                Assert.Equal(0, hub.BroadcastingTransactions.Count());
                Assert.NotNull(broadcasting.Result);
            }
        }
Beispiel #27
0
		public void CanRespondToPong()
		{

			using(var tester = new NodeServerTester())
			{
				var toS2 = tester.Node1;
				toS2.VersionHandshake();
				var ping = new PingPayload();
				CancellationTokenSource cancel = new CancellationTokenSource();
				cancel.CancelAfter(10000);
				using(var list = toS2.CreateListener())
				{
					toS2.SendMessageAsync(ping);
					while(true)
					{
						var pong = list.ReceivePayload<PongPayload>(cancel.Token);
						if(ping.Nonce == pong.Nonce)
							break;
					}
				}

			}

		}
Beispiel #28
0
		public void CanMaintainChainWithChainBehavior()
		{
			using(var node = Node.ConnectToLocal(Network.TestNet))
			{
				var chain = node.GetChain(uint256.Parse("00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70"));
				Assert.True(chain.Height == 500);
				using(var tester = new NodeServerTester(Network.TestNet))
				{
					var n1 = tester.Node1;
					n1.Behaviors.Add(new ChainBehavior(chain));
					n1.VersionHandshake();
					Assert.True(n1.MyVersion.StartHeight == 500);
					var n2 = tester.Node2;
					Assert.True(n2.MyVersion.StartHeight == 0);
					Assert.True(n2.PeerVersion.StartHeight == 500);
					Assert.True(n1.State == NodeState.HandShaked);
					Assert.True(n2.State == NodeState.HandShaked);
					var behavior = new ChainBehavior(new ConcurrentChain(Network.TestNet));
					n2.Behaviors.Add(behavior);
					TestUtils.Eventually(() => behavior.Chain.Height == 500);
					var chain2 = n2.GetChain(uint256.Parse("00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70"));
					Assert.True(chain2.Height == 500);
					var chain1 = n1.GetChain(uint256.Parse("00000000a2424460c992803ed44cfe0c0333e91af04fde9a6a97b468bf1b5f70"));
					Assert.True(chain1.Height == 500);
					chain1 = n1.GetChain(uint256.Parse("000000008cd4b1bdaa1278e3f1708258f862da16858324e939dc650627cd2e27"));
					Assert.True(chain1.Height == 499);
					Thread.Sleep(5000);
				}
			}
		}
Beispiel #29
0
        public void CanSyncWalletCore(WalletCreation creation)
        {
            using (NodeServerTester servers = new NodeServerTester(Network.TestNet))
            {
                var notifiedTransactions = new List <WalletTransaction>();
                var chainBuilder         = new BlockchainBuilder();
                SetupSPVBehavior(servers, chainBuilder);
                NodesGroup connected = CreateGroup(servers, 1);
                Wallet     wallet    = new Wallet(creation, keyPoolSize: 11);
                wallet.NewWalletTransaction += (s, a) => notifiedTransactions.Add(a);
                Assert.True(wallet.State == WalletState.Created);
                wallet.Configure(connected);
                wallet.Connect();
                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.NotNull(wallet.GetKeyPath(k));
                if (creation.UseP2SH)
                {
                    var p2sh = k.GetDestinationAddress(Network.TestNet) as BitcoinScriptAddress;
                    Assert.NotNull(p2sh);
                    var redeem = wallet.GetRedeemScript(p2sh);
                    Assert.NotNull(redeem);
                    Assert.Equal(redeem.Hash, p2sh.Hash);
                }

                Assert.Equal(creation.UseP2SH, k.GetDestinationAddress(Network.TestNet) is BitcoinScriptAddress);
                chainBuilder.GiveMoney(k, Money.Coins(1.0m));
                TestUtils.Eventually(() => wallet.GetTransactions().Count == 1 &&
                                     notifiedTransactions.Count == 1);
                chainBuilder.FindBlock();
                TestUtils.Eventually(() => wallet.GetTransactions().Where(t => t.BlockInformation != null).Count() == 1 &&
                                     notifiedTransactions.Count == 2);
                chainBuilder.Broadcast = false;
                chainBuilder.GiveMoney(k, Money.Coins(1.5m));
                chainBuilder.Broadcast = true;
                chainBuilder.FindBlock();
                TestUtils.Eventually(() => wallet.GetTransactions().Summary.Confirmed.TransactionCount == 2 &&
                                     notifiedTransactions.Count == 3);

                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);

                //Save and restore wallet
                MemoryStream ms = new MemoryStream();
                wallet.Save(ms);
                ms.Position = 0;
                var wallet2 = Wallet.Load(ms);
                //////

                //Save and restore tracker
                ms = new MemoryStream();
                var tracker = connected.NodeConnectionParameters.TemplateBehaviors.Find <TrackerBehavior>();
                connected.NodeConnectionParameters.TemplateBehaviors.Remove(tracker);
                tracker.Tracker.Save(ms);
                ms.Position = 0;
                tracker     = new TrackerBehavior(Tracker.Load(ms), wallet.Chain);
                connected.NodeConnectionParameters.TemplateBehaviors.Add(tracker);
                //////

                wallet2.Configure(connected);
                wallet2.Connect();
                Assert.Equal(wallet.Created, wallet2.Created);
                Assert.Equal(wallet.GetNextScriptPubKey(), wallet2.GetNextScriptPubKey());
                Assert.True(wallet.GetKnownScripts().Length == wallet2.GetKnownScripts().Length);
                TestUtils.Eventually(() => wallet2.GetTransactions().Summary.Confirmed.TransactionCount == 3);

                var fork = wallet.Chain.FindFork(wallet2._ScanLocation);
                Assert.True(fork.Height == chainBuilder.Chain.Height);
            }
        }
Beispiel #30
0
		public void CantConnectToYourself()
		{
			using(var tester = new NodeServerTester())
			{
				tester.Server2.Nonce = tester.Server1.Nonce;
				Assert.Throws(typeof(InvalidOperationException), () =>
				{
					tester.Node1.VersionHandshake();
				});
			}
		}
Beispiel #31
0
        public void CanSyncWallet2()
        {
            using (NodeServerTester servers = new NodeServerTester(Network.TestNet))
            {
                var chainBuilder = new BlockchainBuilder();
                SetupSPVBehavior(servers, chainBuilder);
                NodesGroup aliceConnection = CreateGroup(servers, 1);
                NodesGroup bobConnection   = CreateGroup(servers, 1);

                var    aliceKey = new ExtKey();
                Wallet alice    = new Wallet(new WalletCreation()
                {
                    Network           = Network.TestNet,
                    RootKeys          = new[] { aliceKey.Neuter() },
                    SignatureRequired = 1,
                    UseP2SH           = false
                }, 11);
                Wallet bob = new Wallet(new WalletCreation()
                {
                    Network           = Network.TestNet,
                    RootKeys          = new[] { new ExtKey().Neuter() },
                    SignatureRequired = 1,
                    UseP2SH           = false
                }, 11);

                alice.Configure(aliceConnection);
                alice.Connect();

                bob.Configure(bobConnection);
                bob.Connect();

                TestUtils.Eventually(() => aliceConnection.ConnectedNodes.Count == 1);

                //New address tracked
                var addressAlice = alice.GetNextScriptPubKey();
                chainBuilder.GiveMoney(addressAlice, Money.Coins(1.0m));
                TestUtils.Eventually(() => aliceConnection.ConnectedNodes.Count == 0);                 //Purge
                TestUtils.Eventually(() => aliceConnection.ConnectedNodes.Count == 1);                 //Reconnect
                //////

                TestUtils.Eventually(() => alice.GetTransactions().Count == 1);

                //Alice send tx to bob
                var coins = alice.GetTransactions().GetSpendableCoins();
                var keys  = coins.Select(c => alice.GetKeyPath(c.ScriptPubKey))
                            .Select(k => aliceKey.Derive(k))
                            .ToArray();
                var builder = new TransactionBuilder();
                var tx      =
                    builder
                    .SetTransactionPolicy(new Policy.StandardTransactionPolicy()
                {
                    MinRelayTxFee = new FeeRate(0)
                })
                    .AddCoins(coins)
                    .AddKeys(keys)
                    .Send(bob.GetNextScriptPubKey(), Money.Coins(0.4m))
                    .SetChange(alice.GetNextScriptPubKey(true))
                    .BuildTransaction(true);

                Assert.True(builder.Verify(tx));

                chainBuilder.BroadcastTransaction(tx);

                //Alice get change
                TestUtils.Eventually(() => alice.GetTransactions().Count == 2);
                coins = alice.GetTransactions().GetSpendableCoins();
                Assert.True(coins.Single().Amount == Money.Coins(0.6m));
                //////

                //Bob get coins
                TestUtils.Eventually(() => bob.GetTransactions().Count == 1);
                coins = bob.GetTransactions().GetSpendableCoins();
                Assert.True(coins.Single().Amount == Money.Coins(0.4m));
                //////


                MemoryStream bobWalletBackup = new MemoryStream();
                bob.Save(bobWalletBackup);
                bobWalletBackup.Position = 0;

                MemoryStream bobTrakerBackup = new MemoryStream();
                bob.Tracker.Save(bobTrakerBackup);
                bobTrakerBackup.Position = 0;

                bob.Disconnect();

                //Restore bob
                bob = Wallet.Load(bobWalletBackup);
                bobConnection.NodeConnectionParameters.TemplateBehaviors.Remove <TrackerBehavior>();
                bobConnection.NodeConnectionParameters.TemplateBehaviors.Add(new TrackerBehavior(Tracker.Load(bobTrakerBackup), chainBuilder.Chain));
                /////

                bob.Configure(bobConnection);

                //Bob still has coins
                TestUtils.Eventually(() => bob.GetTransactions().Count == 1);
                coins = bob.GetTransactions().GetSpendableCoins();
                Assert.True(coins.Single().Amount == Money.Coins(0.4m));
                //////

                bob.Connect();
                TestUtils.Eventually(() => bobConnection.ConnectedNodes.Count == 1);

                //New block found !
                chainBuilder.FindBlock();

                //Alice send tx to bob
                coins = alice.GetTransactions().GetSpendableCoins();
                keys  = coins.Select(c => alice.GetKeyPath(c.ScriptPubKey))
                        .Select(k => aliceKey.Derive(k))
                        .ToArray();
                builder = new TransactionBuilder();
                tx      =
                    builder
                    .SetTransactionPolicy(new Policy.StandardTransactionPolicy()
                {
                    MinRelayTxFee = new FeeRate(0)
                })
                    .AddCoins(coins)
                    .AddKeys(keys)
                    .Send(bob.GetNextScriptPubKey(), Money.Coins(0.1m))
                    .SetChange(alice.GetNextScriptPubKey(true))
                    .BuildTransaction(true);

                Assert.True(builder.Verify(tx));

                chainBuilder.BroadcastTransaction(tx);

                //Bob still has coins
                TestUtils.Eventually(() => bob.GetTransactions().Count == 2);                 //Bob has both, old and new tx
                coins = bob.GetTransactions().GetSpendableCoins();
                //////
            }
        }
Beispiel #32
0
		public void CanExchangeFastPingPong()
		{
			using(var tester = new NodeServerTester())
			{
				var n1 = tester.Node1;
				n1.Behaviors.Add(new PingPongBehavior()
				{
					PingInterval = TimeSpan.FromSeconds(0.1),
					TimeoutInterval = TimeSpan.FromSeconds(0.8)
				});

				n1.VersionHandshake();
				Assert.Equal(NodeState.HandShaked, n1.State);
				Assert.True(!n1.Inbound);

				var n2 = tester.Node2;
				n2.Behaviors.Add(new PingPongBehavior()
				{
					PingInterval = TimeSpan.FromSeconds(0.1),
					TimeoutInterval = TimeSpan.FromSeconds(0.5)
				});
				Assert.Equal(NodeState.HandShaked, n2.State);
				Assert.True(n2.Inbound);
				Thread.Sleep(2000);
				Assert.Equal(NodeState.HandShaked, n2.State);
				n1.Behaviors.Clear();
				Thread.Sleep(1200);
				Assert.True(n2.State == NodeState.Disconnecting || n2.State == NodeState.Offline);
				Assert.True(n2.DisconnectReason.Reason.StartsWith("Pong timeout", StringComparison.Ordinal));
			}
		}
Beispiel #33
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);
            }
        }
Beispiel #34
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;
		}
Beispiel #35
0
		public void CanReceiveHandshake()
		{
			using(var tester = new NodeServerTester())
			{
				var toS2 = tester.Node1;
				toS2.VersionHandshake();
				Assert.Equal(NodeState.HandShaked, toS2.State);
				Thread.Sleep(100); //Let the time to Server2 to add the new node, else the test was failing sometimes.
				Assert.Equal(NodeState.HandShaked, tester.Node2.State);
			}
		}
Beispiel #36
0
		public void ServerDisconnectCorrectlyFromDroppingClient()
		{
			using(var tester = new NodeServerTester())
			{
				var to2 = tester.Node1;
				to2.VersionHandshake();
				Assert.True(tester.Server1.IsConnectedTo(tester.Server2.ExternalEndpoint));
				Thread.Sleep(100);
				Assert.True(tester.Server2.IsConnectedTo(tester.Server1.ExternalEndpoint));
				to2.Disconnect();
				Thread.Sleep(100);
				Assert.False(tester.Server1.IsConnectedTo(tester.Server2.ExternalEndpoint));
				Thread.Sleep(100);
				Assert.False(tester.Server2.IsConnectedTo(tester.Server1.ExternalEndpoint));
			}
		}
Beispiel #37
0
		public void CanSyncWallet2()
		{
			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				var chainBuilder = new BlockchainBuilder();
				SetupSPVBehavior(servers, chainBuilder);
				NodesGroup aliceConnection = CreateGroup(servers, 1);
				NodesGroup bobConnection = CreateGroup(servers, 1);

				var aliceKey = new ExtKey();
				Wallet alice = new Wallet(new WalletCreation()
				{
					Network = Network.TestNet,
					RootKeys = new[] { aliceKey.Neuter() },
					SignatureRequired = 1,
					UseP2SH = false
				}, 11);
				Wallet bob = new Wallet(new WalletCreation()
				{
					Network = Network.TestNet,
					RootKeys = new[] { new ExtKey().Neuter() },
					SignatureRequired = 1,
					UseP2SH = false
				}, 11);

				alice.Configure(aliceConnection);
				alice.Connect();

				bob.Configure(bobConnection);
				bob.Connect();

				TestUtils.Eventually(() => aliceConnection.ConnectedNodes.Count == 1);

				//New address tracked
				var addressAlice = alice.GetNextScriptPubKey();
				chainBuilder.GiveMoney(addressAlice, Money.Coins(1.0m));
				TestUtils.Eventually(() => aliceConnection.ConnectedNodes.Count == 0); //Purge
				TestUtils.Eventually(() => aliceConnection.ConnectedNodes.Count == 1); //Reconnect
				//////

				TestUtils.Eventually(() => alice.GetTransactions().Count == 1);

				//Alice send tx to bob
				var coins = alice.GetTransactions().GetSpendableCoins();
				var keys = coins.Select(c => alice.GetKeyPath(c.ScriptPubKey))
								.Select(k => aliceKey.Derive(k))
								.ToArray();
				var builder = new TransactionBuilder();
				var tx =
					builder
					.SetTransactionPolicy(new Policy.StandardTransactionPolicy()
					{
						MinRelayTxFee = new FeeRate(0)
					})
					.AddCoins(coins)
					.AddKeys(keys)
					.Send(bob.GetNextScriptPubKey(), Money.Coins(0.4m))
					.SetChange(alice.GetNextScriptPubKey(true))
					.BuildTransaction(true);

				Assert.True(builder.Verify(tx));

				chainBuilder.BroadcastTransaction(tx);

				//Alice get change
				TestUtils.Eventually(() => alice.GetTransactions().Count == 2);
				coins = alice.GetTransactions().GetSpendableCoins();
				Assert.True(coins.Single().Amount == Money.Coins(0.6m));
				//////

				//Bob get coins
				TestUtils.Eventually(() => bob.GetTransactions().Count == 1);
				coins = bob.GetTransactions().GetSpendableCoins();
				Assert.True(coins.Single().Amount == Money.Coins(0.4m));
				//////


				MemoryStream bobWalletBackup = new MemoryStream();
				bob.Save(bobWalletBackup);
				bobWalletBackup.Position = 0;

				MemoryStream bobTrakerBackup = new MemoryStream();
				bob.Tracker.Save(bobTrakerBackup);
				bobTrakerBackup.Position = 0;

				bob.Disconnect();

				//Restore bob
				bob = Wallet.Load(bobWalletBackup);
				bobConnection.NodeConnectionParameters.TemplateBehaviors.Remove<TrackerBehavior>();
				bobConnection.NodeConnectionParameters.TemplateBehaviors.Add(new TrackerBehavior(Tracker.Load(bobTrakerBackup), chainBuilder.Chain));
				/////

				bob.Configure(bobConnection);

				//Bob still has coins
				TestUtils.Eventually(() => bob.GetTransactions().Count == 1);
				coins = bob.GetTransactions().GetSpendableCoins();
				Assert.True(coins.Single().Amount == Money.Coins(0.4m));
				//////

				bob.Connect();
				TestUtils.Eventually(() => bobConnection.ConnectedNodes.Count == 1);

				//New block found !
				chainBuilder.FindBlock();

				//Alice send tx to bob
				coins = alice.GetTransactions().GetSpendableCoins();
				keys = coins.Select(c => alice.GetKeyPath(c.ScriptPubKey))
								.Select(k => aliceKey.Derive(k))
								.ToArray();
				builder = new TransactionBuilder();
				tx =
					builder
					.SetTransactionPolicy(new Policy.StandardTransactionPolicy()
					{
						MinRelayTxFee = new FeeRate(0)
					})
					.AddCoins(coins)
					.AddKeys(keys)
					.Send(bob.GetNextScriptPubKey(), Money.Coins(0.1m))
					.SetChange(alice.GetNextScriptPubKey(true))
					.BuildTransaction(true);

				Assert.True(builder.Verify(tx));

				chainBuilder.BroadcastTransaction(tx);

				//Bob still has coins
				TestUtils.Eventually(() => bob.GetTransactions().Count == 2); //Bob has both, old and new tx
				coins = bob.GetTransactions().GetSpendableCoins();
				//////
			}
		}
Beispiel #38
0
		private static void SetupSPVBehavior(NodeServerTester servers, BlockchainBuilder chainBuilder)
		{
			foreach(var server in new[] { servers.Server1, servers.Server2 })
			{
				server.InboundNodeConnectionParameters.Services = NodeServices.Network;
				//Simulate SPV compatible server
				server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new ChainBehavior(chainBuilder.Chain)
				{
					AutoSync = false
				});
				server.InboundNodeConnectionParameters.TemplateBehaviors.Add(new SPVBehavior(chainBuilder));
				/////////////
			}
		}
Beispiel #39
0
		public void CanSyncWalletCore(WalletCreation creation)
		{
			using(NodeServerTester servers = new NodeServerTester(Network.TestNet))
			{
				var notifiedTransactions = new List<WalletTransaction>();
				var chainBuilder = new BlockchainBuilder();
				SetupSPVBehavior(servers, chainBuilder);
				NodesGroup connected = CreateGroup(servers, 1);
				Wallet wallet = new Wallet(creation, keyPoolSize: 11);
				wallet.NewWalletTransaction += (s, a) => notifiedTransactions.Add(a);
				Assert.True(wallet.State == WalletState.Created);
				wallet.Configure(connected);
				wallet.Connect();
				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.NotNull(wallet.GetKeyPath(k));
				if(creation.UseP2SH)
				{
					var p2sh = k.GetDestinationAddress(Network.TestNet) as BitcoinScriptAddress;
					Assert.NotNull(p2sh);
					var redeem = wallet.GetRedeemScript(p2sh);
					Assert.NotNull(redeem);
					Assert.Equal(redeem.Hash, p2sh.Hash);
				}

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

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

				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);

				//Save and restore wallet
				MemoryStream ms = new MemoryStream();
				wallet.Save(ms);
				ms.Position = 0;
				var wallet2 = Wallet.Load(ms);
				//////

				//Save and restore tracker
				ms = new MemoryStream();
				var tracker = connected.NodeConnectionParameters.TemplateBehaviors.Find<TrackerBehavior>();
				connected.NodeConnectionParameters.TemplateBehaviors.Remove(tracker);
				tracker.Tracker.Save(ms);
				ms.Position = 0;
				tracker = new TrackerBehavior(Tracker.Load(ms), wallet.Chain);
				connected.NodeConnectionParameters.TemplateBehaviors.Add(tracker);
				//////

				wallet2.Configure(connected);
				wallet2.Connect();
				Assert.Equal(wallet.Created, wallet2.Created);
				Assert.Equal(wallet.GetNextScriptPubKey(), wallet2.GetNextScriptPubKey());
				Assert.True(wallet.GetKnownScripts().Length == wallet2.GetKnownScripts().Length);
				TestUtils.Eventually(() => wallet2.GetTransactions().Summary.Confirmed.TransactionCount == 3);

				var fork = wallet.Chain.FindFork(wallet2._ScanLocation);
				Assert.True(fork.Height == chainBuilder.Chain.Height);
			}
		}
Beispiel #40
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);
			}
		}
Beispiel #41
0
		public void CanConnectMultipleTimeToServer()
		{
			using(var tester = new NodeServerTester())
			{
				int nodeCount = 0;
				tester.Server1.NodeAdded += (s, a) => nodeCount++;
				tester.Server1.NodeRemoved += (s, a) => nodeCount--;

				var n1 = Node.Connect(tester.Server1.Network, tester.Server1.ExternalEndpoint);
				n1.VersionHandshake();
				Thread.Sleep(100);
				Assert.Equal(1, nodeCount);
				n1.PingPong();
				var n2 = Node.Connect(tester.Server1.Network, tester.Server1.ExternalEndpoint);
				n2.VersionHandshake();
				Thread.Sleep(100);
				Assert.Equal(2, nodeCount);
				n2.PingPong();
				n1.PingPong();
				Assert.Throws<ProtocolException>(() => n2.VersionHandshake());
				Thread.Sleep(100);
				n2.PingPong();
				Assert.Equal(2, nodeCount);
				n2.Disconnect();
				Thread.Sleep(100);
				Assert.Equal(1, nodeCount);
			}
		}
Beispiel #42
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);
			}
		}
Beispiel #43
0
 public void CanRespondToPong()
 {
     using(var tester = new NodeServerTester())
     {
         var toS2 = tester.Server1.GetNodeByEndpoint(tester.Server2.ExternalEndpoint);
         toS2.VersionHandshake();
         var ping = new PingPayload();
         toS2.SendMessage(ping);
         var pong = toS2.RecieveMessage<PongPayload>(TimeSpan.FromSeconds(10.0));
         Assert.Equal(ping.Nonce, pong.Nonce);
     }
 }