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)); } }
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); } }
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); } } }
public void CanRespondToPong() { if (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; } } } } }
public void CantConnectToYourself() { using (var tester = new NodeServerTester()) { tester.Server2.Nonce = tester.Server1.Nonce; Assert.Throws(typeof(InvalidOperationException), () => { tester.Node1.VersionHandshake(); }); } }
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); } }
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)); } }
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)); } }
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 }); ///////////// } }
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; servers.AddDisposable(connected); return(connected); }
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); } }