Ejemplo n.º 1
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);
            }
        }
Ejemplo n.º 2
0
        protected override void Dispose(bool disposing)
        {
            if (_disposed)
            {
                return;
            }

            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }

                if (_group != null)
                {
                    _group.Disconnect();
                    _group.Dispose();
                }
            }

            base.Dispose(disposing);

            _disposed = true;
        }
Ejemplo n.º 3
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);
            }
        }
Ejemplo n.º 4
0
 public void Dispose()
 {
     _Disposed = true;
     SaveAsync();
     if (_Group != null)
     {
         _Group.Disconnect();
     }
 }
Ejemplo n.º 5
0
 public void Dispose()
 {
     _Disposed = true;
     _Starting.Wait();
     if (_Group != null)
     {
         _Group.Disconnect();
         _Group = null;
     }
 }
Ejemplo n.º 6
0
 public void Disconnect()
 {
     if (_State == WalletState.Created)
     {
         return;
     }
     TryUpdateLocation();
     _Group.Disconnect();
     _Group.ConnectedNodes.Added -= ConnectedNodes_Added;
     _State = WalletState.Created;
 }
Ejemplo n.º 7
0
        public async Task StopAsync()
        {
            SaveChainData();
            if (_nodeGroup != null)
            {
                _nodeGroup.Disconnect();
            }

            if (EndpointInstance != null)
            {
                await EndpointInstance.Stop();
            }
        }
Ejemplo n.º 8
0
        public void Disconnect()
        {
#pragma warning disable CS0612 // Type or member is obsolete
            if (_State == WalletState.Created)
#pragma warning restore CS0612 // Type or member is obsolete
            {
                return;
            }
            TryUpdateLocation();
            _Group.Disconnect();
            _Group.ConnectedNodes.Added -= ConnectedNodes_Added;
#pragma warning disable CS0612 // Type or member is obsolete
            _State = WalletState.Created;
#pragma warning restore CS0612 // Type or member is obsolete
        }
Ejemplo n.º 9
0
 public void Dispose()
 {
     lock (l)
     {
         if (_Nodes != null)
         {
             _Nodes.Disconnect();
             _Nodes = null;
         }
         if (Repository != null)
         {
             Repository.Dispose();
             Repository = null;
         }
     }
 }
Ejemplo n.º 10
0
 public Task StopAsync(CancellationToken cancellationToken)
 {
     _Disposed = true;
     _Cts.Cancel();
     _Subscription.Dispose();
     if (_Group != null)
     {
         _Group.ConnectedNodes.Added   -= ConnectedNodes_Changed;
         _Group.ConnectedNodes.Removed -= ConnectedNodes_Changed;
         _Group.Disconnect();
         _Group = null;
     }
     State  = BitcoinDWaiterState.NotStarted;
     _Chain = null;
     _Tick.Set();
     return(_Loop);
 }
Ejemplo n.º 11
0
        public void CanHandshakeWithSeveralTemplateBehaviors()
        {
            using (var builder = NodeBuilderEx.Create())
            {
                var node = builder.CreateNode(true);
                node.Generate(101);
                AddressManager manager = new AddressManager();
                manager.Add(new NetworkAddress(node.NodeEndpoint), IPAddress.Loopback);

                var        chain = new SlimChain(builder.Network.GenesisHash);
                NodesGroup group = new NodesGroup(builder.Network, new NodeConnectionParameters()
                {
                    Services          = NodeServices.Nothing,
                    IsRelay           = true,
                    TemplateBehaviors =
                    {
                        new AddressManagerBehavior(manager)
                        {
                            PeersToDiscover = 1,
                            Mode            = AddressManagerBehaviorMode.None
                        },
                        new SlimChainBehavior(chain),
                        new PingPongBehavior()
                    }
                });
                group.AllowSameGroup        = true;
                group.MaximumNodeConnection = 1;
                var connecting = WaitConnected(group);
                try
                {
                    group.Connect();
                    connecting.GetAwaiter().GetResult();
                    Eventually(() =>
                    {
                        Assert.Equal(101, chain.Height);
                    });
                    var ms = new MemoryStream();
                    chain.Save(ms);

                    var chain2 = new SlimChain(chain.Genesis);
                    ms.Position = 0;
                    chain2.Load(ms);
                    Assert.Equal(chain.Tip, chain2.Tip);

                    using (var fs = new FileStream("test.slim.dat", FileMode.Create, FileAccess.Write, FileShare.None, 1024 * 1024))
                    {
                        chain.Save(fs);
                        fs.Flush();
                    }

                    chain.ResetToGenesis();
                    using (var fs = new FileStream("test.slim.dat", FileMode.Open, FileAccess.Read, FileShare.None, 1024 * 1024))
                    {
                        chain.Load(fs);
                    }
                    Assert.Equal(101, chain2.Height);
                    chain.ResetToGenesis();
                }
                finally
                {
                    group.Disconnect();
                }
            }
        }
Ejemplo n.º 12
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();
        }
Ejemplo n.º 13
0
        private void DumpCoins(BitcoinAddress destination, IEnumerable <Coin> coins, IEnumerable <Key> keys)
        {
            var     total   = coins.Select(u => u.Amount).Sum();
            var     fee     = Money.Zero;
            FeeRate feeRate = null;

            try
            {
                feeRate = RPCClient.EstimateFeeRate(6);                 //BCC having few fees, this will confirm fast
            }
            catch
            {
                if (RPCClient.Network == Network.RegTest)
                {
                    feeRate = new FeeRate(Money.Satoshis(30), 1);
                }
                else
                {
                    Logs.Main.LogWarning("Fee estimation unavailable, you need to wait Bitcoin Core to properly sync and retry to dump");
                    return;
                }
            }
            TransactionBuilder builder = new TransactionBuilder();

            builder.AddCoins(coins);
            builder.Send(destination, total);
            try
            {
                builder.SendEstimatedFees(feeRate);
                builder.BuildTransaction(false);
            }
            catch (NotEnoughFundsException ex)
            {
                fee = (Money)ex.Missing;
            }

            builder = new TransactionBuilder();
            builder.AddKeys(keys.ToArray());
            builder.AddCoins(coins);
            builder.Send(destination, total - fee);
            builder.SendFees(fee);
            var dumpTransaction = builder.BuildTransaction(true, SigHash.ForkId | SigHash.All);

            Logs.Main.LogInformation("Dump transaction created " + dumpTransaction.ToHex());

            Logs.Main.LogInformation("Dump transaction ID " + dumpTransaction.GetHash());
            //repository.lock(coins.select(c => c.outpoint).toarray(), dumptransaction.gethash());
            Thread.Sleep(1000);
            while (true)
            {
                Console.WriteLine("Are you sure to dump " + coins.Select(c => c.Amount).Sum().ToString() + " BCash coin to " + destination.ToString() + " ? (type `yes` to continue)");
                var response = Console.ReadLine();
                if (response.Equals("yes", StringComparison.OrdinalIgnoreCase))
                {
                    break;
                }
            }

            Logs.Main.LogInformation("Connecting to a BCC node...");

            AddressManagerBehavior addrman = new AddressManagerBehavior(new AddressManager());

            addrman.PeersToDiscover = 10;
            addrman.Mode            = AddressManagerBehaviorMode.Discover;
            NodesGroup group = new NodesGroup(RPCClient.Network, new NodeConnectionParameters()
            {
                IsRelay           = false,
                Services          = NodeServices.Nothing | NodeServices.NODE_BITCOIN_CASH,
                TemplateBehaviors = { addrman },
                UserAgent         = "BCCSpliter",
                Advertize         = false
            }, new NodeRequirement()
            {
                RequiredServices = NodeServices.NODE_BITCOIN_CASH
            });

            group.MaximumNodeConnection = 1;

            if (Configuration.BCCEndpoint != null)
            {
                addrman.PeersToDiscover = 1;
                addrman.Mode            = AddressManagerBehaviorMode.None;
                addrman.AddressManager.Add(new NetworkAddress(Configuration.BCCEndpoint), IPAddress.Parse("127.0.0.1"));
                group.CustomGroupSelector = WellKnownGroupSelectors.ByEndpoint;
                group.AllowSameGroup      = true;
            }

            group.ConnectedNodes.Added += (s, e) =>
            {
                Logs.Main.LogInformation("Connected to " + e.Node.RemoteSocketEndpoint);
                Logs.Main.LogInformation("Broadcasting...");
                e.Node.SendMessageAsync(new InvPayload(new InventoryVector(InventoryType.MSG_TX, dumpTransaction.GetHash())));
                e.Node.SendMessageAsync(new TxPayload(dumpTransaction));
                CancellationTokenSource cts = new CancellationTokenSource();
                cts.CancelAfter(10000);
                try
                {
                    e.Node.PingPong(cts.Token);
                }
                catch (Exception ex)
                {
                    Logs.Main.LogWarning("Error while broadcasting transaction, retrying with another node...");
                    e.Node.Disconnect("Error while broadcasting transaction", ex);
                    return;
                }
                Logs.Main.LogInformation("Broadcasted " + dumpTransaction.GetHash());
                group.Disconnect();
                group.Dispose();
            };

            group.Connect();
        }
 /// <summary>
 /// Disconnects from the network and saves all connection data.
 /// </summary>
 public void Disconnect()
 {
     Save();
     _peers.Disconnect();
     _disposed = true;
 }
Ejemplo n.º 15
0
        public void CanHandshakeRestrictNodes()
        {
            using (var builder = NodeBuilderEx.Create())
            {
                var node    = builder.CreateNode(true);
                var manager = new AddressManager();
                manager.Add(new NetworkAddress(node.NodeEndpoint), IPAddress.Loopback);

                var nodesRequirement = new NodeRequirement()
                {
                    MinStartHeight = 100
                };
                var nodeConnectionParameters = new NodeConnectionParameters()
                {
                    TemplateBehaviors =
                    {
                        new AddressManagerBehavior(manager)
                        {
                            PeersToDiscover = 1,
                            Mode            = AddressManagerBehaviorMode.None
                        }
                    }
                };
                var group = new NodesGroup(builder.Network, nodeConnectionParameters, nodesRequirement);
                group.AllowSameGroup = true;
                var connecting = WaitConnected(group);
                try
                {
                    group.Connect();
                    connecting.GetAwaiter().GetResult();
                }
                catch (TaskCanceledException)
                {
                    // It is expected because no node should connect.
                    Assert.Empty(group.ConnectedNodes);                     // but we chack it anyway.
                }
                finally
                {
                    group.Disconnect();
                }

                node.Generate(101);
                group = new NodesGroup(builder.Network, nodeConnectionParameters, nodesRequirement);
                group.AllowSameGroup = true;
                connecting           = WaitConnected(group);
                try
                {
                    group.Connect();
                    connecting.GetAwaiter().GetResult();
                    Eventually(() =>
                    {
                        Assert.NotEmpty(group.ConnectedNodes);
                        Assert.All(group.ConnectedNodes, connectedNode =>
                                   Assert.True(connectedNode.RemoteSocketEndpoint.IsEqualTo(node.NodeEndpoint)));
                    });
                }
                finally
                {
                    group.Disconnect();
                }
            }
        }
Ejemplo n.º 16
0
        private void Dump(DumpOptions o)
        {
            if (o.Address == null)
            {
                throw new FormatException();
            }
            var destination = BitcoinAddress.Create(o.Address);

            if (destination is BitcoinWitScriptAddress || destination is BitcoinWitPubKeyAddress)
            {
                throw new FormatException("BCC disabled segwit, segwit address unsupported");
            }
            UTXO[] utxos = GetDumpingUTXOs();
            if (utxos.Length == 0)
            {
                Logs.Main.LogWarning("No UTXO selected to dump, use `select` command to select UTXOs to select for dump");
                return;
            }
            Logs.Main.LogInformation("Dumping " + utxos.Length + " UTXOs");
            FeeRate feeRate = null;

            try
            {
                feeRate = RPCClient.EstimateFeeRate(6);                 //BCC having few fees, this will confirm fast
            }
            catch
            {
                if (RPCClient.Network == Network.RegTest)
                {
                    feeRate = new FeeRate(Money.Satoshis(30), 1);
                }
                else
                {
                    Logs.Main.LogWarning("Fee estimation unavailable, you need to wait Bitcoin Core to properly sync and retry to dump");
                    return;
                }
            }

            var total = utxos.Select(u => u.Amount).Sum();
            var fee   = Money.Zero;
            var coins = utxos.Select(u => u.AsCoin());
            TransactionBuilder builder = new TransactionBuilder();

            builder.AddCoins(coins);
            builder.Send(destination, total);
            try
            {
                builder.SendEstimatedFees(feeRate);
                builder.BuildTransaction(false);
            }
            catch (NotEnoughFundsException ex)
            {
                fee = (Money)ex.Missing;
            }

            builder = new TransactionBuilder();
            builder.AddKeys(FetchKeys(coins).ToArray());
            builder.AddCoins(coins);
            builder.Send(destination, total - fee);
            builder.SendFees(fee);
            var dumpTransaction = builder.BuildTransaction(true, SigHash.ForkId | SigHash.All);

            Logs.Main.LogInformation("Dump transaction created " + dumpTransaction.ToHex());

            Logs.Main.LogInformation("Dump transaction ID " + dumpTransaction.GetHash());
            Repository.Lock(coins.Select(c => c.Outpoint).ToArray(), dumpTransaction.GetHash());

            Logs.Main.LogInformation("Connecting to a BCC node...");

            AddressManagerBehavior addrman = new AddressManagerBehavior(new AddressManager());

            addrman.PeersToDiscover = 10;
            addrman.Mode            = AddressManagerBehaviorMode.Discover;
            NodesGroup group = new NodesGroup(RPCClient.Network, new NodeConnectionParameters()
            {
                IsRelay           = false,
                Services          = NodeServices.Nothing | NodeServices.NODE_BITCOIN_CASH,
                TemplateBehaviors = { addrman },
                UserAgent         = "BCCSpliter",
                Advertize         = false
            }, new NodeRequirement()
            {
                RequiredServices = NodeServices.NODE_BITCOIN_CASH
            });

            group.MaximumNodeConnection = 1;

            if (Configuration.BCCEndpoint != null)
            {
                addrman.PeersToDiscover = 1;
                addrman.Mode            = AddressManagerBehaviorMode.None;
                addrman.AddressManager.Add(new NetworkAddress(Configuration.BCCEndpoint), IPAddress.Parse("127.0.0.1"));
                group.CustomGroupSelector = WellKnownGroupSelectors.ByEndpoint;
                group.AllowSameGroup      = true;
            }

            group.ConnectedNodes.Added += (s, e) =>
            {
                Logs.Main.LogInformation("Connected to " + e.Node.RemoteSocketEndpoint);
                Logs.Main.LogInformation("Broadcasting...");
                e.Node.SendMessageAsync(new InvPayload(new InventoryVector(InventoryType.MSG_TX, dumpTransaction.GetHash())));
                e.Node.SendMessageAsync(new TxPayload(dumpTransaction));
                CancellationTokenSource cts = new CancellationTokenSource();
                cts.CancelAfter(10000);
                try
                {
                    e.Node.PingPong(cts.Token);
                }
                catch (Exception ex)
                {
                    Logs.Main.LogWarning("Error while broadcasting transaction, retrying with another node...");
                    e.Node.Disconnect("Error while broadcasting transaction", ex);
                    return;
                }
                Logs.Main.LogInformation("Broadcasted " + dumpTransaction.GetHash() + ", when this transaction is confirmed, unlock your Bitcoins again with `confirm " + dumpTransaction.GetHash() + "`");
                group.Disconnect();
                group.Dispose();
            };

            group.Connect();
        }