public PeerManagerProvider( INBXplorerClientProvider nbXplorerClientProvider, NRustLightningNetworkProvider networkProvider, IKeysRepository keysRepository, ILoggerFactory loggerFactory, ChannelProvider channelProvider, IOptions <Config> config ) { foreach (var n in networkProvider.GetAll()) { var nbx = nbXplorerClientProvider.TryGetClient(n); if (nbx != null) { var b = new NbXplorerBroadcaster(nbx, loggerFactory.CreateLogger <NbXplorerBroadcaster>()); var feeEst = new NbXplorerFeeEstimator(loggerFactory.CreateLogger <NbXplorerFeeEstimator>(), channelProvider.GetFeeRateChannel(n).Reader); var chainWatchInterface = new NbxChainWatchInterface(nbx, loggerFactory.CreateLogger <NbxChainWatchInterface>(), n); var peerManSeed = new byte[32]; RandomUtils.GetBytes(peerManSeed); var logger = new NativeLogger(loggerFactory.CreateLogger <NativeLogger>()); var nbitcoinNetwork = n.NBitcoinNetwork; var conf = config.Value.RustLightningConfig; var peerMan = PeerManager.Create(peerManSeed.AsSpan(), nbitcoinNetwork, conf, chainWatchInterface, keysRepository, b, logger, feeEst, 400000); _peerManagers.Add(n.CryptoCode, peerMan); } } }
public async Task StartAsync(CancellationToken cancellationToken) { foreach (var n in _networkProvider.GetAll()) { var nbx = _nbXplorerClientProvider.TryGetClient(n); if (nbx != null) { var b = new NbXplorerBroadcaster(nbx, _loggerFactory.CreateLogger <NbXplorerBroadcaster>(), _eventAggregator); var feeEst = new NbXplorerFeeEstimator(_loggerFactory.CreateLogger <NbXplorerFeeEstimator>(), _channelProvider.GetFeeRateChannel(n).Reader); var chainWatchInterface = new NbxChainWatchInterface(nbx, _loggerFactory.CreateLogger <NbxChainWatchInterface>(), n); var conf = _config.Value.RustLightningConfig; var logger = new NativeLogger(_loggerFactory.CreateLogger <NativeLogger>()); var repo = _repositoryProvider.GetRepository(n); uint currentBlockHeight; int tried0 = 0; retry0: try { currentBlockHeight = (uint)await nbx.RPCClient.GetBlockCountAsync(); } catch when(tried0 < 4) { tried0++; await Task.Delay(1000, cancellationToken); goto retry0; }
public RepositoryProvider(NRustLightningNetworkProvider networks, IOptions <Config> config, IServiceProvider serviceProvider) { Config = config.Value; var directory = Path.Combine(Config.DataDir, "db"); if (!Directory.Exists(directory)) { Directory.CreateDirectory(directory); } foreach (var n in networks.GetAll()) { var settings = GetChainSetting(n); if (settings != null) { var keysRepository = serviceProvider.GetRequiredService <IKeysRepository>(); var serializer = new RepositorySerializer(n); keysRepository.Serializer = serializer; _keysRepositories.Add(n.CryptoCode, keysRepository); _repositorySerializers.Add(n.CryptoCode, serializer); var invoiceRepository = serviceProvider.GetRequiredService <IInvoiceRepository>(); _invoiceRepositories.Add(n.CryptoCode, invoiceRepository); } } }
public ChannelProvider(INBXplorerClientProvider clientProvider, NRustLightningNetworkProvider networkProvider) { foreach (var n in networkProvider.GetAll()) { var maybeClient = clientProvider.TryGetClient(n.CryptoCode); if (maybeClient != null) { _feeRateChannels.Add(n.CryptoCode, Channel.CreateBounded <FeeRateSet>(50)); } } }
public DataFlowProvider(INBXplorerClientProvider clientProvider, NRustLightningNetworkProvider networkProvider) { foreach (var n in networkProvider.GetAll()) { var maybeClient = clientProvider.TryGetClient(n.CryptoCode); if (maybeClient != null) { var inputBuffer = new BufferBlock <FeeRateSet>(); _feeRateSourceBlock.Add(n.CryptoCode, inputBuffer); throw new NotImplementedException(); } } }
public ChannelProvider(INBXplorerClientProvider clientProvider, NRustLightningNetworkProvider networkProvider) { foreach (var n in networkProvider.GetAll()) { var maybeClient = clientProvider.TryGetClient(n.CryptoCode); if (maybeClient != null) { _feeRateChannels.Add(n.CryptoCode, Channel.CreateBounded <FeeRateSet>(50)); _outboundConnectionRequestChannel.Add(n.CryptoCode, Channel.CreateBounded <PeerConnectionString>(1000)); _spendableOutputDescriptorChannel.Add(n.CryptoCode, Channel.CreateBounded <SpendableOutputDescriptor>(100000)); } } }
public NBXplorerListeners(NRustLightningNetworkProvider networkProvider, INBXplorerClientProvider clientProvider, PeerManagerProvider peerManagerProvider, ILoggerFactory loggerFactory, ChannelProvider channelProvider) { foreach (var n in networkProvider.GetAll()) { var cli = clientProvider.TryGetClient(n); if (cli != null) { var listener = new NBXplorerListener(cli, peerManagerProvider, loggerFactory.CreateLogger <NBXplorerListener>(), channelProvider.GetFeeRateChannel(n).Writer, n); _listeners.TryAdd(n.CryptoCode, listener); } } }
public NBXplorerClientProvider(IOptions <Config> config, IOptionsMonitor <ChainConfiguration> chainConfig, NRustLightningNetworkProvider networkProvider, IHttpClientFactory httpClientFactory, ILogger <NBXplorerClientProvider> logger) { _logger = logger; foreach (var n in networkProvider.GetAll()) { var chainConf = chainConfig.Get(n.CryptoCode); if (!(chainConf is null)) { var c = new ExplorerClient(n.NbXplorerNetwork, config.Value.NBXplorerUri); if (!string.IsNullOrEmpty(config.Value.NBXCookieFile)) { c.SetCookieAuth(config.Value.NBXCookieFile); } c.SetClient(httpClientFactory.CreateClient(nameof(NBXplorerClientProvider))); // check the connection by getting status. // TODO: Prepare HostedService for waiting NBXplorer and bitcoind gets ready? int sleepMs = 50; Exception e = null; int maxRetry = 6; for (int count = 0; count <= maxRetry; count++) { try { var _ = c.GetStatus(); e = null; } catch (Exception ex) { _logger.LogWarning($"Failed to connect to nbxplorer. retrying in {sleepMs} milliseconds..."); e = ex; Thread.Sleep(sleepMs); sleepMs *= 2; } } if (e != null) { _logger.LogCritical($"Failed to connect nbxplorer. check your settings."); throw e; } explorerClients.Add(n.CryptoCode, c); } } if (explorerClients.Count == 0) { throw new NRustLightningException("Found zero valid nbxplorer instance to connect"); } }
public RepositoryProvider(NRustLightningNetworkProvider networks, IOptions <Config> config, IServiceProvider serviceProvider) { Config = config.Value; foreach (var n in networks.GetAll()) { var settings = GetChainSetting(n); if (settings != null) { var keysRepository = serviceProvider.GetRequiredService <IKeysRepository>(); var serializer = new RepositorySerializer(n); keysRepository.Serializer = serializer; _keysRepositories.Add(n.CryptoCode, keysRepository); _repositorySerializers.Add(n.CryptoCode, serializer); var repository = serviceProvider.GetRequiredService <IRepository>(); _repos.Add(n.CryptoCode, repository); } } }
public RustLightningEventReactors(NRustLightningNetworkProvider networkProvider, INBXplorerClientProvider clientProvider, IServiceProvider serviceProvider, ILoggerFactory loggerFactory) { foreach (var n in networkProvider.GetAll()) { var cli = clientProvider.TryGetClient(n); if (cli != null) // it means we want to support that chain. { var reactor = new RustLightningEventReactor( serviceProvider.GetRequiredService <P2PConnectionHandler>(), serviceProvider.GetRequiredService <IPeerManagerProvider>(), serviceProvider.GetRequiredService <IWalletService>(), n, serviceProvider.GetRequiredService <EventAggregator>(), loggerFactory.CreateLogger(nameof(RustLightningEventReactor) + $":{n.CryptoCode}"), serviceProvider.GetRequiredService <IInvoiceRepository>() ); Reactors.Add(n.CryptoCode, reactor); } } }
public WorkQueueProcessors(RepositoryProvider repositoryProvider, NRustLightningNetworkProvider networkProvider, IServiceProvider serviceProvider, ILoggerFactory loggerFactory) { _networkProvider = networkProvider; foreach (var n in networkProvider.GetAll()) { var repo = repositoryProvider.TryGetRepository(n); if (repo is null) { continue; } var p = new WorkQueueProcessor( serviceProvider.GetRequiredService <ChannelProvider>(), serviceProvider.GetRequiredService <P2PConnectionHandler>(), loggerFactory.CreateLogger <WorkQueueProcessor>(), serviceProvider.GetRequiredService <PeerManagerProvider>(), n, serviceProvider.GetRequiredService <IWalletService>(), repo ); _processors.Add(n.CryptoCode, p); } }
public NBXplorerClientProvider(IOptions <Config> config, IOptionsMonitor <ChainConfiguration> chainConfig, NRustLightningNetworkProvider networkProvider, IHttpClientFactory httpClientFactory, ILogger <NBXplorerClientProvider> logger) { _logger = logger; foreach (var n in networkProvider.GetAll()) { var chainConf = chainConfig.Get(n.CryptoCode); if (!(chainConf is null)) { var c = new ExplorerClient(n.NbXplorerNetwork, config.Value.NBXplorerUri); if (!string.IsNullOrEmpty(config.Value.NBXCookieFile)) { c.SetCookieAuth(config.Value.NBXCookieFile); } c.SetClient(httpClientFactory.CreateClient(nameof(NBXplorerClientProvider))); var timeout = new CancellationTokenSource(4000); try { c.WaitServerStarted(timeout.Token); c.GetStatus(); } catch (Exception) { _logger.LogError($"Failed to connect to nbxplorer! cryptoCode: {n.CryptoCode} url: {config.Value.NBXplorerUri}. cookiefile: {config.Value.NBXCookieFile}"); throw; } explorerClients.Add(n.CryptoCode, c); } } if (explorerClients.Count == 0) { throw new NRustLightningException("Found zero valid nbxplorer instance to connect"); } }
public Config LoadArgs(IConfiguration config, ILogger logger) { var networkType = config.GetNetworkType(); logger.LogInformation($"Network type: {networkType}"); NetworkProvider = new NRustLightningNetworkProvider(networkType); var defaultSettings = NRustLightningDefaultSettings.GetDefaultSettings(NetworkProvider.NetworkType); DataDir = config.GetOrDefault <string>("datadir", null); if (DataDir is null) { DataDir = Path.GetDirectoryName(defaultSettings.DefaultDataDir); if (!Directory.Exists(DataDir)) { Directory.CreateDirectory(DataDir); } if (!Directory.Exists(defaultSettings.DefaultDataDir)) { Directory.CreateDirectory(defaultSettings.DefaultDataDir); } } var nbxConfig = config.GetSection("nbx"); var nbxCookieFile = nbxConfig.GetOrDefault("cookiefile", Constants.DefaultNBXplorerCookieFile(NetworkProvider.NetworkType)); NBXplorerUri = new Uri(nbxConfig.GetOrDefault("rpcurl", Constants.DefaultNBXplorerUri)); if (!File.Exists(nbxCookieFile)) { logger.LogWarning($"cookie file for nbxplorer does not exist in {nbxCookieFile}" + " Make sure you are running nbx with --noauth."); } logger.LogInformation($"nbxplorer url {NBXplorerUri}"); NBXCookieFile = nbxCookieFile; var p2pExternalIp = config.GetOrDefault("externalip", Constants.DefaultP2PExternalIpStr); if (IPEndPoint.TryParse(p2pExternalIp, out var ip)) { P2PExternalIp = ip; } else if (p2pExternalIp.Contains(":")) { var s = p2pExternalIp.Split(":", StringSplitOptions.RemoveEmptyEntries); if (s.Length != 2) { throw new ConfigException($"Invalid external ip {p2pExternalIp}"); } if (Int32.TryParse(s[1], out var port)) { P2PExternalIp = new DnsEndPoint(s[0], port); } else { throw new ConfigException($"Invalid external ip {p2pExternalIp}"); } } else { throw new ConfigException($"Invalid external ip {p2pExternalIp}"); } logger.LogInformation($"Advertising external ip: {P2PExternalIp.ToEndpointString()}"); logger.LogDebug($"Network: {NetworkProvider.NetworkType.ToString()}"); var supportedChains = config.GetOrDefault <string>("chains", "BTC") .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(t => t.ToLowerInvariant()); var validChains = new List <string>(); foreach (var n in NetworkProvider.GetAll()) { if (supportedChains.Contains(n.CryptoCode)) { validChains.Add(n.CryptoCode); var chainConfiguration = new ChainConfiguration(); chainConfiguration.CryptoCode = n.CryptoCode; var args = RPCArgs.Parse(config, n.NBitcoinNetwork, n.CryptoCode); chainConfiguration.Rpc = args.ConfigureRPCClient(n, logger); if (chainConfiguration.Rpc.Address.Port == n.NBitcoinNetwork.DefaultPort) { logger.LogWarning($"{n.CryptoCode}: It seems that the1 RPC port ({chainConfiguration.Rpc.Address.Port}) is equal to the default P2P port ({n.NBitcoinNetwork.DefaultPort}, this is probably a misconfiguration)"); } if ((chainConfiguration.Rpc.CredentialString.CookieFile != null || chainConfiguration.Rpc.CredentialString.UseDefault) && !n.SupportCookieAuthentication) { throw new ConfigException($"Chain {n.CryptoCode} does not support cookie file authentication,\n" + $"Please use {n.CryptoCode.ToLowerInvariant()}rpcuser and {n.CryptoCode.ToLowerInvariant()}rpcpassword settings in NRustLightning" + $"And configure rpcuser and rpcpassword in the configuration file or in commandline or your node"); } ChainConfiguration.Add(chainConfiguration); } } var invalidChains = String.Join(',', supportedChains.Where(s => !validChains.Contains(s))); if (!string.IsNullOrEmpty(invalidChains)) { throw new ConfigException($"Invalid chains {invalidChains}"); } config.GetSection("ln").Bind(RustLightningConfig); string?seed = null; var filePath = Path.Join(DataDir, "node_secret"); if (File.Exists(filePath)) { logger.LogDebug($"reading seed from {filePath}"); seed = File.ReadAllText(filePath); } if (seed is null) { seed = config.GetOrDefault("seed", String.Empty); } if (String.IsNullOrEmpty(seed)) { logger.LogWarning($"seed not found in {filePath}! You can specify it with --seed option."); logger.LogInformation("generating new seed..."); seed = RandomUtils.GetUInt256().ToString(); } InvoiceDBFilePath = Path.Combine(DataDir, "InvoiceDb"); if (!Directory.Exists(InvoiceDBFilePath)) { Directory.CreateDirectory(InvoiceDBFilePath); } var h = new HexEncoder(); if (!(h.IsValid(seed) && seed.Length == 64)) { throw new NRustLightningException($"Seed corrupted {seed}"); } File.WriteAllText(filePath, seed); GetSeed = async() => { var s = await File.ReadAllTextAsync(filePath); return(h.DecodeData(s)); }; PaymentTimeoutSec = config.GetOrDefault("paymenttimeout", Constants.DefaultPaymentTimeoutSec); DBCacheMB = config.GetOrDefault("dbcache", Constants.DefaultDBCacheMB); return(this); }
public IEnumerable <ExplorerClient> GetAll() { return(_networkProvider.GetAll().Select(n => new ExplorerClient(n.NbXplorerNetwork))); }
public Config LoadArgs(IConfiguration config, ILogger?logger) { _logger = logger; var networkType = config.GetNetworkType(); logger?.LogInformation($"Network type: {networkType}"); NetworkProvider = new NRustLightningNetworkProvider(networkType); var defaultSettings = NRustLightningDefaultSettings.GetDefaultSettings(NetworkProvider.NetworkType); var d = config.GetOrDefault <string>("datadir", null); DataDir = d is null?Path.GetDirectoryName(defaultSettings.DefaultDataDir) : Path.Join(d, NRustLightningDefaultSettings.GetFolderName(networkType)); if (!Directory.Exists(DataDir)) { Directory.CreateDirectory(DataDir ?? throw new Exception("Unreachable")); } var nbxConfig = config.GetSection("nbx"); var nbxCookieFile = nbxConfig.GetOrDefault("cookiefile", Constants.DefaultNbXplorerCookieFile(NetworkProvider.NetworkType)); NBXplorerUri = new Uri(nbxConfig.GetOrDefault("rpcurl", Constants.DefaultNBXplorerUri)); if (!File.Exists(nbxCookieFile)) { logger?.LogWarning($"cookie file for nbxplorer does not exist in {nbxCookieFile}" + " Make sure you are running nbx with --noauth."); } logger?.LogInformation($"nbxplorer url {NBXplorerUri}"); NBXCookieFile = nbxCookieFile; var p2pExternalIp = config.GetOrDefault("externalip", Constants.DefaultP2PExternalIpStr); if (NBitcoin.Utils.TryParseEndpoint(p2pExternalIp, Constants.DefaultP2PPort, out var ip)) { P2PExternalIp = ip; } else if (p2pExternalIp.Contains(":")) { var s = p2pExternalIp.Split(":", StringSplitOptions.RemoveEmptyEntries); if (s.Length != 2) { throw new ConfigException($"Invalid external ip {p2pExternalIp}"); } if (Int32.TryParse(s[1], out var port)) { P2PExternalIp = new DnsEndPoint(s[0], port); } else { throw new ConfigException($"Invalid external ip {p2pExternalIp}"); } } else { throw new ConfigException($"Invalid external ip {p2pExternalIp}"); } logger?.LogInformation($"Advertising external ip: {P2PExternalIp.ToEndpointString()}"); logger?.LogDebug($"Network: {NetworkProvider.NetworkType.ToString()}"); var supportedChains = config.GetOrDefault <string>("chains", "BTC") .Split(',', StringSplitOptions.RemoveEmptyEntries) .Select(t => t.ToLowerInvariant()); var validChains = new List <string>(); foreach (var n in NetworkProvider.GetAll()) { if (supportedChains.Contains(n.CryptoCode)) { validChains.Add(n.CryptoCode); var chainConfiguration = new ChainConfiguration(); chainConfiguration.CryptoCode = n.CryptoCode; var args = RPCArgs.Parse(config, n.NBitcoinNetwork, n.CryptoCode); chainConfiguration.Rpc = args.ConfigureRPCClient(n, logger); if (chainConfiguration.Rpc.Address.Port == n.NBitcoinNetwork.DefaultPort) { logger?.LogWarning($"{n.CryptoCode}: It seems that the1 RPC port ({chainConfiguration.Rpc.Address.Port}) is equal to the default P2P port ({n.NBitcoinNetwork.DefaultPort}, this is probably a misconfiguration)"); } if ((chainConfiguration.Rpc.CredentialString.CookieFile != null || chainConfiguration.Rpc.CredentialString.UseDefault) && !n.SupportCookieAuthentication) { throw new ConfigException($"Chain {n.CryptoCode} does not support cookie file authentication,\n" + $"Please use {n.CryptoCode.ToLowerInvariant()}rpcuser and {n.CryptoCode.ToLowerInvariant()}rpcpassword settings in NRustLightning" + $"And configure rpcuser and rpcpassword in the configuration file or in commandline or your node"); } ChainConfiguration.Add(chainConfiguration); } } var invalidChains = String.Join(',', supportedChains.Where(s => !validChains.Contains(s))); if (!string.IsNullOrEmpty(invalidChains)) { throw new ConfigException($"Invalid chains {invalidChains}"); } config.GetSection("ln").Bind(RustLightningConfig); DBFilePath = Path.Combine(DataDir, "Db.dat"); if (!Directory.Exists(DBFilePath)) { Directory.CreateDirectory(DBFilePath); } PaymentTimeoutSec = config.GetOrDefault("paymenttimeout", Constants.DefaultPaymentTimeoutSec); DBCacheMB = config.GetOrDefault("dbcache", Constants.DefaultDBCacheMB); _seedFromConfig = config.GetOrDefault("seed", string.Empty); _pin = config.GetOrDefault("pin", string.Empty); SeedFilePath = Path.Join(DataDir, "node_secret"); return(this); }