Пример #1
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);
            }
        }
Пример #2
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);
         }
     }
 }
Пример #3
0
        public void CanMaintainConnectionToNodes()
        {
            using (var builder = NodeBuilder.Create())
            {
                NodesGroup connected = CreateGroup(builder, 2);
                connected.Connect();
                TestUtils.Eventually(() => connected.ConnectedNodes.Count == 2);

                //Server crash abruptly
                builder.Nodes[0].Kill(false);
                TestUtils.Eventually(() => connected.ConnectedNodes.Count < 2);
                builder.Nodes[0].Start();
                //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);
            }
        }
Пример #4
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);
            }
        }
Пример #5
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);
            }
        }
Пример #6
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);
         }
     }
 }
Пример #7
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));
            }
        }
Пример #8
0
        public void CanSyncWalletCore(NodeBuilder builder, CoreNode walletNode, WalletCreation creation)
        {
            var        rpc = builder.Nodes[0].CreateRPCClient();
            var        notifiedTransactions = new List <WalletTransaction>();
            NodesGroup connected            = CreateGroup(new List <CoreNode>(new[] { walletNode }), 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);

            TestUtils.Eventually(() => wallet.Chain.Height == rpc.GetBlockCount());
            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);

            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);
            builder.Nodes[0].GiveMoney(k, Money.Coins(1.0m));
            TestUtils.Eventually(() => wallet.GetTransactions().Count == 1 &&
                                 notifiedTransactions.Count == 1);
            builder.Nodes[0].FindBlock();
            TestUtils.Eventually(() => wallet.GetTransactions().Where(t => t.BlockInformation != null).Count() == 1 &&
                                 notifiedTransactions.Count == 2);
            builder.Nodes[0].GiveMoney(k, Money.Coins(1.5m), false);
            builder.Nodes[0].FindBlock();
            TestUtils.Eventually(() => wallet.GetTransactions().Summary.Confirmed.TransactionCount == 2 &&
                                 notifiedTransactions.Count == 3);

            builder.Nodes[0].FindBlock(30);
            Assert.True(wallet.GetTransactions().Summary.Confirmed.TransactionCount == 2);
            builder.Nodes[0].GiveMoney(k, Money.Coins(0.001m), false);
            Assert.True(wallet.GetTransactions().Summary.Confirmed.TransactionCount == 2);
            builder.Nodes[0].FindBlock(1, false);
            Assert.True(wallet.GetTransactions().Summary.Confirmed.TransactionCount == 2);
            builder.Nodes[0].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>();

            tracker.Tracker.Save(ms);
            ms.Position = 0;
            connected   = CreateGroup(new List <CoreNode>(new[] { walletNode }), 1);
            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);

            //TestUtils.Eventually(() =>
            //{
            //    var fork = wallet.Chain.FindFork(wallet2._ScanLocation);
            //    return fork.Height == rpc.GetBlockCount();
            //});

            wallet2.Disconnect();
            wallet.Disconnect();
            connected.Disconnect();
        }
Пример #9
0
        public void CanSyncWallet2()
        {
            using (var builder = NodeBuilder.Create())
            {
                NodesGroup aliceConnection = CreateGroup(builder, 1);
                NodesGroup bobConnection   = CreateGroup(new[] { builder.Nodes[0] }, 1);
                builder.Nodes[0].Generate(101);
                var    rpc      = builder.Nodes[0].CreateRPCClient();
                var    aliceKey = new ExtKey();
                Wallet alice    = new Wallet(new WalletCreation()
                {
                    Network           = Network.RegTest,
                    RootKeys          = new[] { aliceKey.Neuter() },
                    SignatureRequired = 1,
                    UseP2SH           = false
                }, 11);
                Wallet bob = new Wallet(new WalletCreation()
                {
                    Network           = Network.RegTest,
                    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();
                builder.Nodes[0].GiveMoney(addressAlice, Money.Coins(1.0m));
                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 txBuilder = new TransactionBuilder();
                var tx        =
                    txBuilder
                    .SetTransactionPolicy(new Policy.StandardTransactionPolicy()
                {
                    MinRelayTxFee = new FeeRate(0)
                })
                    .AddCoins(coins)
                    .AddKeys(keys)
                    .Send(bob.GetNextScriptPubKey(), Money.Coins(0.4m))
                    .SetChange(alice.GetNextScriptPubKey(true))
                    .SendFees(Money.Coins(0.0001m))
                    .BuildTransaction(true);

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

                builder.Nodes[0].Broadcast(tx);

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

                //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), alice.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 !
                builder.Nodes[0].SelectMempoolTransactions();
                builder.Nodes[0].Generate(1);

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

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

                builder.Nodes[0].Broadcast(tx);

                //Bob still has coins
                TestUtils.Eventually(() => bob.GetTransactions().Count == 2);                 //Bob has both, old and new tx
                coins = bob.GetTransactions().GetSpendableCoins();
                //////
            }
        }
Пример #10
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);
            }
        }
Пример #11
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);
            }
        }
Пример #12
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);
            }
        }