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); } }
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; }
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); } }
public void Dispose() { _Disposed = true; SaveAsync(); if (_Group != null) { _Group.Disconnect(); } }
public void Dispose() { _Disposed = true; _Starting.Wait(); if (_Group != null) { _Group.Disconnect(); _Group = null; } }
public void Disconnect() { if (_State == WalletState.Created) { return; } TryUpdateLocation(); _Group.Disconnect(); _Group.ConnectedNodes.Added -= ConnectedNodes_Added; _State = WalletState.Created; }
public async Task StopAsync() { SaveChainData(); if (_nodeGroup != null) { _nodeGroup.Disconnect(); } if (EndpointInstance != null) { await EndpointInstance.Stop(); } }
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 }
public void Dispose() { lock (l) { if (_Nodes != null) { _Nodes.Disconnect(); _Nodes = null; } if (Repository != null) { Repository.Dispose(); Repository = null; } } }
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); }
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(); } } }
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(); }
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; }
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(); } } }
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(); }