mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-19 06:54:19 +01:00
Refactor TorService (#2388)
* TorServices Refactor to make value passing easier * Allow specifying Tor services through config Format: BTCPAY_TORSERVICES: "BTCPAYSERVER:URL.ONION:VIRTUALPORT;BTC-P2P:URL.ONION:VIRTUALPORT;BTC-RPC:URL.ONION:VIRTUALPORT;SOMEOTHERONIONSERVICE:URL.ONION:VIRTUALPORT" * add tests * Optimize Tor Services loader and ensure it is loaded as a hosted service * Remove Task from Tor service loader * Use options to parse Tor services * Fix booboo * Fix test after fixing booboo * Adding timeout on long running CanEnumeratetorServices test (cherry picked from commit 274b77e3175960158b803410037e2c7ff31984be) * Renaming timeout variable to better name * Only allow one of torrcfile or torservices Co-authored-by: Kukks <evilkukka@gmail.com> Co-authored-by: rockstardev <rockstardev@users.noreply.github.com>
This commit is contained in:
committed by
GitHub
parent
475a68924e
commit
ee0fa71605
@@ -131,5 +131,10 @@ namespace BTCPayServer
|
|||||||
}
|
}
|
||||||
return network as T;
|
return network as T;
|
||||||
}
|
}
|
||||||
|
public bool TryGetNetwork<T>(string cryptoCode, out T network) where T : BTCPayNetworkBase
|
||||||
|
{
|
||||||
|
network = GetNetwork<T>(cryptoCode);
|
||||||
|
return network != null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ namespace BTCPayServer.Tests
|
|||||||
Logs.LogProvider = new XUnitLogProvider(helper);
|
Logs.LogProvider = new XUnitLogProvider(helper);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanCreateAndDeleteCrowdfundApp()
|
public async Task CanCreateAndDeleteCrowdfundApp()
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanContributeOnlyWhenAllowed()
|
public async Task CanContributeOnlyWhenAllowed()
|
||||||
{
|
{
|
||||||
@@ -155,7 +155,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanComputeCrowdfundModel()
|
public async Task CanComputeCrowdfundModel()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -47,7 +47,10 @@ using BTCPayServer.Validation;
|
|||||||
using ExchangeSharp;
|
using ExchangeSharp;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Configuration;
|
||||||
|
using Microsoft.Extensions.Configuration.Memory;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.DataEncoders;
|
using NBitcoin.DataEncoders;
|
||||||
using NBitcoin.Payment;
|
using NBitcoin.Payment;
|
||||||
@@ -67,7 +70,7 @@ namespace BTCPayServer.Tests
|
|||||||
{
|
{
|
||||||
public class UnitTest1
|
public class UnitTest1
|
||||||
{
|
{
|
||||||
public const int TestTimeout = 60_000;
|
public const int LongRunningTestTimeout = 60_000; // 60s
|
||||||
|
|
||||||
public UnitTest1(ITestOutputHelper helper)
|
public UnitTest1(ITestOutputHelper helper)
|
||||||
{
|
{
|
||||||
@@ -870,18 +873,55 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public async Task CanEnumerateTorServices()
|
public async Task CanEnumerateTorServices()
|
||||||
{
|
{
|
||||||
var tor = new TorServices(new BTCPayNetworkProvider(ChainName.Regtest),
|
var tor = new TorServices(new BTCPayNetworkProvider(ChainName.Regtest),
|
||||||
new BTCPayServerOptions() { TorrcFile = TestUtils.GetTestDataFullPath("Tor/torrc") });
|
new OptionsWrapper<BTCPayServerOptions>(new BTCPayServerOptions()
|
||||||
|
{
|
||||||
|
TorrcFile = TestUtils.GetTestDataFullPath("Tor/torrc")
|
||||||
|
}));
|
||||||
await tor.Refresh();
|
await tor.Refresh();
|
||||||
|
|
||||||
Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.BTCPayServer));
|
Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.BTCPayServer));
|
||||||
Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.P2P));
|
Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.P2P));
|
||||||
Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.RPC));
|
Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.RPC));
|
||||||
Assert.True(tor.Services.Where(t => t.ServiceType == TorServiceType.Other).Count() > 1);
|
Assert.True(tor.Services.Count(t => t.ServiceType == TorServiceType.Other) > 1);
|
||||||
|
|
||||||
|
tor = new TorServices(new BTCPayNetworkProvider(ChainName.Regtest),
|
||||||
|
new OptionsWrapper<BTCPayServerOptions>(new BTCPayServerOptions()
|
||||||
|
{
|
||||||
|
TorrcFile = null,
|
||||||
|
TorServices = "btcpayserver:host.onion:80;btc-p2p:host2.onion:81,BTC-RPC:host3.onion:82,UNKNOWN:host4.onion:83,INVALID:ddd".Split(new[] {';', ','}, StringSplitOptions.RemoveEmptyEntries)
|
||||||
|
}));
|
||||||
|
await Task.WhenAll(tor.StartAsync(CancellationToken.None));
|
||||||
|
|
||||||
|
var btcpayS = Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.BTCPayServer));
|
||||||
|
Assert.Null(btcpayS.Network);
|
||||||
|
Assert.Equal("host.onion", btcpayS.OnionHost);
|
||||||
|
Assert.Equal(80, btcpayS.VirtualPort);
|
||||||
|
|
||||||
|
var p2p = Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.P2P));
|
||||||
|
Assert.NotNull(p2p.Network);
|
||||||
|
Assert.Equal("BTC", p2p.Network.CryptoCode);
|
||||||
|
Assert.Equal("host2.onion", p2p.OnionHost);
|
||||||
|
Assert.Equal(81, p2p.VirtualPort);
|
||||||
|
|
||||||
|
var rpc = Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.RPC));
|
||||||
|
Assert.NotNull(p2p.Network);
|
||||||
|
Assert.Equal("BTC", rpc.Network.CryptoCode);
|
||||||
|
Assert.Equal("host3.onion", rpc.OnionHost);
|
||||||
|
Assert.Equal(82, rpc.VirtualPort);
|
||||||
|
|
||||||
|
var unknown = Assert.Single(tor.Services.Where(t => t.ServiceType == TorServiceType.Other));
|
||||||
|
Assert.Null(unknown.Network);
|
||||||
|
Assert.Equal("host4.onion", unknown.OnionHost);
|
||||||
|
Assert.Equal(83, unknown.VirtualPort);
|
||||||
|
Assert.Equal("UNKNOWN", unknown.Name);
|
||||||
|
|
||||||
|
Assert.Equal(4, tor.Services.Length);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1046,7 +1086,7 @@ namespace BTCPayServer.Tests
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanUseServerInitiatedPairingCode()
|
public async Task CanUseServerInitiatedPairingCode()
|
||||||
{
|
{
|
||||||
@@ -1073,7 +1113,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanSendIPN()
|
public async Task CanSendIPN()
|
||||||
{
|
{
|
||||||
@@ -1143,7 +1183,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CantPairTwiceWithSamePubkey()
|
public async Task CantPairTwiceWithSamePubkey()
|
||||||
{
|
{
|
||||||
@@ -1167,7 +1207,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public void CanSolveTheDogesRatesOnKraken()
|
public void CanSolveTheDogesRatesOnKraken()
|
||||||
{
|
{
|
||||||
@@ -1185,7 +1225,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanUseTorClient()
|
public async Task CanUseTorClient()
|
||||||
{
|
{
|
||||||
@@ -1238,7 +1278,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanRescanWallet()
|
public async Task CanRescanWallet()
|
||||||
{
|
{
|
||||||
@@ -1340,7 +1380,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanListInvoices()
|
public async Task CanListInvoices()
|
||||||
{
|
{
|
||||||
@@ -1391,7 +1431,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanListNotifications()
|
public async Task CanListNotifications()
|
||||||
{
|
{
|
||||||
@@ -1675,7 +1715,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.NotNull(paymentData.KeyPath);
|
Assert.NotNull(paymentData.KeyPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public void CanParseFilter()
|
public void CanParseFilter()
|
||||||
{
|
{
|
||||||
@@ -1703,7 +1743,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal("hekki", search.TextSearch);
|
Assert.Equal("hekki", search.TextSearch);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public void CanParseFingerprint()
|
public void CanParseFingerprint()
|
||||||
{
|
{
|
||||||
@@ -1720,7 +1760,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.Equal(f1.ToString(), f2.ToString());
|
Assert.Equal(f1.ToString(), f2.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async void CheckCORSSetOnBitpayAPI()
|
public async void CheckCORSSetOnBitpayAPI()
|
||||||
{
|
{
|
||||||
@@ -1755,7 +1795,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task TestAccessBitpayAPI()
|
public async Task TestAccessBitpayAPI()
|
||||||
{
|
{
|
||||||
@@ -1834,7 +1874,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanUseExchangeSpecificRate()
|
public async Task CanUseExchangeSpecificRate()
|
||||||
{
|
{
|
||||||
@@ -1879,7 +1919,7 @@ namespace BTCPayServer.Tests
|
|||||||
return invoice2.CryptoInfo[0].Rate;
|
return invoice2.CryptoInfo[0].Rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanUseAnyoneCanCreateInvoice()
|
public async Task CanUseAnyoneCanCreateInvoice()
|
||||||
{
|
{
|
||||||
@@ -1931,7 +1971,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanTweakRate()
|
public async Task CanTweakRate()
|
||||||
{
|
{
|
||||||
@@ -1978,7 +2018,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanModifyRates()
|
public async Task CanModifyRates()
|
||||||
{
|
{
|
||||||
@@ -2307,7 +2347,7 @@ namespace BTCPayServer.Tests
|
|||||||
Assert.True(client.WaitAllRunning(default).Wait(100));
|
Assert.True(client.WaitAllRunning(default).Wait(100));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public void PosDataParser_ParsesCorrectly()
|
public void PosDataParser_ParsesCorrectly()
|
||||||
{
|
{
|
||||||
@@ -2333,7 +2373,7 @@ namespace BTCPayServer.Tests
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task PosDataParser_ParsesCorrectly_Slower()
|
public async Task PosDataParser_ParsesCorrectly_Slower()
|
||||||
{
|
{
|
||||||
@@ -2383,7 +2423,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanExportInvoicesJson()
|
public async Task CanExportInvoicesJson()
|
||||||
{
|
{
|
||||||
@@ -2462,7 +2502,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanChangeNetworkFeeMode()
|
public async Task CanChangeNetworkFeeMode()
|
||||||
{
|
{
|
||||||
@@ -2553,7 +2593,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanExportInvoicesCsv()
|
public async Task CanExportInvoicesCsv()
|
||||||
{
|
{
|
||||||
@@ -2595,7 +2635,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanCreateAndDeleteApps()
|
public async Task CanCreateAndDeleteApps()
|
||||||
{
|
{
|
||||||
@@ -2633,7 +2673,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanCreateStrangeInvoice()
|
public async Task CanCreateStrangeInvoice()
|
||||||
{
|
{
|
||||||
@@ -2679,7 +2719,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task InvoiceFlowThroughDifferentStatesCorrectly()
|
public async Task InvoiceFlowThroughDifferentStatesCorrectly()
|
||||||
{
|
{
|
||||||
@@ -2869,7 +2909,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public void CanQueryDirectProviders()
|
public void CanQueryDirectProviders()
|
||||||
{
|
{
|
||||||
@@ -2940,7 +2980,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanExportBackgroundFetcherState()
|
public async Task CanExportBackgroundFetcherState()
|
||||||
{
|
{
|
||||||
@@ -2982,7 +3022,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public void CanGetRateCryptoCurrenciesByDefault()
|
public void CanGetRateCryptoCurrenciesByDefault()
|
||||||
{
|
{
|
||||||
@@ -3034,7 +3074,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CheckLogsRoute()
|
public async Task CheckLogsRoute()
|
||||||
{
|
{
|
||||||
@@ -3117,7 +3157,7 @@ namespace BTCPayServer.Tests
|
|||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public void CanCheckFileNameValid()
|
public void CanCheckFileNameValid()
|
||||||
{
|
{
|
||||||
@@ -3135,7 +3175,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public async Task CanCreateSqlitedb()
|
public async Task CanCreateSqlitedb()
|
||||||
{
|
{
|
||||||
@@ -3147,7 +3187,7 @@ namespace BTCPayServer.Tests
|
|||||||
await new ApplicationDbContext(builder.Options).Database.MigrateAsync();
|
await new ApplicationDbContext(builder.Options).Database.MigrateAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public void CanUsePermission()
|
public void CanUsePermission()
|
||||||
{
|
{
|
||||||
@@ -3172,7 +3212,7 @@ namespace BTCPayServer.Tests
|
|||||||
.Contains(Permission.Create(Policies.CanModifyStoreSettings)));
|
.Contains(Permission.Create(Policies.CanModifyStoreSettings)));
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Fast", "Fast")]
|
[Trait("Fast", "Fast")]
|
||||||
public void CheckRatesProvider()
|
public void CheckRatesProvider()
|
||||||
{
|
{
|
||||||
@@ -3260,7 +3300,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanLoginWithNoSecondaryAuthSystemsOrRequestItWhenAdded()
|
public async Task CanLoginWithNoSecondaryAuthSystemsOrRequestItWhenAdded()
|
||||||
{
|
{
|
||||||
@@ -3336,7 +3376,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async void CheckOnionlocationForNonOnionHtmlRequests()
|
public async void CheckOnionlocationForNonOnionHtmlRequests()
|
||||||
{
|
{
|
||||||
@@ -3382,7 +3422,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanCheckForNewVersion()
|
public async Task CanCheckForNewVersion()
|
||||||
{
|
{
|
||||||
@@ -3428,7 +3468,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanDoLightningInternalNodeMigration()
|
public async Task CanDoLightningInternalNodeMigration()
|
||||||
{
|
{
|
||||||
@@ -3507,7 +3547,7 @@ namespace BTCPayServer.Tests
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task CanDoInvoiceMigrations()
|
public async Task CanDoInvoiceMigrations()
|
||||||
{
|
{
|
||||||
@@ -3588,7 +3628,7 @@ namespace BTCPayServer.Tests
|
|||||||
await migrationStartupTask.ExecuteAsync();
|
await migrationStartupTask.ExecuteAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Timeout = TestTimeout)]
|
[Fact(Timeout = LongRunningTestTimeout)]
|
||||||
[Trait("Integration", "Integration")]
|
[Trait("Integration", "Integration")]
|
||||||
public async Task EmailSenderTests()
|
public async Task EmailSenderTests()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -69,7 +69,12 @@ namespace BTCPayServer.Configuration
|
|||||||
BundleJsCss = conf.GetOrDefault<bool>("bundlejscss", true);
|
BundleJsCss = conf.GetOrDefault<bool>("bundlejscss", true);
|
||||||
DockerDeployment = conf.GetOrDefault<bool>("dockerdeployment", true);
|
DockerDeployment = conf.GetOrDefault<bool>("dockerdeployment", true);
|
||||||
AllowAdminRegistration = conf.GetOrDefault<bool>("allow-admin-registration", false);
|
AllowAdminRegistration = conf.GetOrDefault<bool>("allow-admin-registration", false);
|
||||||
|
|
||||||
TorrcFile = conf.GetOrDefault<string>("torrcfile", null);
|
TorrcFile = conf.GetOrDefault<string>("torrcfile", null);
|
||||||
|
TorServices = conf.GetOrDefault<string>("torservices", null)
|
||||||
|
?.Split(new[] {';', ','}, StringSplitOptions.RemoveEmptyEntries);
|
||||||
|
if (!string.IsNullOrEmpty(TorrcFile) && TorServices != null)
|
||||||
|
throw new ConfigException($"torrcfile or torservices should be provided, but not both");
|
||||||
|
|
||||||
var socksEndpointString = conf.GetOrDefault<string>("socksendpoint", null);
|
var socksEndpointString = conf.GetOrDefault<string>("socksendpoint", null);
|
||||||
if (!string.IsNullOrEmpty(socksEndpointString))
|
if (!string.IsNullOrEmpty(socksEndpointString))
|
||||||
@@ -195,6 +200,7 @@ namespace BTCPayServer.Configuration
|
|||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
public string TorrcFile { get; set; }
|
public string TorrcFile { get; set; }
|
||||||
|
public string[] TorServices { get; set; }
|
||||||
public Uri UpdateUrl { get; set; }
|
public Uri UpdateUrl { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,6 +39,7 @@ namespace BTCPayServer.Configuration
|
|||||||
app.Option("--sshauthorizedkeys", "Path to a authorized_keys file that BTCPayServer can modify from the website (default: empty)", CommandOptionType.SingleValue);
|
app.Option("--sshauthorizedkeys", "Path to a authorized_keys file that BTCPayServer can modify from the website (default: empty)", CommandOptionType.SingleValue);
|
||||||
app.Option("--sshtrustedfingerprints", "SSH Host public key fingerprint or sha256 (default: empty, it will allow untrusted connections)", CommandOptionType.SingleValue);
|
app.Option("--sshtrustedfingerprints", "SSH Host public key fingerprint or sha256 (default: empty, it will allow untrusted connections)", CommandOptionType.SingleValue);
|
||||||
app.Option("--torrcfile", "Path to torrc file containing hidden services directories (default: empty)", CommandOptionType.SingleValue);
|
app.Option("--torrcfile", "Path to torrc file containing hidden services directories (default: empty)", CommandOptionType.SingleValue);
|
||||||
|
app.Option("--torservices", "Tor hostnames of available services added to Server Settings (and sets onion header for btcpay). Format: btcpayserver:host.onion:80;btc-p2p:host2.onion:81,BTC-RPC:host3.onion:82,UNKNOWN:host4.onion:83. (default: empty)", CommandOptionType.SingleValue);
|
||||||
app.Option("--socksendpoint", "Socks endpoint to connect to onion urls (default: empty)", CommandOptionType.SingleValue);
|
app.Option("--socksendpoint", "Socks endpoint to connect to onion urls (default: empty)", CommandOptionType.SingleValue);
|
||||||
app.Option("--updateurl", $"Url used for once a day new release version check. Check performed only if value is not empty (default: empty)", CommandOptionType.SingleValue);
|
app.Option("--updateurl", $"Url used for once a day new release version check. Check performed only if value is not empty (default: empty)", CommandOptionType.SingleValue);
|
||||||
app.Option("--debuglog", "A rolling log file for debug messages.", CommandOptionType.SingleValue);
|
app.Option("--debuglog", "A rolling log file for debug messages.", CommandOptionType.SingleValue);
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Configuration;
|
|
||||||
using BTCPayServer.Services;
|
|
||||||
|
|
||||||
namespace BTCPayServer.HostedServices
|
|
||||||
{
|
|
||||||
public class TorServicesHostedService : BaseAsyncService
|
|
||||||
{
|
|
||||||
private readonly BTCPayServerOptions _options;
|
|
||||||
private readonly TorServices _torServices;
|
|
||||||
|
|
||||||
public TorServicesHostedService(BTCPayServerOptions options, TorServices torServices)
|
|
||||||
{
|
|
||||||
_options = options;
|
|
||||||
_torServices = torServices;
|
|
||||||
}
|
|
||||||
|
|
||||||
internal override Task[] InitializeTasks()
|
|
||||||
{
|
|
||||||
return new Task[] { CreateLoopTask(RefreshTorServices) };
|
|
||||||
}
|
|
||||||
|
|
||||||
async Task RefreshTorServices()
|
|
||||||
{
|
|
||||||
await _torServices.Refresh();
|
|
||||||
await Task.Delay(TimeSpan.FromSeconds(120), Cancellation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -93,6 +93,7 @@ namespace BTCPayServer.Hosting
|
|||||||
services.TryAddSingleton<ISettingsRepository>(provider => provider.GetService<SettingsRepository>());
|
services.TryAddSingleton<ISettingsRepository>(provider => provider.GetService<SettingsRepository>());
|
||||||
services.TryAddSingleton<LabelFactory>();
|
services.TryAddSingleton<LabelFactory>();
|
||||||
services.TryAddSingleton<TorServices>();
|
services.TryAddSingleton<TorServices>();
|
||||||
|
services.AddSingleton<IHostedService>(provider => provider.GetRequiredService<TorServices>());
|
||||||
services.TryAddSingleton<SocketFactory>();
|
services.TryAddSingleton<SocketFactory>();
|
||||||
services.TryAddSingleton<LightningClientFactoryService>();
|
services.TryAddSingleton<LightningClientFactoryService>();
|
||||||
services.TryAddSingleton<InvoicePaymentNotification>();
|
services.TryAddSingleton<InvoicePaymentNotification>();
|
||||||
@@ -346,7 +347,6 @@ namespace BTCPayServer.Hosting
|
|||||||
services.AddSingleton<IHostedService, TransactionLabelMarkerHostedService>();
|
services.AddSingleton<IHostedService, TransactionLabelMarkerHostedService>();
|
||||||
services.AddSingleton<IHostedService, UserEventHostedService>();
|
services.AddSingleton<IHostedService, UserEventHostedService>();
|
||||||
services.AddSingleton<IHostedService, DynamicDnsHostedService>();
|
services.AddSingleton<IHostedService, DynamicDnsHostedService>();
|
||||||
services.AddSingleton<IHostedService, TorServicesHostedService>();
|
|
||||||
services.AddSingleton<IHostedService, PaymentRequestStreamer>();
|
services.AddSingleton<IHostedService, PaymentRequestStreamer>();
|
||||||
services.AddSingleton<IBackgroundJobClient, BackgroundJobClient>();
|
services.AddSingleton<IBackgroundJobClient, BackgroundJobClient>();
|
||||||
services.AddScoped<IAuthorizationHandler, CookieAuthorizationHandler>();
|
services.AddScoped<IAuthorizationHandler, CookieAuthorizationHandler>();
|
||||||
|
|||||||
@@ -2,74 +2,77 @@ using System;
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Configuration;
|
using BTCPayServer.Configuration;
|
||||||
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Logging;
|
using BTCPayServer.Logging;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
|
||||||
namespace BTCPayServer.Services
|
namespace BTCPayServer.Services
|
||||||
{
|
{
|
||||||
public class TorServices
|
public class TorServices : BaseAsyncService
|
||||||
{
|
{
|
||||||
private readonly BTCPayNetworkProvider _networks;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
readonly BTCPayServerOptions _Options;
|
private readonly IOptions<BTCPayServerOptions> _options;
|
||||||
public TorServices(BTCPayServer.BTCPayNetworkProvider networks, BTCPayServerOptions options)
|
|
||||||
|
public TorServices(BTCPayNetworkProvider btcPayNetworkProvider, IOptions<BTCPayServerOptions> options)
|
||||||
{
|
{
|
||||||
_networks = networks;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_Options = options;
|
_options = options;
|
||||||
}
|
}
|
||||||
|
|
||||||
public TorService[] Services { get; internal set; } = Array.Empty<TorService>();
|
public TorService[] Services { get; internal set; } = Array.Empty<TorService>();
|
||||||
|
|
||||||
|
private bool firstRun = true;
|
||||||
internal async Task Refresh()
|
internal async Task Refresh()
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(_Options.TorrcFile) || !File.Exists(_Options.TorrcFile))
|
if (firstRun)
|
||||||
{
|
{
|
||||||
if (!string.IsNullOrEmpty(_Options.TorrcFile))
|
firstRun = false;
|
||||||
Logs.PayServer.LogWarning("Torrc file is not found");
|
}
|
||||||
Services = Array.Empty<TorService>();
|
else
|
||||||
return;
|
{
|
||||||
|
await Task.Delay(TimeSpan.FromSeconds(120), Cancellation);
|
||||||
}
|
}
|
||||||
List<TorService> result = new List<TorService>();
|
List<TorService> result = new List<TorService>();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var torrcContent = await File.ReadAllTextAsync(_Options.TorrcFile);
|
if (!File.Exists(_options.Value.TorrcFile))
|
||||||
|
{
|
||||||
|
Logs.PayServer.LogWarning("Torrc file is not found");
|
||||||
|
Services = Array.Empty<TorService>();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var torrcContent = await File.ReadAllTextAsync(_options.Value.TorrcFile);
|
||||||
if (!Torrc.TryParse(torrcContent, out var torrc))
|
if (!Torrc.TryParse(torrcContent, out var torrc))
|
||||||
{
|
{
|
||||||
Logs.PayServer.LogWarning("Torrc file could not be parsed");
|
Logs.PayServer.LogWarning("Torrc file could not be parsed");
|
||||||
Services = Array.Empty<TorService>();
|
Services = Array.Empty<TorService>();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
var torrcDir = Path.GetDirectoryName(_Options.TorrcFile);
|
|
||||||
var services = torrc.ServiceDirectories.SelectMany(d => d.ServicePorts.Select(p => (Directory: GetDirectory(d, torrcDir), VirtualPort: p.VirtualPort)))
|
var torrcDir = Path.GetDirectoryName(_options.Value.TorrcFile);
|
||||||
.Select(d => (ServiceName: d.Directory.Name,
|
var services = torrc.ServiceDirectories.SelectMany(d =>
|
||||||
ReadingLines: System.IO.File.ReadAllLinesAsync(Path.Combine(d.Directory.FullName, "hostname")),
|
d.ServicePorts.Select(p => (Directory: GetDirectory(d, torrcDir), VirtualPort: p.VirtualPort)))
|
||||||
VirtualPort: d.VirtualPort))
|
.Select(d => (ServiceName: d.Directory.Name,
|
||||||
.ToArray();
|
ReadingLines: System.IO.File.ReadAllLinesAsync(Path.Combine(d.Directory.FullName, "hostname")),
|
||||||
|
VirtualPort: d.VirtualPort))
|
||||||
|
.ToArray();
|
||||||
foreach (var service in services)
|
foreach (var service in services)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var onionHost = (await service.ReadingLines)[0].Trim();
|
var onionHost = (await service.ReadingLines)[0].Trim();
|
||||||
var torService = new TorService()
|
var torService = ParseService(service.ServiceName, onionHost, service.VirtualPort);
|
||||||
{
|
|
||||||
Name = service.ServiceName,
|
|
||||||
OnionHost = onionHost,
|
|
||||||
VirtualPort = service.VirtualPort
|
|
||||||
};
|
|
||||||
if (service.ServiceName.Equals("BTCPayServer", StringComparison.OrdinalIgnoreCase))
|
|
||||||
torService.ServiceType = TorServiceType.BTCPayServer;
|
|
||||||
else if (TryParseP2PService(service.ServiceName, out var network, out var serviceType))
|
|
||||||
{
|
|
||||||
torService.ServiceType = serviceType;
|
|
||||||
torService.Network = network;
|
|
||||||
}
|
|
||||||
result.Add(torService);
|
result.Add(torService);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logs.PayServer.LogWarning(ex, $"Error while reading hidden service {service.ServiceName} configuration");
|
Logs.PayServer.LogWarning(ex,
|
||||||
|
$"Error while reading hidden service {service.ServiceName} configuration");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,9 +80,29 @@ namespace BTCPayServer.Services
|
|||||||
{
|
{
|
||||||
Logs.PayServer.LogWarning(ex, $"Error while reading torrc file");
|
Logs.PayServer.LogWarning(ex, $"Error while reading torrc file");
|
||||||
}
|
}
|
||||||
|
|
||||||
Services = result.ToArray();
|
Services = result.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private TorService ParseService(string serviceName, string onionHost, int virtualPort)
|
||||||
|
{
|
||||||
|
var torService = new TorService() {Name = serviceName, OnionHost = onionHost, VirtualPort = virtualPort};
|
||||||
|
|
||||||
|
if (Enum.TryParse<TorServiceType>(serviceName, true, out var serviceType))
|
||||||
|
torService.ServiceType = serviceType;
|
||||||
|
else if (TryParseCryptoSpecificService(serviceName, out var network, out serviceType))
|
||||||
|
{
|
||||||
|
torService.ServiceType = serviceType;
|
||||||
|
torService.Network = network;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
torService.ServiceType = TorServiceType.Other;
|
||||||
|
}
|
||||||
|
|
||||||
|
return torService;
|
||||||
|
}
|
||||||
|
|
||||||
private static DirectoryInfo GetDirectory(HiddenServiceDir hs, string relativeTo)
|
private static DirectoryInfo GetDirectory(HiddenServiceDir hs, string relativeTo)
|
||||||
{
|
{
|
||||||
if (Path.IsPathRooted(hs.DirectoryPath))
|
if (Path.IsPathRooted(hs.DirectoryPath))
|
||||||
@@ -87,25 +110,42 @@ namespace BTCPayServer.Services
|
|||||||
return new DirectoryInfo(Path.Combine(relativeTo, hs.DirectoryPath));
|
return new DirectoryInfo(Path.Combine(relativeTo, hs.DirectoryPath));
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryParseP2PService(string name, out BTCPayNetworkBase network, out TorServiceType serviceType)
|
private bool TryParseCryptoSpecificService(string name, out BTCPayNetworkBase network,
|
||||||
|
out TorServiceType serviceType)
|
||||||
{
|
{
|
||||||
network = null;
|
network = null;
|
||||||
serviceType = TorServiceType.Other;
|
serviceType = TorServiceType.Other;
|
||||||
var splitted = name.Trim().Split('-');
|
var splitted = name.Trim().Split('-');
|
||||||
if (splitted.Length == 2 && splitted[1] == "P2P")
|
return splitted.Length == 2 && Enum.TryParse(splitted[1], true, out serviceType) &&
|
||||||
|
_btcPayNetworkProvider.TryGetNetwork(splitted[0], out network);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override async Task StartAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(_options.Value.TorrcFile))
|
||||||
{
|
{
|
||||||
serviceType = TorServiceType.P2P;
|
LoadFromConfig();
|
||||||
}
|
|
||||||
else if (splitted.Length == 2 && splitted[1] == "RPC")
|
|
||||||
{
|
|
||||||
serviceType = TorServiceType.RPC;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return false;
|
await Refresh();
|
||||||
|
await base.StartAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
network = _networks.GetNetwork<BTCPayNetworkBase>(splitted[0]);
|
}
|
||||||
return network != null;
|
|
||||||
|
internal override Task[] InitializeTasks()
|
||||||
|
{
|
||||||
|
return new[] {CreateLoopTask(Refresh)};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LoadFromConfig()
|
||||||
|
{
|
||||||
|
Services = _options.Value.TorServices.Select(p => p.Split(":", StringSplitOptions.RemoveEmptyEntries))
|
||||||
|
.Where(p => p.Length == 3)
|
||||||
|
.Select(strings =>
|
||||||
|
int.TryParse(strings[2], out var port) ? ParseService(strings[0], strings[1], port) : null)
|
||||||
|
.Where(p => p != null)
|
||||||
|
.ToArray();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user