private async Task <bool> WarmupBlockchain() { if (await _RPC.GetBlockCountAsync() < 100) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Less than 100 blocks, mining some block for regtest"); await _RPC.GenerateAsync(101); return(true); } else { var hash = await _RPC.GetBestBlockHashAsync(); BlockHeader header = null; try { header = await _RPC.GetBlockHeaderAsync(hash); } catch (RPCException ex) when(ex.RPCCode == RPCErrorCode.RPC_METHOD_NOT_FOUND) { header = (await _RPC.GetBlockAsync(hash)).Header; } if ((DateTimeOffset.UtcNow - header.BlockTime) > TimeSpan.FromSeconds(24 * 60 * 60)) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: It has been a while nothing got mined on regtest... mining 10 blocks"); await _RPC.GenerateAsync(10); return(true); } return(false); } }
public static async Task CreateChannel(RPCClient cashCow, ILightningClient sender, ILightningClient dest) { var destInfo = await dest.GetInfo(); var destInvoice = await dest.CreateInvoice(1000, "EnsureConnectedToDestination", TimeSpan.FromSeconds(5000)); while (true) { var result = await sender.Pay(destInvoice.BOLT11); if (result.Result == PayResult.CouldNotFindRoute) { var openChannel = await sender.OpenChannel(new OpenChannelRequest() { NodeInfo = destInfo.NodeInfoList[0], ChannelAmount = Money.Satoshis(16777215), FeeRate = new FeeRate(1UL, 1) }); if (openChannel.Result == OpenChannelResult.CannotAffordFunding) { var address = await sender.GetDepositAddress(); try { await cashCow.SendToAddressAsync(address, Money.Coins(1.0m), null, null, true); } catch (RPCException ex) when(ex.RPCCode == RPCErrorCode.RPC_WALLET_INSUFFICIENT_FUNDS || ex.RPCCode == RPCErrorCode.RPC_WALLET_ERROR) { await cashCow.GenerateAsync(1); await cashCow.SendToAddressAsync(address, Money.Coins(1.0m), null, null, true); } await cashCow.GenerateAsync(10); await WaitLNSynched(cashCow, sender); await WaitLNSynched(cashCow, dest); } if (openChannel.Result == OpenChannelResult.PeerNotConnected) { await sender.ConnectTo(destInfo.NodeInfoList[0]); } if (openChannel.Result == OpenChannelResult.NeedMoreConf) { await cashCow.GenerateAsync(6); await WaitLNSynched(cashCow, sender); await WaitLNSynched(cashCow, dest); } if (openChannel.Result == OpenChannelResult.AlreadyExists) { await Task.Delay(1000); } } else if (result.Result == PayResult.Ok) { break; } } }
private async Task WarmupBlockchain() { if (await _RPC.GetBlockCountAsync() < 100) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: Less than 100 blocks, mining some block for regtest"); await _RPC.GenerateAsync(101); } else { var header = await _RPC.GetBlockHeaderAsync(await _RPC.GetBestBlockHashAsync()); if ((DateTimeOffset.UtcNow - header.BlockTime) > TimeSpan.FromSeconds(24 * 60 * 60)) { Logs.Configuration.LogInformation($"{_Network.CryptoCode}: It has been a while nothing got mined on regtest... mining 10 blocks"); await _RPC.GenerateAsync(10); } } }
public static async Task <uint256[]> EnsureGenerateAsync(this RPCClient client, int blockCount) { uint256[] blockIds = new uint256[blockCount]; int generated = 0; while (generated < blockCount) { foreach (var id in await client.GenerateAsync(blockCount - generated).ConfigureAwait(false)) { blockIds[generated++] = id; } } return(blockIds); }
/// <summary> /// Create channels from all senders to all receivers while mining on cashCow /// </summary> /// <param name="cashCow">The miner and liquidity source</param> /// <param name="senders">Senders of payment on Lightning Network</param> /// <param name="receivers">Receivers of payment on Lightning Network</param> /// <returns></returns> public static async Task ConnectAll(RPCClient cashCow, IEnumerable <ILightningClient> senders, IEnumerable <ILightningClient> receivers) { if (await cashCow.GetBlockCountAsync() <= cashCow.Network.Consensus.CoinbaseMaturity) { await cashCow.GenerateAsync(cashCow.Network.Consensus.CoinbaseMaturity + 1); } foreach (var sender in senders) { foreach (var dest in receivers) { await CreateChannel(cashCow, sender, dest); } } }
public async Task CreateEnoughTxToEstimateFee() { var txPerBlock = 6; var nBlock = 6; for (int i = 0; i < nBlock; i++) { for (int j = 0; j < txPerBlock; j++) { var addr = new Key().PubKey.GetSegwitAddress(Network.RegTest); await this.BitcoinRPCClient.SendToAddressAsync(addr, Money.Coins(0.1m)); } await BitcoinRPCClient.GenerateAsync(1); } await WaitChainSync(); }
public static async Task CreateChannel(RPCClient cashCow, ILightningClient sender, ILightningClient dest) { var destInfo = await dest.GetInfo(); var destInvoice = await dest.CreateInvoice(1000, "EnsureConnectedToDestination", TimeSpan.FromSeconds(5000)); while (true) { int payErrors = 0; var result = await Pay(sender, destInvoice.BOLT11); Logs.LogInformation($"Pay Result: {result.Result} {result.ErrorDetail}"); if (result.Result == PayResult.Ok) { break; } else if (result.Result == PayResult.CouldNotFindRoute) { // check channels that are in process of opening, to prevent double channel open await Task.Delay(100); var pendingChannels = await sender.ListChannels(); if (pendingChannels.Any(a => a.RemoteNode == destInfo.NodeInfoList[0].NodeId)) { Logs.LogInformation($"Channel to {destInfo.NodeInfoList[0]} is already open(ing)"); Logs.LogInformation($"Attempting to reconnect Result: {await sender.ConnectTo(destInfo.NodeInfoList.First())}"); await cashCow.GenerateAsync(1); await WaitLNSynched(cashCow, sender); await WaitLNSynched(cashCow, dest); continue; } Logs.LogInformation($"Opening channel to {destInfo.NodeInfoList[0]}"); var openChannel = await sender.OpenChannel(new OpenChannelRequest() { NodeInfo = destInfo.NodeInfoList[0], ChannelAmount = Money.Satoshis(16777215), FeeRate = new FeeRate(1UL, 1) }); Logs.LogInformation($"Channel opening result: {openChannel.Result}"); if (openChannel.Result == OpenChannelResult.CannotAffordFunding) { var address = await sender.GetDepositAddress(); try { await cashCow.SendToAddressAsync(address, Money.Coins(1.0m), new SendToAddressParameters() { Replaceable = true }); } catch (RPCException ex) when(ex.RPCCode == RPCErrorCode.RPC_WALLET_INSUFFICIENT_FUNDS || ex.RPCCode == RPCErrorCode.RPC_WALLET_ERROR) { await cashCow.GenerateAsync(1); await cashCow.SendToAddressAsync(address, Money.Coins(1.0m), new SendToAddressParameters() { Replaceable = true }); } await cashCow.GenerateAsync(10); await WaitLNSynched(cashCow, sender); await WaitLNSynched(cashCow, dest); } if (openChannel.Result == OpenChannelResult.PeerNotConnected) { await sender.ConnectTo(destInfo.NodeInfoList[0]); } if (openChannel.Result == OpenChannelResult.NeedMoreConf) { await cashCow.GenerateAsync(6); await WaitLNSynched(cashCow, sender); await WaitLNSynched(cashCow, dest); } if (openChannel.Result == OpenChannelResult.AlreadyExists) { await Task.Delay(1000); } if (openChannel.Result == OpenChannelResult.Ok) { // generate one block and a bit more time to confirm channel opening await cashCow.GenerateAsync(1); await WaitLNSynched(cashCow, sender); await WaitLNSynched(cashCow, dest); await Task.Delay(500); } } else { if (payErrors++ > 10) { throw new Exception($"Couldn't establish payment channel after {payErrors} repeated tries"); } await Task.Delay(1000); } } }
public async Task StartAsync() { if (_Disposed) { throw new ObjectDisposedException(nameof(NBxplorerInitializer)); } _Starting.Reset(); try { if (_Network.IsRegTest) { if (await _RPC.GetBlockCountAsync() < 100) { Logs.Configuration.LogInformation($"Less than 100 blocks, mining some block for regtest"); await _RPC.GenerateAsync(101); } else { var header = await _RPC.GetBlockHeaderAsync(await _RPC.GetBestBlockHashAsync()); if ((DateTimeOffset.UtcNow - header.BlockTime) > TimeSpan.FromSeconds(24 * 60 * 60)) { Logs.Configuration.LogInformation($"It has been a while nothing got mined on regtest... mining 10 blocks"); await _RPC.GenerateAsync(10); } } } var cachePath = Path.Combine(_Configuration.DataDir, "chain.dat"); if (_Configuration.CacheChain && File.Exists(cachePath)) { Logs.Configuration.LogInformation($"Loading chain from cache..."); _Chain.Load(File.ReadAllBytes(cachePath)); Logs.Configuration.LogInformation($"Height: " + _Chain.Height); } var heightBefore = _Chain.Height; Logs.Configuration.LogInformation($"Loading chain from node..."); using (var node = Node.Connect(_Network.Network, _Configuration.NodeEndpoint)) { var cts = new CancellationTokenSource(); cts.CancelAfter(5000); node.VersionHandshake(cts.Token); node.SynchronizeChain(_Chain); } Logs.Configuration.LogInformation("Height: " + _Chain.Height); if (_Configuration.CacheChain && heightBefore != _Chain.Height) { Logs.Configuration.LogInformation($"Saving chain to cache..."); var ms = new MemoryStream(); _Chain.WriteTo(ms); File.WriteAllBytes(cachePath, ms.ToArray()); Logs.Configuration.LogInformation($"Saved"); } AddressManager manager = new AddressManager(); manager.Add(new NetworkAddress(_Configuration.NodeEndpoint), IPAddress.Loopback); NodesGroup group = new NodesGroup(_Network.Network, new NodeConnectionParameters() { Services = NodeServices.Nothing, IsRelay = true, TemplateBehaviors = { new AddressManagerBehavior(manager) { PeersToDiscover = 1, Mode = AddressManagerBehaviorMode.None }, new ExplorerBehavior(_Repository, _Chain, _Invoker, _Events) { StartHeight = _Configuration.StartHeight }, new ChainBehavior(_Chain) { CanRespondToGetHeaders = false } } }); group.AllowSameGroup = true; group.MaximumNodeConnection = 1; group.Connect(); _Group = group; } finally { _Starting.Set(); } }