diff --git a/BTCPayServer.Tests/README.md b/BTCPayServer.Tests/README.md
index 5b1d7689b..4b65f03a4 100644
--- a/BTCPayServer.Tests/README.md
+++ b/BTCPayServer.Tests/README.md
@@ -26,7 +26,7 @@ docker-compose down
If you want to stop, and remove all existing data
```
-docker-compose down -v
+docker-compose down --v
```
You can run the tests inside a container by running
@@ -35,7 +35,9 @@ You can run the tests inside a container by running
docker-compose run --rm tests
```
-## Send commands to bitcoind
+## How to manually test payments
+
+### Using the test bitcoin-cli
You can call bitcoin-cli inside the container with `docker exec`, for example, if you want to send `0.23111090` to `mohu16LH66ptoWGEL1GtP6KHTBJYXMWhEf`:
```
@@ -47,7 +49,28 @@ If you are using Powershell:
.\docker-bitcoin-cli.ps1 sendtoaddress "mohu16LH66ptoWGEL1GtP6KHTBJYXMWhEf" 0.23111090
```
-For sending to litecoin, use .\docker-litecoin-cli.ps1 instead.
+### Using the test litecoin-cli
+
+Same as bitcoin-cli, but with `.\docker-litecoin-cli.ps1` instead.
+
+### Using the test lightning-cli
+
+```
+docker exec -ti btcpayservertests_customer_lightningd_1 lightning-cli pay lnbcrt100u1pd2e6uspp5ajnadvhazjrz55twd5k6yeg9u87wpw0q2fdr7g960yl5asv5fmnqdq9d3hkccqpxmedyrk0ehw5ueqx5e0r4qrrv74cewddfcvsxaawqz7634cmjj39sqwy5tvhz0hasktkk6t9pqfdh3edmf3z09zst5y7khv3rvxh8ctqqw6mwhh
+```
+
+If you are using Powershell:
+```
+.\docker-customer-lightning-cli.ps1 pay lnbcrt100u1pd2e6uspp5ajnadvhazjrz55twd5k6yeg9u87wpw0q2fdr7g960yl5asv5fmnqdq9d3hkccqpxmedyrk0ehw5ueqx5e0r4qrrv74cewddfcvsxaawqz7634cmjj39sqwy5tvhz0hasktkk6t9pqfdh3edmf3z09zst5y7khv3rvxh8ctqqw6mwhh
+```
+
+If you get this message:
+
+```
+{ "code" : 205, "message" : "Could not find a route", "data" : { "getroute_tries" : 1, "sendpay_tries" : 0 } }
+```
+
+Please, run the test `CanSetLightningServer`, this will establish a channel between the customer and the merchant, then, retry.
## FAQ
diff --git a/BTCPayServer.Tests/ServerTester.cs b/BTCPayServer.Tests/ServerTester.cs
index dbd01b834..04d526cd0 100644
--- a/BTCPayServer.Tests/ServerTester.cs
+++ b/BTCPayServer.Tests/ServerTester.cs
@@ -102,6 +102,7 @@ namespace BTCPayServer.Tests
await ExplorerNode.SendToAddressAsync(address, Money.Coins(0.2m));
ExplorerNode.Generate(1);
await WaitLNSynched();
+ await Task.Delay(1000);
await CustomerLightningD.FundChannelAsync(clightning, Money.Satoshis(16777215));
break;
case "CHANNELD_AWAITING_LOCKIN":
diff --git a/BTCPayServer.Tests/docker-compose.yml b/BTCPayServer.Tests/docker-compose.yml
index ec45c6cff..7672bbec9 100644
--- a/BTCPayServer.Tests/docker-compose.yml
+++ b/BTCPayServer.Tests/docker-compose.yml
@@ -17,7 +17,7 @@ services:
TESTS_POSTGRES: User ID=postgres;Host=postgres;Port=5432;Database=btcpayserver
TESTS_PORT: 80
TESTS_HOSTNAME: tests
- TEST_CUSTOMERLIGHTNINGD: http://lightningd:9835/
+ TEST_CUSTOMERLIGHTNINGD: http://customer_lightningd:9835/
TEST_MERCHANTCHARGE: http://api-token:foiewnccewuify@lightning-charged:9112/
expose:
- "80"
@@ -36,7 +36,8 @@ services:
links:
- nbxplorer
- postgres
- - lightningd
+ - customer_lightningd
+ - merchant_lightningd
- lightning-charged
nbxplorer:
@@ -83,24 +84,7 @@ services:
volumes:
- "bitcoin_datadir:/data"
- lightning-charged:
- image: shesek/lightning-charge:0.3.5
- environment:
- NETWORK: regtest
- API_TOKEN: foiewnccewuify
- SKIP_BITCOIND: 1
- BITCOIND_RPCCONNECT: bitcoind
- volumes:
- - "bitcoin_datadir:/etc/bitcoin"
- expose:
- - "9112" # Charge
- - "9735" # Lightning
- ports:
- - "54938:9112" # Charge
- links:
- - bitcoind
-
- lightningd:
+ customer_lightningd:
image: nicolasdorier/clightning
environment:
LIGHTNINGD_OPT: |
@@ -115,6 +99,46 @@ services:
- "9835" # api port
volumes:
- "bitcoin_datadir:/etc/bitcoin"
+ - "customer_lightningd_datadir:/root/.lightning"
+ links:
+ - bitcoind
+
+ lightning-charged:
+ image: shesek/lightning-charge:0.3.5
+ environment:
+ NETWORK: regtest
+ API_TOKEN: foiewnccewuify
+ SKIP_BITCOIND: 1
+ BITCOIND_RPCCONNECT: bitcoind
+ volumes:
+ - "bitcoin_datadir:/etc/bitcoin"
+ - "lightning_charge_datadir:/data"
+ - "merchant_lightningd_datadir:/etc/lightning"
+ expose:
+ - "9112" # Charge
+ - "9735" # Lightning
+ ports:
+ - "54938:9112" # Charge
+ links:
+ - bitcoind
+ - merchant_lightningd
+
+ merchant_lightningd:
+ image: nicolasdorier/clightning
+ environment:
+ LIGHTNINGD_OPT: |
+ bitcoin-datadir=/etc/bitcoin
+ bitcoin-rpcconnect=bitcoind
+ network=regtest
+ log-level=debug
+ ports:
+ - "30993:9835" # api port
+ expose:
+ - "9735" # server port
+ - "9835" # api port
+ volumes:
+ - "bitcoin_datadir:/etc/bitcoin"
+ - "merchant_lightningd_datadir:/root/.lightning"
links:
- bitcoind
@@ -145,3 +169,6 @@ services:
volumes:
bitcoin_datadir:
+ customer_lightningd_datadir:
+ merchant_lightningd_datadir:
+ lightning_charge_datadir:
diff --git a/BTCPayServer.Tests/docker-customer-lightning-cli.ps1 b/BTCPayServer.Tests/docker-customer-lightning-cli.ps1
new file mode 100644
index 000000000..64209bfe0
--- /dev/null
+++ b/BTCPayServer.Tests/docker-customer-lightning-cli.ps1
@@ -0,0 +1 @@
+docker exec -ti btcpayservertests_customer_lightningd_1 lightning-cli $args
diff --git a/BTCPayServer/Payments/Lightning/ChargeListener.cs b/BTCPayServer/Payments/Lightning/ChargeListener.cs
index c2b7f6e6c..4f031409b 100644
--- a/BTCPayServer/Payments/Lightning/ChargeListener.cs
+++ b/BTCPayServer/Payments/Lightning/ChargeListener.cs
@@ -60,6 +60,8 @@ namespace BTCPayServer.Payments.Lightning
private async Task EnsureListening(string invoiceId, bool poll)
{
+ if (Listening(invoiceId))
+ return;
var invoice = await _InvoiceRepository.GetInvoice(null, invoiceId);
foreach (var paymentMethod in invoice.GetPaymentMethods(_NetworkProvider)
.Where(c => c.GetId().PaymentType == PaymentTypes.LightningLike))
@@ -89,16 +91,13 @@ namespace BTCPayServer.Payments.Lightning
var chargeInvoice = await charge.GetInvoice(lightningMethod.InvoiceId);
if (chargeInvoice == null)
continue;
- if(chargeInvoice.Status == "paid")
+ if (chargeInvoice.Status == "paid")
await AddPayment(network, chargeInvoice, listenedInvoice);
if (chargeInvoice.Status == "paid" || chargeInvoice.Status == "expired")
continue;
}
- if (!Listening(invoiceId))
- {
- StartListening(listenedInvoice);
- }
+ StartListening(listenedInvoice);
}
}
@@ -157,6 +156,7 @@ namespace BTCPayServer.Payments.Lightning
catch (Exception ex)
{
Logs.PayServer.LogError(ex, $"{supportedPaymentMethod.CryptoCode} (Lightning): Error while contacting {supportedPaymentMethod.GetLightningChargeUrl(false)}");
+ DoneListening(supportedPaymentMethod.GetLightningChargeUrl(false));
}
Logs.PayServer.LogInformation($"{supportedPaymentMethod.CryptoCode} (Lightning): Stop listening {supportedPaymentMethod.GetLightningChargeUrl(false)}");
}
@@ -202,9 +202,26 @@ namespace BTCPayServer.Payments.Lightning
return false;
}
+ ///
+ /// Stop listening all invoices on this server
+ ///
+ ///
+ private void DoneListening(Uri uri)
+ {
+ lock (_ListenedInvoiceByChargeInvoiceId)
+ {
+ foreach (var listenedInvoice in _ListenedInvoiceByLightningUrl[uri.AbsoluteUri])
+ {
+ _ListenedInvoiceByChargeInvoiceId.Remove(listenedInvoice.PaymentMethodDetails.InvoiceId);
+ _InvoiceIds.Remove(listenedInvoice.InvoiceId);
+ }
+ _ListenedInvoiceByLightningUrl.Remove(uri.AbsoluteUri);
+ }
+ }
+
bool Listening(string invoiceId)
{
- lock(_ListenedInvoiceByLightningUrl)
+ lock (_ListenedInvoiceByLightningUrl)
{
return _InvoiceIds.Contains(invoiceId);
}
@@ -230,10 +247,6 @@ namespace BTCPayServer.Payments.Lightning
{
var listen = Listen(listenedInvoice.SupportedPaymentMethod, listenedInvoice.Network);
_ListeningLightning.Add(listen);
- listen.ContinueWith(_ =>
- {
- DoneListening(listenedInvoice);
- }, TaskScheduler.Default);
}
_ListenedInvoiceByLightningUrl.Add(listenedInvoice.Uri, listenedInvoice);
_ListenedInvoiceByChargeInvoiceId.Add(listenedInvoice.PaymentMethodDetails.InvoiceId, listenedInvoice);
diff --git a/BTCPayServer/Services/Wallets/BTCPayWallet.cs b/BTCPayServer/Services/Wallets/BTCPayWallet.cs
index af8cfd749..2877c91c3 100644
--- a/BTCPayServer/Services/Wallets/BTCPayWallet.cs
+++ b/BTCPayServer/Services/Wallets/BTCPayWallet.cs
@@ -126,13 +126,13 @@ namespace BTCPayServer.Services.Wallets
}
catch
{
- Logs.PayServer.LogError("Call to NBXplorer GetUTXOsAsync timed out, this should never happen, please report this issue to NBXplorer developers");
+ Logs.PayServer.LogError($"{Network.CryptoCode}: Call to NBXplorer GetUTXOsAsync timed out, this should never happen, please report this issue to NBXplorer developers");
throw;
}
var spentTime = DateTimeOffset.UtcNow - now;
if (spentTime.TotalSeconds > 30)
{
- Logs.PayServer.LogWarning($"NBXplorer took {(int)spentTime.TotalSeconds} seconds to reply, there is something wrong, please report this issue to NBXplorer developers");
+ Logs.PayServer.LogWarning($"{Network.CryptoCode}: NBXplorer took {(int)spentTime.TotalSeconds} seconds to reply, there is something wrong, please report this issue to NBXplorer developers");
}
entry.AbsoluteExpiration = DateTimeOffset.UtcNow + CacheSpan;
return result;