Update NBitcoin, fix warnings on nullable (#2718)

This commit is contained in:
Nicolas Dorier
2021-07-29 20:29:34 +09:00
committed by GitHub
parent 499a231432
commit 6ea96efe68
22 changed files with 97 additions and 72 deletions

View File

@@ -27,8 +27,8 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="NBitcoin" Version="5.0.81" /> <PackageReference Include="NBitcoin" Version="6.0.4" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.2.0" /> <PackageReference Include="BTCPayServer.Lightning.Common" Version="1.2.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View File

@@ -4,7 +4,7 @@
<ItemGroup> <ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="NBXplorer.Client" Version="3.0.21" /> <PackageReference Include="NBXplorer.Client" Version="4.0.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition="'$(Altcoins)' != 'true'"> <ItemGroup Condition="'$(Altcoins)' != 'true'">
<Compile Remove="Altcoins\**\*.cs"></Compile> <Compile Remove="Altcoins\**\*.cs"></Compile>

View File

@@ -6,7 +6,7 @@
<FrameworkReference Include="Microsoft.AspNetCore.App" /> <FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" /> <PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.6.0" />
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" /> <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
<PackageReference Include="NBitcoin" Version="5.0.81" /> <PackageReference Include="NBitcoin" Version="6.0.4" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.3" /> <PackageReference Include="Newtonsoft.Json" Version="12.0.3" />
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.6.3" /> <PackageReference Include="DigitalRuby.ExchangeSharp" Version="0.6.3" />
</ItemGroup> </ItemGroup>

View File

@@ -1937,7 +1937,7 @@ namespace BTCPayServer.Tests
} }
var methods = await adminClient.GetStorePaymentMethods(store.Id); var methods = await adminClient.GetStorePaymentMethods(store.Id);
Assert.Equal(1, methods.Count); Assert.Single(methods);
VerifyLightning(methods); VerifyLightning(methods);
var randK = new Mnemonic(Wordlist.English, WordCount.Twelve).DeriveExtKey().Neuter().ToString(Network.RegTest); var randK = new Mnemonic(Wordlist.English, WordCount.Twelve).DeriveExtKey().Neuter().ToString(Network.RegTest);

View File

@@ -146,7 +146,7 @@ namespace BTCPayServer.Tests
{ {
var tx = network.NBitcoinNetwork.CreateTransaction(); var tx = network.NBitcoinNetwork.CreateTransaction();
tx.Inputs.Add(new OutPoint(RandomUtils.GetUInt256(), 0), Script.Empty); tx.Inputs.Add(new OutPoint(RandomUtils.GetUInt256(), 0), Script.Empty);
tx.Outputs.Add(Money.Coins(1.0m), new Key().ScriptPubKey); tx.Outputs.Add(Money.Coins(1.0m), new Key().GetScriptPubKey(ScriptPubKeyType.Legacy));
return tx; return tx;
} }
@@ -184,12 +184,16 @@ namespace BTCPayServer.Tests
foreach (ScriptPubKeyType senderAddressType in Enum.GetValues(typeof(ScriptPubKeyType))) foreach (ScriptPubKeyType senderAddressType in Enum.GetValues(typeof(ScriptPubKeyType)))
{ {
if (senderAddressType == ScriptPubKeyType.TaprootBIP86)
continue;
var senderUser = tester.NewAccount(); var senderUser = tester.NewAccount();
senderUser.GrantAccess(true); senderUser.GrantAccess(true);
senderUser.RegisterDerivationScheme("BTC", senderAddressType); senderUser.RegisterDerivationScheme("BTC", senderAddressType);
foreach (ScriptPubKeyType receiverAddressType in Enum.GetValues(typeof(ScriptPubKeyType))) foreach (ScriptPubKeyType receiverAddressType in Enum.GetValues(typeof(ScriptPubKeyType)))
{ {
if (receiverAddressType == ScriptPubKeyType.TaprootBIP86)
continue;
var senderCoin = await senderUser.ReceiveUTXO(Money.Satoshis(100000), network); var senderCoin = await senderUser.ReceiveUTXO(Money.Satoshis(100000), network);
Logs.Tester.LogInformation($"Testing payjoin with sender: {senderAddressType} receiver: {receiverAddressType}"); Logs.Tester.LogInformation($"Testing payjoin with sender: {senderAddressType} receiver: {receiverAddressType}");

View File

@@ -1689,7 +1689,10 @@ namespace BTCPayServer.Tests
var invoice2Address = var invoice2Address =
BitcoinAddress.Create(invoice2.BitcoinAddress, user.SupportedNetwork.NBitcoinNetwork); BitcoinAddress.Create(invoice2.BitcoinAddress, user.SupportedNetwork.NBitcoinNetwork);
uint256 invoice2tx1Id = uint256 invoice2tx1Id =
await tester.ExplorerNode.SendToAddressAsync(invoice2Address, invoice2.BtcDue, replaceable: true); await tester.ExplorerNode.SendToAddressAsync(invoice2Address, invoice2.BtcDue, new NBitcoin.RPC.SendToAddressParameters()
{
Replaceable = true
});
Transaction invoice2Tx1 = null; Transaction invoice2Tx1 = null;
TestUtils.Eventually(() => TestUtils.Eventually(() =>
{ {
@@ -1707,7 +1710,7 @@ namespace BTCPayServer.Tests
output = invoice2Tx2.Outputs.First(o => output = invoice2Tx2.Outputs.First(o =>
o.ScriptPubKey == invoice2Address.ScriptPubKey); o.ScriptPubKey == invoice2Address.ScriptPubKey);
output.Value -= new Money(10_000, MoneyUnit.Satoshi); output.Value -= new Money(10_000, MoneyUnit.Satoshi);
output.ScriptPubKey = new Key().ScriptPubKey; output.ScriptPubKey = new Key().GetScriptPubKey(ScriptPubKeyType.Legacy);
invoice2Tx2 = await tester.ExplorerNode.SignRawTransactionAsync(invoice2Tx2); invoice2Tx2 = await tester.ExplorerNode.SignRawTransactionAsync(invoice2Tx2);
await tester.ExplorerNode.SendRawTransactionAsync(invoice2Tx2); await tester.ExplorerNode.SendRawTransactionAsync(invoice2Tx2);
tester.ExplorerNode.Generate(1); tester.ExplorerNode.Generate(1);

View File

@@ -84,7 +84,7 @@ services:
- customer_lnd - customer_lnd
- merchant_lnd - merchant_lnd
nbxplorer: nbxplorer:
image: nicolasdorier/nbxplorer:2.1.49 image: nicolasdorier/nbxplorer:2.1.53
restart: unless-stopped restart: unless-stopped
ports: ports:
- "32838:32838" - "32838:32838"

View File

@@ -81,7 +81,7 @@ services:
- customer_lnd - customer_lnd
- merchant_lnd - merchant_lnd
nbxplorer: nbxplorer:
image: nicolasdorier/nbxplorer:2.1.49 image: nicolasdorier/nbxplorer:2.1.53
restart: unless-stopped restart: unless-stopped
ports: ports:
- "32838:32838" - "32838:32838"

View File

@@ -46,7 +46,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="BIP78.Sender" Version="0.2.0" /> <PackageReference Include="BIP78.Sender" Version="0.2.0" />
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.1" /> <PackageReference Include="BTCPayServer.Hwi" Version="2.0.1" />
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.2.7" /> <PackageReference Include="BTCPayServer.Lightning.All" Version="1.2.9" />
<PackageReference Include="BuildBundlerMinifier" Version="3.2.449" /> <PackageReference Include="BuildBundlerMinifier" Version="3.2.449" />
<PackageReference Include="BundlerMinifier.Core" Version="3.2.435" /> <PackageReference Include="BundlerMinifier.Core" Version="3.2.435" />
<PackageReference Include="BundlerMinifier.TagHelpers" Version="3.2.435" /> <PackageReference Include="BundlerMinifier.TagHelpers" Version="3.2.435" />

View File

@@ -504,11 +504,11 @@ namespace BTCPayServer.Controllers.GreenField
return Task.FromResult(GetFromActionResult(_chainPaymentMethodsController.GetOnChainPaymentMethods(storeId, enabled))); return Task.FromResult(GetFromActionResult(_chainPaymentMethodsController.GetOnChainPaymentMethods(storeId, enabled)));
} }
public override async Task<OnChainPaymentMethodData> GetStoreOnChainPaymentMethod(string storeId, public override Task<OnChainPaymentMethodData> GetStoreOnChainPaymentMethod(string storeId,
string cryptoCode, CancellationToken token = default) string cryptoCode, CancellationToken token = default)
{ {
return GetFromActionResult( return Task.FromResult(GetFromActionResult(
await _chainPaymentMethodsController.GetOnChainPaymentMethod(storeId, cryptoCode)); _chainPaymentMethodsController.GetOnChainPaymentMethod(storeId, cryptoCode)));
} }
public override async Task RemoveStoreOnChainPaymentMethod(string storeId, string cryptoCode, public override async Task RemoveStoreOnChainPaymentMethod(string storeId, string cryptoCode,
@@ -534,13 +534,13 @@ namespace BTCPayServer.Controllers.GreenField
paymentMethod, offset, amount))); paymentMethod, offset, amount)));
} }
public override async Task<OnChainPaymentMethodPreviewResultData> PreviewStoreOnChainPaymentMethodAddresses( public override Task<OnChainPaymentMethodPreviewResultData> PreviewStoreOnChainPaymentMethodAddresses(
string storeId, string cryptoCode, int offset = 0, int amount = 10, string storeId, string cryptoCode, int offset = 0, int amount = 10,
CancellationToken token = default) CancellationToken token = default)
{ {
return GetFromActionResult<OnChainPaymentMethodPreviewResultData>( return Task.FromResult(GetFromActionResult<OnChainPaymentMethodPreviewResultData>(
await _chainPaymentMethodsController.GetOnChainPaymentMethodPreview(storeId, cryptoCode, offset, _chainPaymentMethodsController.GetOnChainPaymentMethodPreview(storeId, cryptoCode, offset,
amount)); amount)));
} }
public override Task<ApiHealthData> GetHealth(CancellationToken token = default) public override Task<ApiHealthData> GetHealth(CancellationToken token = default)

View File

@@ -1,5 +1,6 @@
#nullable enable #nullable enable
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants; using BTCPayServer.Abstractions.Constants;
@@ -122,7 +123,7 @@ namespace BTCPayServer.Controllers.GreenField
return NotFound(); return NotFound();
} }
if (string.IsNullOrEmpty(paymentMethodData?.ConnectionString)) if (string.IsNullOrEmpty(paymentMethodData.ConnectionString))
{ {
ModelState.AddModelError(nameof(LightningNetworkPaymentMethodData.ConnectionString), ModelState.AddModelError(nameof(LightningNetworkPaymentMethodData.ConnectionString),
"Missing connectionString"); "Missing connectionString");
@@ -131,8 +132,8 @@ namespace BTCPayServer.Controllers.GreenField
if (!ModelState.IsValid) if (!ModelState.IsValid)
return this.CreateValidationError(ModelState); return this.CreateValidationError(ModelState);
LightningSupportedPaymentMethod paymentMethod = null; LightningSupportedPaymentMethod? paymentMethod = null;
if (!string.IsNullOrEmpty(paymentMethodData.ConnectionString)) if (!string.IsNullOrEmpty(paymentMethodData!.ConnectionString))
{ {
if (paymentMethodData.ConnectionString == LightningSupportedPaymentMethod.InternalNode) if (paymentMethodData.ConnectionString == LightningSupportedPaymentMethod.InternalNode)
{ {
@@ -189,8 +190,8 @@ namespace BTCPayServer.Controllers.GreenField
return Ok(GetExistingLightningLikePaymentMethod(cryptoCode, store)); return Ok(GetExistingLightningLikePaymentMethod(cryptoCode, store));
} }
private LightningNetworkPaymentMethodData GetExistingLightningLikePaymentMethod(string cryptoCode, private LightningNetworkPaymentMethodData? GetExistingLightningLikePaymentMethod(string cryptoCode,
StoreData store = null) StoreData? store = null)
{ {
store ??= Store; store ??= Store;
var storeBlob = store.GetStoreBlob(); var storeBlob = store.GetStoreBlob();
@@ -201,13 +202,13 @@ namespace BTCPayServer.Controllers.GreenField
.FirstOrDefault(method => method.PaymentId == id); .FirstOrDefault(method => method.PaymentId == id);
var excluded = storeBlob.IsExcluded(id); var excluded = storeBlob.IsExcluded(id);
return paymentMethod == null return paymentMethod is null
? null ? null
: new LightningNetworkPaymentMethodData(paymentMethod.PaymentId.CryptoCode, : new LightningNetworkPaymentMethodData(paymentMethod.PaymentId.CryptoCode,
paymentMethod.GetDisplayableConnectionString(), !excluded); paymentMethod.GetDisplayableConnectionString(), !excluded);
} }
private bool GetNetwork(string cryptoCode, out BTCPayNetwork network) private bool GetNetwork(string cryptoCode, [MaybeNullWhen(false)] out BTCPayNetwork network)
{ {
network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode); network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
network = network?.SupportLightning is true ? network : null; network = network?.SupportLightning is true ? network : null;

View File

@@ -73,7 +73,7 @@ namespace BTCPayServer.Controllers.GreenField
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)] [Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}")] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}")]
public async Task<ActionResult<OnChainPaymentMethodData>> GetOnChainPaymentMethod( public ActionResult<OnChainPaymentMethodData> GetOnChainPaymentMethod(
string storeId, string storeId,
string cryptoCode) string cryptoCode)
{ {
@@ -93,7 +93,7 @@ namespace BTCPayServer.Controllers.GreenField
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)] [Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/preview")] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/preview")]
public async Task<IActionResult> GetOnChainPaymentMethodPreview( public IActionResult GetOnChainPaymentMethodPreview(
string storeId, string storeId,
string cryptoCode, string cryptoCode,
int offset = 0, int amount = 10) int offset = 0, int amount = 10)

View File

@@ -1,6 +1,7 @@
#nullable enable #nullable enable
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
@@ -83,8 +84,8 @@ namespace BTCPayServer.Controllers.GreenField
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet")] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet")]
public async Task<IActionResult> ShowOnChainWalletOverview(string storeId, string cryptoCode) public async Task<IActionResult> ShowOnChainWalletOverview(string storeId, string cryptoCode)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
var balance = await wallet.GetBalance(derivationScheme.AccountDerivation); var balance = await wallet.GetBalance(derivationScheme.AccountDerivation);
@@ -102,8 +103,8 @@ namespace BTCPayServer.Controllers.GreenField
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feerate")] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feerate")]
public async Task<IActionResult> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null) public async Task<IActionResult> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var feeRateTarget = blockTarget?? Store.GetStoreBlob().RecommendedFeeBlockTarget; var feeRateTarget = blockTarget?? Store.GetStoreBlob().RecommendedFeeBlockTarget;
return Ok(new OnChainWalletFeeRateData() return Ok(new OnChainWalletFeeRateData()
@@ -117,8 +118,8 @@ namespace BTCPayServer.Controllers.GreenField
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")]
public async Task<IActionResult> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false) public async Task<IActionResult> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var kpi = await _walletReceiveService.GetOrGenerate(new WalletId(storeId, cryptoCode), forceGenerate); var kpi = await _walletReceiveService.GetOrGenerate(new WalletId(storeId, cryptoCode), forceGenerate);
if (kpi is null) if (kpi is null)
@@ -145,8 +146,8 @@ namespace BTCPayServer.Controllers.GreenField
[HttpDelete("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")] [HttpDelete("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")]
public async Task<IActionResult> UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode) public async Task<IActionResult> UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var addr = await _walletReceiveService.UnReserveAddress(new WalletId(storeId, cryptoCode)); var addr = await _walletReceiveService.UnReserveAddress(new WalletId(storeId, cryptoCode));
if (addr is null) if (addr is null)
@@ -166,8 +167,8 @@ namespace BTCPayServer.Controllers.GreenField
[FromQuery] int limit = int.MaxValue [FromQuery] int limit = int.MaxValue
) )
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
var walletId = new WalletId(storeId, cryptoCode); var walletId = new WalletId(storeId, cryptoCode);
@@ -203,8 +204,8 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> GetOnChainWalletTransaction(string storeId, string cryptoCode, public async Task<IActionResult> GetOnChainWalletTransaction(string storeId, string cryptoCode,
string transactionId) string transactionId)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
var tx = await wallet.FetchTransaction(derivationScheme.AccountDerivation, uint256.Parse(transactionId)); var tx = await wallet.FetchTransaction(derivationScheme.AccountDerivation, uint256.Parse(transactionId));
@@ -225,8 +226,8 @@ namespace BTCPayServer.Controllers.GreenField
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/utxos")] [HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/utxos")]
public async Task<IActionResult> GetOnChainWalletUTXOs(string storeId, string cryptoCode) public async Task<IActionResult> GetOnChainWalletUTXOs(string storeId, string cryptoCode)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network); var wallet = _btcPayWalletProvider.GetWallet(network);
@@ -258,8 +259,8 @@ namespace BTCPayServer.Controllers.GreenField
public async Task<IActionResult> CreateOnChainTransaction(string storeId, string cryptoCode, public async Task<IActionResult> CreateOnChainTransaction(string storeId, string cryptoCode,
[FromBody] CreateOnChainTransactionRequest request) [FromBody] CreateOnChainTransactionRequest request)
{ {
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network, if (IsInvalidWalletRequest(cryptoCode, out var network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult; out var derivationScheme, out var actionResult)) return actionResult;
if (network.ReadonlyWallet) if (network.ReadonlyWallet)
{ {
return this.CreateAPIError("not-available", return this.CreateAPIError("not-available",
@@ -445,8 +446,13 @@ namespace BTCPayServer.Controllers.GreenField
psbt.PSBT.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath); psbt.PSBT.RebaseKeyPaths(signingKeySettings.AccountKey, rootedKeyPath);
var accountKey = signingKey.Derive(rootedKeyPath.KeyPath); var accountKey = signingKey.Derive(rootedKeyPath.KeyPath);
if (signingContext?.EnforceLowR is bool v)
psbt.PSBT.Settings.SigningOptions.EnforceLowR = v;
else if (psbt.Suggestions?.ShouldEnforceLowR is bool v2)
psbt.PSBT.Settings.SigningOptions.EnforceLowR = v2;
var changed = psbt.PSBT.PSBTChanged(() => psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, var changed = psbt.PSBT.PSBTChanged(() => psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey,
rootedKeyPath, new SigningOptions() {EnforceLowR = signingContext?.EnforceLowR is bool v ? v : psbt.Suggestions.ShouldEnforceLowR })); rootedKeyPath));
if (!changed) if (!changed)
{ {
@@ -458,7 +464,7 @@ namespace BTCPayServer.Controllers.GreenField
var transaction = psbt.PSBT.ExtractTransaction(); var transaction = psbt.PSBT.ExtractTransaction();
var transactionHash = transaction.GetHash(); var transactionHash = transaction.GetHash();
BroadcastResult broadcastResult; BroadcastResult broadcastResult;
if (!string.IsNullOrEmpty(signingContext.PayJoinBIP21)) if (!string.IsNullOrEmpty(signingContext?.PayJoinBIP21))
{ {
signingContext.OriginalPSBT = psbt.PSBT.ToBase64(); signingContext.OriginalPSBT = psbt.PSBT.ToBase64();
try try
@@ -468,8 +474,8 @@ namespace BTCPayServer.Controllers.GreenField
var payjoinPSBT = await _payjoinClient.RequestPayjoin( var payjoinPSBT = await _payjoinClient.RequestPayjoin(
new BitcoinUrlBuilder(signingContext.PayJoinBIP21, network.NBitcoinNetwork), new PayjoinWallet(derivationScheme), new BitcoinUrlBuilder(signingContext.PayJoinBIP21, network.NBitcoinNetwork), new PayjoinWallet(derivationScheme),
psbt.PSBT, CancellationToken.None); psbt.PSBT, CancellationToken.None);
payjoinPSBT = psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, rootedKeyPath, psbt.PSBT.Settings.SigningOptions = new SigningOptions() { EnforceLowR = !(signingContext?.EnforceLowR is false) };
new SigningOptions() {EnforceLowR = !(signingContext?.EnforceLowR is false)}); payjoinPSBT = psbt.PSBT.SignAll(derivationScheme.AccountDerivation, accountKey, rootedKeyPath);
payjoinPSBT.Finalize(); payjoinPSBT.Finalize();
var payjoinTransaction = payjoinPSBT.ExtractTransaction(); var payjoinTransaction = payjoinPSBT.ExtractTransaction();
var hash = payjoinTransaction.GetHash(); var hash = payjoinTransaction.GetHash();
@@ -508,11 +514,10 @@ namespace BTCPayServer.Controllers.GreenField
return await _authorizationService.CanUseHotWallet(await _settingsRepository.GetPolicies(), User); return await _authorizationService.CanUseHotWallet(await _settingsRepository.GetPolicies(), User);
} }
private bool IsInvalidWalletRequest(string cryptoCode, out BTCPayNetwork network, private bool IsInvalidWalletRequest(string cryptoCode, [MaybeNullWhen(true)] out BTCPayNetwork network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult) [MaybeNullWhen(true)] out DerivationSchemeSettings derivationScheme, [MaybeNullWhen(false)] out IActionResult actionResult)
{ {
derivationScheme = null; derivationScheme = null;
actionResult = null;
network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode); network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
if (network is null) if (network is null)
{ {
@@ -535,6 +540,7 @@ namespace BTCPayServer.Controllers.GreenField
return true; return true;
} }
actionResult = null;
return false; return false;
} }

View File

@@ -440,9 +440,9 @@ namespace BTCPayServer.Controllers
{ {
//Keep compatibility with Bitpay //Keep compatibility with Bitpay
invoiceId = invoiceId ?? id; invoiceId = invoiceId ?? id;
id = invoiceId;
// //
if (invoiceId is null)
return NotFound();
var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang);
if (model == null) if (model == null)
return NotFound(); return NotFound();
@@ -472,24 +472,24 @@ namespace BTCPayServer.Controllers
{ {
//Keep compatibility with Bitpay //Keep compatibility with Bitpay
invoiceId = invoiceId ?? id; invoiceId = invoiceId ?? id;
id = invoiceId;
// //
if (invoiceId is null)
var model = await GetInvoiceModel(invoiceId, paymentMethodId == null ? null : PaymentMethodId.Parse(paymentMethodId), lang); return NotFound();
var model = await GetInvoiceModel(invoiceId, paymentMethodId is null ? null : PaymentMethodId.Parse(paymentMethodId), lang);
if (model == null) if (model == null)
return NotFound(); return NotFound();
return View(model); return View(model);
} }
private async Task<PaymentModel?> GetInvoiceModel(string invoiceId, PaymentMethodId paymentMethodId, string? lang) private async Task<PaymentModel?> GetInvoiceModel(string invoiceId, PaymentMethodId? paymentMethodId, string? lang)
{ {
var invoice = await _InvoiceRepository.GetInvoice(invoiceId); var invoice = await _InvoiceRepository.GetInvoice(invoiceId);
if (invoice == null) if (invoice == null)
return null; return null;
var store = await _StoreRepository.FindStore(invoice.StoreId); var store = await _StoreRepository.FindStore(invoice.StoreId);
bool isDefaultPaymentId = false; bool isDefaultPaymentId = false;
if (paymentMethodId == null) if (paymentMethodId is null)
{ {
paymentMethodId = store.GetDefaultPaymentId(_NetworkProvider); paymentMethodId = store.GetDefaultPaymentId(_NetworkProvider);
isDefaultPaymentId = true; isDefaultPaymentId = true;
@@ -846,6 +846,11 @@ namespace BTCPayServer.Controllers
ModelState.AddModelError(nameof(model.StoreId), "You need to configure the derivation scheme in order to create an invoice"); ModelState.AddModelError(nameof(model.StoreId), "You need to configure the derivation scheme in order to create an invoice");
return View(model); return View(model);
} }
if (model.Amount is null)
{
ModelState.AddModelError(nameof(model.Amount), "Thhe invoice amount can't be empty");
return View(model);
}
try try
{ {
@@ -910,7 +915,7 @@ namespace BTCPayServer.Controllers
public class InvoiceStateChangeModel public class InvoiceStateChangeModel
{ {
public bool NotFound { get; set; } public bool NotFound { get; set; }
public string StatusString { get; set; } public string? StatusString { get; set; }
} }
private string GetUserId() private string GetUserId()
@@ -933,7 +938,7 @@ namespace BTCPayServer.Controllers
var jObject = JObject.Parse(posData); var jObject = JObject.Parse(posData);
foreach (var item in jObject) foreach (var item in jObject)
{ {
switch (item.Value.Type) switch (item.Value?.Type)
{ {
case JTokenType.Array: case JTokenType.Array:
var items = item.Value.AsEnumerable().ToList(); var items = item.Value.AsEnumerable().ToList();
@@ -945,6 +950,8 @@ namespace BTCPayServer.Controllers
case JTokenType.Object: case JTokenType.Object:
result.TryAdd(item.Key, ParsePosData(item.Value.ToString())); result.TryAdd(item.Key, ParsePosData(item.Value.ToString()));
break; break;
case null:
break;
default: default:
result.TryAdd(item.Key, item.Value.ToString()); result.TryAdd(item.Key, item.Value.ToString());
break; break;

View File

@@ -335,13 +335,14 @@ namespace BTCPayServer.Controllers
derivationSchemeSettings, network, cancellationToken); derivationSchemeSettings, network, cancellationToken);
try try
{ {
proposedPayjoin.Settings.SigningOptions = new SigningOptions()
{
EnforceLowR = !(vm.SigningContext?.EnforceLowR is false)
};
var extKey = ExtKey.Parse(vm.SigningKey, network.NBitcoinNetwork); var extKey = ExtKey.Parse(vm.SigningKey, network.NBitcoinNetwork);
proposedPayjoin = proposedPayjoin.SignAll(derivationSchemeSettings.AccountDerivation, proposedPayjoin = proposedPayjoin.SignAll(derivationSchemeSettings.AccountDerivation,
extKey, extKey,
RootedKeyPath.Parse(vm.SigningKeyPath), new SigningOptions() RootedKeyPath.Parse(vm.SigningKeyPath));
{
EnforceLowR = !(vm.SigningContext?.EnforceLowR is false)
});
vm.SigningContext.PSBT = proposedPayjoin.ToBase64(); vm.SigningContext.PSBT = proposedPayjoin.ToBase64();
vm.SigningContext.OriginalPSBT = psbt.ToBase64(); vm.SigningContext.OriginalPSBT = psbt.ToBase64();
proposedPayjoin.Finalize(); proposedPayjoin.Finalize();

View File

@@ -925,10 +925,11 @@ namespace BTCPayServer.Controllers
return View(nameof(SignWithSeed), viewModel); return View(nameof(SignWithSeed), viewModel);
} }
var changed = psbt.PSBTChanged( () => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath, new SigningOptions() psbt.Settings.SigningOptions = new SigningOptions()
{ {
EnforceLowR = !(viewModel.SigningContext?.EnforceLowR is false) EnforceLowR = !(viewModel.SigningContext?.EnforceLowR is false)
})); };
var changed = psbt.PSBTChanged( () => psbt.SignAll(settings.AccountDerivation, signingKey, rootedKeyPath));
if (!changed) if (!changed)
{ {
ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Impossible to sign the transaction. Probable causes: Incorrect account key path in wallet settings or PSBT already signed."); ModelState.AddModelError(nameof(viewModel.SeedOrKey), "Impossible to sign the transaction. Probable causes: Incorrect account key path in wallet settings or PSBT already signed.");

View File

@@ -302,7 +302,9 @@ public class BitcoinLikePayoutHandler : IPayoutHandler
.ThenInclude(o => o.StoreData) .ThenInclude(o => o.StoreData)
.Where(p => p.State == PayoutState.AwaitingPayment) .Where(p => p.State == PayoutState.AwaitingPayment)
.Where(p => p.PaymentMethodId == paymentMethodId.ToString()) .Where(p => p.PaymentMethodId == paymentMethodId.ToString())
#pragma warning disable CA1307 // Specify StringComparison
.Where(p => destination.Equals(p.Destination)) .Where(p => destination.Equals(p.Destination))
#pragma warning restore CA1307 // Specify StringComparison
.ToListAsync(); .ToListAsync();
var payoutByDestination = payouts.ToDictionary(p => p.Destination); var payoutByDestination = payouts.ToDictionary(p => p.Destination);

View File

@@ -47,7 +47,7 @@ namespace BTCPayServer
if (str == null) if (str == null)
throw new ArgumentNullException(nameof(str)); throw new ArgumentNullException(nameof(str));
str = str.Trim(); str = str.Trim();
var outputDescriptor = OutputDescriptor.Parse(str); var outputDescriptor = OutputDescriptor.Parse(str, Network);
switch(outputDescriptor) switch(outputDescriptor)
{ {
case OutputDescriptor.PK _: case OutputDescriptor.PK _:

View File

@@ -270,7 +270,7 @@ namespace BTCPayServer.HostedServices
await Task.Delay(wait, CancellationToken); await Task.Delay(wait, CancellationToken);
ctx = await CreateRedeliveryRequest(originalDeliveryId); ctx = await CreateRedeliveryRequest(originalDeliveryId);
// This may have changed // This may have changed
if (!ctx.WebhookBlob.AutomaticRedelivery || if (ctx is null || !ctx.WebhookBlob.AutomaticRedelivery ||
!ShouldDeliver(ctx.WebhookEvent.Type, ctx.WebhookBlob)) !ShouldDeliver(ctx.WebhookEvent.Type, ctx.WebhookBlob))
break; break;
result = await SendAndSaveDelivery(ctx); result = await SendAndSaveDelivery(ctx);

View File

@@ -1,4 +1,3 @@
#nullable enable
using System; using System;
namespace BTCPayServer.Models.StoreViewModels namespace BTCPayServer.Models.StoreViewModels
@@ -11,7 +10,7 @@ namespace BTCPayServer.Models.StoreViewModels
public string Url { get; set; } public string Url { get; set; }
public bool LastDeliverySuccessful { get; set; } = true; public bool LastDeliverySuccessful { get; set; } = true;
public DateTimeOffset? LastDeliveryTimeStamp { get; set; } = null; public DateTimeOffset? LastDeliveryTimeStamp { get; set; } = null;
public string? LastDeliveryErrorMessage { get; set; } = null; public string LastDeliveryErrorMessage { get; set; } = null;
} }
public WebhookViewModel[] Webhooks { get; set; } public WebhookViewModel[] Webhooks { get; set; }
} }

View File

@@ -462,10 +462,11 @@ namespace BTCPayServer.Payments.PayJoin
var coin = selectedUtxo.AsCoin(derivationSchemeSettings.AccountDerivation); var coin = selectedUtxo.AsCoin(derivationSchemeSettings.AccountDerivation);
signedInput.UpdateFromCoin(coin); signedInput.UpdateFromCoin(coin);
var privateKey = accountKey.Derive(selectedUtxo.KeyPath).PrivateKey; var privateKey = accountKey.Derive(selectedUtxo.KeyPath).PrivateKey;
signedInput.Sign(privateKey, new SigningOptions() signedInput.PSBT.Settings.SigningOptions = new SigningOptions()
{ {
EnforceLowR = enforcedLowR EnforceLowR = enforcedLowR
}); };
signedInput.Sign(privateKey);
signedInput.FinalizeInput(); signedInput.FinalizeInput();
newTx.Inputs[signedInput.Index].WitScript = newPsbt.Inputs[(int)signedInput.Index].FinalScriptWitness; newTx.Inputs[signedInput.Index].WitScript = newPsbt.Inputs[(int)signedInput.Index].FinalScriptWitness;
} }

View File

@@ -83,7 +83,7 @@ namespace BTCPayServer.Services
acceptedLocales[locale] = qualityScore; acceptedLocales[locale] = qualityScore;
} }
} }
catch (System.FormatException e) catch (System.FormatException)
{ {
// Can't use this piece, moving on... // Can't use this piece, moving on...
} }