mirror of
https://github.com/aljazceru/btcpayserver.git
synced 2025-12-17 05:54:26 +01:00
Add wallet policy support (#6765)
This commit is contained in:
@@ -31,7 +31,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.5.2" />
|
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.5.2" />
|
||||||
<PackageReference Include="NBitcoin" Version="8.0.13" />
|
<PackageReference Include="NBitcoin" Version="9.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ namespace BTCPayServer.Client.Models
|
|||||||
public string KeyPath { get; set; }
|
public string KeyPath { get; set; }
|
||||||
//The address generated at the key path
|
//The address generated at the key path
|
||||||
public string Address { get; set; }
|
public string Address { get; set; }
|
||||||
|
public int Index { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
|
<Import Project="../Build/Version.csproj" Condition="Exists('../Build/Version.csproj')" />
|
||||||
<Import Project="../Build/Common.csproj" />
|
<Import Project="../Build/Common.csproj" />
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="NBXplorer.Client" Version="4.3.9" />
|
<PackageReference Include="NBXplorer.Client" Version="5.0.5" />
|
||||||
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="2.0.1" />
|
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="2.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.11" />
|
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="8.0.11" />
|
||||||
<PackageReference Include="NBitcoin.Altcoins" Version="4.0.8" />
|
<PackageReference Include="NBitcoin.Altcoins" Version="5.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\BTCPayServer.Abstractions\BTCPayServer.Abstractions.csproj" />
|
<ProjectReference Include="..\BTCPayServer.Abstractions\BTCPayServer.Abstractions.csproj" />
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.10.0" />
|
||||||
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
|
<PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="6.0.0" />
|
||||||
<PackageReference Include="NBitcoin" Version="8.0.13" />
|
<PackageReference Include="NBitcoin" Version="9.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||||
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="1.2.0" />
|
<PackageReference Include="DigitalRuby.ExchangeSharp" Version="1.2.0" />
|
||||||
|
|||||||
@@ -918,7 +918,7 @@ namespace BTCPayServer.Tests
|
|||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
var expectedScripts = script.Derive(AddressIntent.Deposit, i).Miniscript.ToScripts();
|
var expectedScripts = script.Derive(AddressIntent.Deposit, i).Miniscript.ToScripts();
|
||||||
var actual = scheme.AccountDerivation.GetDerivation(new KeyPath(0, (uint)i));
|
var actual = ((StandardDerivationStrategyBase)scheme.AccountDerivation).GetDerivation(new KeyPath(0, (uint)i));
|
||||||
Assert.Equal(expectedScripts.ScriptPubKey, actual.ScriptPubKey);
|
Assert.Equal(expectedScripts.ScriptPubKey, actual.ScriptPubKey);
|
||||||
Assert.Equal(expectedScripts.RedeemScript, actual.Redeem);
|
Assert.Equal(expectedScripts.RedeemScript, actual.Redeem);
|
||||||
if (i == 0)
|
if (i == 0)
|
||||||
@@ -1029,7 +1029,7 @@ namespace BTCPayServer.Tests
|
|||||||
"ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD",
|
"ypub6WWc2gWwHbdnAAyJDnR4SPL1phRh7REqrPBfZeizaQ1EmTshieRXJC3Z5YoU4wkcdKHEjQGkh6AYEzCQC1Kz3DNaWSwdc1pc8416hAjzqyD",
|
||||||
settings.AccountOriginal);
|
settings.AccountOriginal);
|
||||||
Assert.Equal(root.Derive(new KeyPath("m/49'/0'/0'")).Neuter().PubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey,
|
Assert.Equal(root.Derive(new KeyPath("m/49'/0'/0'")).Neuter().PubKey.WitHash.ScriptPubKey.Hash.ScriptPubKey,
|
||||||
settings.AccountDerivation.GetDerivation().ScriptPubKey);
|
((StandardDerivationStrategyBase)settings.AccountDerivation).GetDerivation(new KeyPath()).ScriptPubKey);
|
||||||
Assert.Equal("ElectrumFile", settings.Source);
|
Assert.Equal("ElectrumFile", settings.Source);
|
||||||
Assert.Null(error);
|
Assert.Null(error);
|
||||||
|
|
||||||
@@ -1101,8 +1101,7 @@ bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku
|
|||||||
Assert.True(multsig.LexicographicOrder);
|
Assert.True(multsig.LexicographicOrder);
|
||||||
Assert.Equal(1, multsig.RequiredSignatures);
|
Assert.Equal(1, multsig.RequiredSignatures);
|
||||||
|
|
||||||
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
|
var line = nunchuk.AccountDerivation.GetLineFor(DerivationFeature.Deposit).Derive(0);
|
||||||
var line = nunchuk.AccountDerivation.GetLineFor(deposit).Derive(0);
|
|
||||||
|
|
||||||
Assert.Equal(BitcoinAddress.Create("bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku", Network.Main).ScriptPubKey,
|
Assert.Equal(BitcoinAddress.Create("bc1qfzu57kgu5jthl934f9xrdzzx8mmemx7gn07tf0grnvz504j6kzusu2v0ku", Network.Main).ScriptPubKey,
|
||||||
line.ScriptPubKey);
|
line.ScriptPubKey);
|
||||||
|
|||||||
@@ -176,7 +176,7 @@ public class MultisigTests : UnitTestBase
|
|||||||
var resp1 = new GenerateWalletResponse
|
var resp1 = new GenerateWalletResponse
|
||||||
{
|
{
|
||||||
MasterHDKey = key1,
|
MasterHDKey = key1,
|
||||||
DerivationScheme = parser.Parse(derivation),
|
DerivationScheme = (StandardDerivationStrategyBase)parser.Parse(derivation),
|
||||||
AccountKeyPath = RootedKeyPath.Parse(keypath)
|
AccountKeyPath = RootedKeyPath.Parse(keypath)
|
||||||
};
|
};
|
||||||
return resp1;
|
return resp1;
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ using Microsoft.Extensions.Caching.Memory;
|
|||||||
using PosViewType = BTCPayServer.Client.Models.PosViewType;
|
using PosViewType = BTCPayServer.Client.Models.PosViewType;
|
||||||
using BTCPayServer.PaymentRequest;
|
using BTCPayServer.PaymentRequest;
|
||||||
using BTCPayServer.Views.Stores;
|
using BTCPayServer.Views.Stores;
|
||||||
|
using NBXplorer.DerivationStrategy;
|
||||||
|
|
||||||
namespace BTCPayServer.Tests
|
namespace BTCPayServer.Tests
|
||||||
{
|
{
|
||||||
@@ -730,7 +731,7 @@ namespace BTCPayServer.Tests
|
|||||||
|
|
||||||
// Sending a coin
|
// Sending a coin
|
||||||
var txId = tester.ExplorerNode.SendToAddress(
|
var txId = tester.ExplorerNode.SendToAddress(
|
||||||
btcDerivationScheme.GetDerivation(new KeyPath("0/90")).ScriptPubKey, Money.Coins(1.0m));
|
((StandardDerivationStrategyBase)btcDerivationScheme).GetDerivation(new KeyPath("0/90")).ScriptPubKey, Money.Coins(1.0m));
|
||||||
tester.ExplorerNode.Generate(1);
|
tester.ExplorerNode.Generate(1);
|
||||||
var transactions = Assert.IsType<ListTransactionsViewModel>(Assert
|
var transactions = Assert.IsType<ListTransactionsViewModel>(Assert
|
||||||
.IsType<ViewResult>(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model);
|
.IsType<ViewResult>(walletController.WalletTransactions(walletId, loadTransactions: true).Result).Model);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ services:
|
|||||||
custom:
|
custom:
|
||||||
|
|
||||||
nbxplorer:
|
nbxplorer:
|
||||||
image: nicolasdorier/nbxplorer:2.5.26
|
image: nicolasdorier/nbxplorer:2.5.28
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "32838:32838"
|
- "32838:32838"
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ services:
|
|||||||
custom:
|
custom:
|
||||||
|
|
||||||
nbxplorer:
|
nbxplorer:
|
||||||
image: nicolasdorier/nbxplorer:2.5.26
|
image: nicolasdorier/nbxplorer:2.5.28
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "32838:32838"
|
- "32838:32838"
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ services:
|
|||||||
custom:
|
custom:
|
||||||
|
|
||||||
nbxplorer:
|
nbxplorer:
|
||||||
image: nicolasdorier/nbxplorer:2.5.26
|
image: nicolasdorier/nbxplorer:2.5.28
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "32838:32838"
|
- "32838:32838"
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ services:
|
|||||||
custom:
|
custom:
|
||||||
|
|
||||||
nbxplorer:
|
nbxplorer:
|
||||||
image: nicolasdorier/nbxplorer:2.5.26
|
image: nicolasdorier/nbxplorer:2.5.28
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
ports:
|
ports:
|
||||||
- "32838:32838"
|
- "32838:32838"
|
||||||
|
|||||||
@@ -51,9 +51,9 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="BTCPayServer.NTag424" Version="1.0.25" />
|
<PackageReference Include="BTCPayServer.NTag424" Version="1.0.25" />
|
||||||
<PackageReference Include="NBitcoin" Version="8.0.13" />
|
<PackageReference Include="NBitcoin" Version="9.0.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="8.0.0" />
|
<PackageReference Include="YamlDotNet" Version="8.0.0" />
|
||||||
<PackageReference Include="BIP78.Sender" Version="0.2.4" />
|
<PackageReference Include="BIP78.Sender" Version="0.2.5" />
|
||||||
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.6" />
|
<PackageReference Include="BTCPayServer.Hwi" Version="2.0.6" />
|
||||||
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.6.11" />
|
<PackageReference Include="BTCPayServer.Lightning.All" Version="1.6.11" />
|
||||||
<PackageReference Include="CsvHelper" Version="32.0.3" />
|
<PackageReference Include="CsvHelper" Version="32.0.3" />
|
||||||
|
|||||||
@@ -15,6 +15,8 @@ using BTCPayServer.Services.Wallets;
|
|||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Cors;
|
using Microsoft.AspNetCore.Cors;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using NBitcoin;
|
||||||
|
using NBXplorer;
|
||||||
using NBXplorer.DerivationStrategy;
|
using NBXplorer.DerivationStrategy;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using StoreData = BTCPayServer.Data.StoreData;
|
using StoreData = BTCPayServer.Data.StoreData;
|
||||||
@@ -115,18 +117,26 @@ namespace BTCPayServer.Controllers.Greenfield
|
|||||||
|
|
||||||
internal static OnChainPaymentMethodPreviewResultData GetPreviewResultData(int offset, int count, BTCPayNetwork network, DerivationStrategyBase strategy)
|
internal static OnChainPaymentMethodPreviewResultData GetPreviewResultData(int offset, int count, BTCPayNetwork network, DerivationStrategyBase strategy)
|
||||||
{
|
{
|
||||||
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
|
var line = strategy.GetLineFor(DerivationFeature.Deposit);
|
||||||
var line = strategy.GetLineFor(deposit);
|
|
||||||
var result = new OnChainPaymentMethodPreviewResultData();
|
var result = new OnChainPaymentMethodPreviewResultData();
|
||||||
for (var i = offset; i < count; i++)
|
for (var i = offset; i < count; i++)
|
||||||
{
|
{
|
||||||
|
var keyPath = new KeyPath(0, (uint)i);
|
||||||
|
if (strategy is PolicyDerivationStrategy)
|
||||||
|
keyPath = null;
|
||||||
var derivation = line.Derive((uint)i);
|
var derivation = line.Derive((uint)i);
|
||||||
result.Addresses.Add(
|
result.Addresses.Add(
|
||||||
new()
|
new()
|
||||||
{
|
{
|
||||||
KeyPath = deposit.GetKeyPath((uint)i).ToString(),
|
KeyPath = keyPath?.ToString(),
|
||||||
|
Index = i,
|
||||||
Address =
|
Address =
|
||||||
network.NBXplorerNetwork.CreateAddress(strategy, deposit.GetKeyPath((uint)i), derivation.ScriptPubKey)
|
#pragma warning disable CS0612 // Type or member is obsolete
|
||||||
|
// We should be able to derive the address from the scriptPubKey.
|
||||||
|
// However, Elements has blinded addresses, so we can't derive the address from the scriptPubKey.
|
||||||
|
// We should probably just use a special if/else just for elements here instead of relying on obsolete stuff.
|
||||||
|
network.NBXplorerNetwork.CreateAddress(strategy, keyPath ?? new(), derivation.ScriptPubKey)
|
||||||
|
#pragma warning restore CS0612 // Type or member is obsolete
|
||||||
.ToString()
|
.ToString()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1125,7 +1125,7 @@ namespace BTCPayServer.Controllers
|
|||||||
{
|
{
|
||||||
var appsById = apps.ToDictionary(a => a.Id);
|
var appsById = apps.ToDictionary(a => a.Id);
|
||||||
var searchTexts = appIds.Select(a => appsById.TryGet(a)).Where(a => a != null)
|
var searchTexts = appIds.Select(a => appsById.TryGet(a)).Where(a => a != null)
|
||||||
.Select(a => AppService.GetAppSearchTerm(a.AppType, a.Id))
|
.Select(a => AppService.GetAppSearchTerm(a!.AppType, a!.Id))
|
||||||
.ToList();
|
.ToList();
|
||||||
searchTexts.Add(fs.TextSearch);
|
searchTexts.Add(fs.TextSearch);
|
||||||
textSearch = string.Join(' ', searchTexts.Where(t => !string.IsNullOrEmpty(t)).ToList());
|
textSearch = string.Join(' ', searchTexts.Where(t => !string.IsNullOrEmpty(t)).ToList());
|
||||||
|
|||||||
@@ -184,7 +184,7 @@ public partial class UIStoresController
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(vm.DerivationScheme), StringLocalizer["Invalid derivation scheme"]);
|
ModelState.AddModelError(nameof(vm.DerivationScheme), StringLocalizer["NBXplorer is unable to track this derivation scheme. You may need to update it."]);
|
||||||
return View(vm.ViewName, vm);
|
return View(vm.ViewName, vm);
|
||||||
}
|
}
|
||||||
await _storeRepo.UpdateStore(store);
|
await _storeRepo.UpdateStore(store);
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using System.Text.RegularExpressions;
|
|||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.Scripting;
|
using NBitcoin.Scripting;
|
||||||
using NBitcoin.WalletPolicies;
|
using NBitcoin.WalletPolicies;
|
||||||
|
using NBXplorer;
|
||||||
using NBXplorer.DerivationStrategy;
|
using NBXplorer.DerivationStrategy;
|
||||||
using static NBitcoin.WalletPolicies.MiniscriptNode;
|
using static NBitcoin.WalletPolicies.MiniscriptNode;
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ namespace BTCPayServer
|
|||||||
}).ToArray() ?? new AccountKeySettings[result.Item1.GetExtPubKeys().Count()];
|
}).ToArray() ?? new AccountKeySettings[result.Item1.GetExtPubKeys().Count()];
|
||||||
if (result.Item2?.Length > 1)
|
if (result.Item2?.Length > 1)
|
||||||
derivationSchemeSettings.IsMultiSigOnServer = true;
|
derivationSchemeSettings.IsMultiSigOnServer = true;
|
||||||
var isTaproot = derivationSchemeSettings.AccountDerivation.GetDerivation().ScriptPubKey.IsScriptType(ScriptType.Taproot);
|
var isTaproot = derivationSchemeSettings.AccountDerivation.GetLineFor(DerivationFeature.Deposit).Derive(0).ScriptPubKey.IsScriptType(ScriptType.Taproot);
|
||||||
derivationSchemeSettings.DefaultIncludeNonWitnessUtxo = !isTaproot;
|
derivationSchemeSettings.DefaultIncludeNonWitnessUtxo = !isTaproot;
|
||||||
return derivationSchemeSettings;
|
return derivationSchemeSettings;
|
||||||
}
|
}
|
||||||
@@ -209,10 +210,41 @@ namespace BTCPayServer
|
|||||||
ScriptPubKeyType = ScriptPubKeyType.SegwitP2SH,
|
ScriptPubKeyType = ScriptPubKeyType.SegwitP2SH,
|
||||||
KeepOrder = desc.Name == "multi"
|
KeepOrder = desc.Name == "multi"
|
||||||
}), rpks),
|
}), rpks),
|
||||||
_ => throw new FormatException("Not supporting this script policy (BIP388) yet.")
|
_ => ParsePolicy(factory, str)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private (DerivationStrategyBase, RootedKeyPath[]) ParsePolicy(DerivationStrategyFactory factory, string str)
|
||||||
|
{
|
||||||
|
var policy = factory.Parse(str) as PolicyDerivationStrategy;
|
||||||
|
if (policy is null)
|
||||||
|
throw new FormatException("Invalid miniscript derivation");
|
||||||
|
var v = new RootKeyPathVisitor();
|
||||||
|
policy.Policy.FullDescriptor.Visit(v);
|
||||||
|
return (policy, v.RootedKeyPaths.ToArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
class RootKeyPathVisitor : MiniscriptVisitor
|
||||||
|
{
|
||||||
|
public List<RootedKeyPath> RootedKeyPaths { get; set; } = new();
|
||||||
|
public override void Visit(MiniscriptNode node)
|
||||||
|
{
|
||||||
|
// Match all '[12345678]xpub/**'
|
||||||
|
if (node is MiniscriptNode.MultipathNode
|
||||||
|
{
|
||||||
|
Target: HDKeyNode hd
|
||||||
|
})
|
||||||
|
{
|
||||||
|
RootedKeyPaths.Add(hd.RootedKeyPath);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
base.Visit(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private (DerivationStrategyBase, RootedKeyPath[]) ParseLegacyOutputDescriptor(string str)
|
private (DerivationStrategyBase, RootedKeyPath[]) ParseLegacyOutputDescriptor(string str)
|
||||||
{
|
{
|
||||||
(DerivationStrategyBase, RootedKeyPath[]) ExtractFromPkProvider(PubKeyProvider pubKeyProvider,
|
(DerivationStrategyBase, RootedKeyPath[]) ExtractFromPkProvider(PubKeyProvider pubKeyProvider,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Linq;
|
||||||
using BTCPayServer.Client.JsonConverters;
|
using BTCPayServer.Client.JsonConverters;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
@@ -14,12 +15,18 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BitcoinLikePaymentData(OutPoint outpoint, bool rbf, KeyPath keyPath)
|
public BitcoinLikePaymentData(OutPoint outpoint, bool rbf, KeyPath keyPath, int keyIndex)
|
||||||
{
|
{
|
||||||
|
if (keyPath != null)
|
||||||
|
// This shouldn't be needed on new version of NBXplorer, but old version of NBXplorer
|
||||||
|
// are not returning KeyIndex, and it is thus set to '0'.
|
||||||
|
keyIndex = (int)keyPath.Indexes.Last();
|
||||||
|
|
||||||
Outpoint = outpoint;
|
Outpoint = outpoint;
|
||||||
ConfirmationCount = 0;
|
ConfirmationCount = 0;
|
||||||
RBF = rbf;
|
RBF = rbf;
|
||||||
KeyPath = keyPath;
|
KeyPath = keyPath;
|
||||||
|
KeyIndex = keyIndex;
|
||||||
}
|
}
|
||||||
[JsonConverter(typeof(SaneOutpointJsonConverter))]
|
[JsonConverter(typeof(SaneOutpointJsonConverter))]
|
||||||
public OutPoint Outpoint { get; set; }
|
public OutPoint Outpoint { get; set; }
|
||||||
@@ -28,6 +35,8 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
public bool RBF { get; set; }
|
public bool RBF { get; set; }
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
|
||||||
public KeyPath KeyPath { get; set; }
|
public KeyPath KeyPath { get; set; }
|
||||||
|
|
||||||
|
public int? KeyIndex { get; set; }
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
|
||||||
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Ignore)]
|
||||||
public uint256 AssetId { get; set; }
|
public uint256 AssetId { get; set; }
|
||||||
|
|||||||
@@ -190,6 +190,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
paymentMethod.Destination = reserved.Address.ToString();
|
paymentMethod.Destination = reserved.Address.ToString();
|
||||||
paymentContext.TrackedDestinations.Add(Network.GetTrackedDestination(reserved.Address.ScriptPubKey));
|
paymentContext.TrackedDestinations.Add(Network.GetTrackedDestination(reserved.Address.ScriptPubKey));
|
||||||
onchainMethod.KeyPath = reserved.KeyPath;
|
onchainMethod.KeyPath = reserved.KeyPath;
|
||||||
|
onchainMethod.KeyIndex = reserved.Index ?? (int)reserved.KeyPath.Indexes.Last();
|
||||||
onchainMethod.AccountDerivation = accountDerivation;
|
onchainMethod.AccountDerivation = accountDerivation;
|
||||||
onchainMethod.PayjoinEnabled = blob.PayJoinEnabled &&
|
onchainMethod.PayjoinEnabled = blob.PayJoinEnabled &&
|
||||||
accountDerivation.ScriptPubKeyType() != ScriptPubKeyType.Legacy &&
|
accountDerivation.ScriptPubKeyType() != ScriptPubKeyType.Legacy &&
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
public FeeRate RecommendedFeeRate { get; set; }
|
public FeeRate RecommendedFeeRate { get; set; }
|
||||||
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
|
[JsonConverter(typeof(NBitcoin.JsonConverters.KeyPathJsonConverter))]
|
||||||
public KeyPath KeyPath { get; set; }
|
public KeyPath KeyPath { get; set; }
|
||||||
|
public int KeyIndex { get; set; }
|
||||||
public DerivationStrategyBase AccountDerivation { get; set; }
|
public DerivationStrategyBase AccountDerivation { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,7 +164,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
if (invoice != null)
|
if (invoice != null)
|
||||||
{
|
{
|
||||||
var handler = _handlers[pmi];
|
var handler = _handlers[pmi];
|
||||||
var details = new BitcoinLikePaymentData(output.outPoint, evt.TransactionData.Transaction.RBF, output.matchedOutput.KeyPath)
|
var details = new BitcoinLikePaymentData(output.outPoint, evt.TransactionData.Transaction.RBF, output.matchedOutput.KeyPath, output.matchedOutput.KeyIndex)
|
||||||
{
|
{
|
||||||
AssetId = output.matchedOutput.Value.GetAssetId(network)
|
AssetId = output.matchedOutput.Value.GetAssetId(network)
|
||||||
};
|
};
|
||||||
@@ -414,7 +414,7 @@ namespace BTCPayServer.Payments.Bitcoin
|
|||||||
Status = PaymentStatus.Processing,
|
Status = PaymentStatus.Processing,
|
||||||
Amount = coin.Value.GetValue(network),
|
Amount = coin.Value.GetValue(network),
|
||||||
Currency = network.CryptoCode
|
Currency = network.CryptoCode
|
||||||
}.Set(invoice, handler, new BitcoinLikePaymentData(coin.OutPoint, transaction?.Transaction is null ? true : transaction.Transaction.RBF, coin.KeyPath)
|
}.Set(invoice, handler, new BitcoinLikePaymentData(coin.OutPoint, transaction?.Transaction is null ? true : transaction.Transaction.RBF, coin.KeyPath, coin.KeyIndex)
|
||||||
{
|
{
|
||||||
AssetId = coin.Value.GetAssetId(network)
|
AssetId = coin.Value.GetAssetId(network)
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ namespace BTCPayServer.Payments.PayJoin
|
|||||||
Dictionary<OutPoint, UTXO> selectedUTXOs = new Dictionary<OutPoint, UTXO>();
|
Dictionary<OutPoint, UTXO> selectedUTXOs = new Dictionary<OutPoint, UTXO>();
|
||||||
PSBTOutput? originalPaymentOutput = null;
|
PSBTOutput? originalPaymentOutput = null;
|
||||||
BitcoinAddress? paymentAddress = null;
|
BitcoinAddress? paymentAddress = null;
|
||||||
KeyPath? paymentAddressIndex = null;
|
(KeyPath KeyPath, int KeyIndex)? paymentAddressIndex = null;
|
||||||
InvoiceEntity? invoice = null;
|
InvoiceEntity? invoice = null;
|
||||||
DerivationStrategyBase? accountDerivation = null;
|
DerivationStrategyBase? accountDerivation = null;
|
||||||
WalletId? walletId = null;
|
WalletId? walletId = null;
|
||||||
@@ -312,7 +312,7 @@ namespace BTCPayServer.Payments.PayJoin
|
|||||||
}
|
}
|
||||||
|
|
||||||
paymentAddress = BitcoinAddress.Create(paymentMethod.Destination, network.NBitcoinNetwork);
|
paymentAddress = BitcoinAddress.Create(paymentMethod.Destination, network.NBitcoinNetwork);
|
||||||
paymentAddressIndex = paymentDetails.KeyPath;
|
paymentAddressIndex = (paymentDetails.KeyPath, paymentDetails.KeyIndex);
|
||||||
|
|
||||||
if (invoice.GetAllBitcoinPaymentData(handler, false).Any())
|
if (invoice.GetAllBitcoinPaymentData(handler, false).Any())
|
||||||
{
|
{
|
||||||
@@ -325,7 +325,8 @@ namespace BTCPayServer.Payments.PayJoin
|
|||||||
{
|
{
|
||||||
due = Money.Zero;
|
due = Money.Zero;
|
||||||
paymentAddress = walletReceiveMatch.Item2.Address;
|
paymentAddress = walletReceiveMatch.Item2.Address;
|
||||||
paymentAddressIndex = walletReceiveMatch.Item2.KeyPath;
|
// Old versions of NBX doesn't have the Index property, we can remove ?? (int)walletReceiveMatch.Item2.KeyPath.Indexes.Last() later.
|
||||||
|
paymentAddressIndex = (walletReceiveMatch.Item2.KeyPath, walletReceiveMatch.Item2.Index ?? (int)walletReceiveMatch.Item2.KeyPath.Indexes.Last());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -500,7 +501,7 @@ namespace BTCPayServer.Payments.PayJoin
|
|||||||
// broadcast the payjoin.
|
// broadcast the payjoin.
|
||||||
|
|
||||||
var outpoint = new OutPoint(ctx.OriginalTransaction.GetHash(), originalPaymentOutput.Index);
|
var outpoint = new OutPoint(ctx.OriginalTransaction.GetHash(), originalPaymentOutput.Index);
|
||||||
var details = new BitcoinLikePaymentData(outpoint, ctx.OriginalTransaction.RBF, paymentAddressIndex)
|
var details = new BitcoinLikePaymentData(outpoint, ctx.OriginalTransaction.RBF, paymentAddressIndex.Value.KeyPath, paymentAddressIndex.Value.KeyIndex)
|
||||||
{
|
{
|
||||||
ConfirmationCount = -1,
|
ConfirmationCount = -1,
|
||||||
PayjoinInformation = new PayjoinInformation()
|
PayjoinInformation = new PayjoinInformation()
|
||||||
|
|||||||
@@ -21,11 +21,6 @@ namespace BTCPayServer.Payments.PayJoin.Sender
|
|||||||
return ((IHDScriptPubKey)_derivationSchemeSettings.AccountDerivation).Derive(keyPath);
|
return ((IHDScriptPubKey)_derivationSchemeSettings.AccountDerivation).Derive(keyPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool CanDeriveHardenedPath()
|
|
||||||
{
|
|
||||||
return _derivationSchemeSettings.AccountDerivation.CanDeriveHardenedPath();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Script ScriptPubKey => ((IHDScriptPubKey)_derivationSchemeSettings.AccountDerivation).ScriptPubKey;
|
public Script ScriptPubKey => ((IHDScriptPubKey)_derivationSchemeSettings.AccountDerivation).ScriptPubKey;
|
||||||
public ScriptPubKeyType ScriptPubKeyType => _derivationSchemeSettings.AccountDerivation.ScriptPubKeyType();
|
public ScriptPubKeyType ScriptPubKeyType => _derivationSchemeSettings.AccountDerivation.ScriptPubKeyType();
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ using System.Diagnostics.CodeAnalysis;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using BTCPayServer;
|
using BTCPayServer;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
|
using NBXplorer;
|
||||||
using NBXplorer.DerivationStrategy;
|
using NBXplorer.DerivationStrategy;
|
||||||
using AccountKeySettings = BTCPayServer.AccountKeySettings;
|
using AccountKeySettings = BTCPayServer.AccountKeySettings;
|
||||||
using BTCPayNetwork = BTCPayServer.BTCPayNetwork;
|
using BTCPayNetwork = BTCPayServer.BTCPayNetwork;
|
||||||
@@ -37,8 +38,7 @@ public class BSMSWalletFileParser : IWalletFileParser
|
|||||||
|
|
||||||
derivationSchemeSettings = network.GetDerivationSchemeParser().ParseOD(descriptor);
|
derivationSchemeSettings = network.GetDerivationSchemeParser().ParseOD(descriptor);
|
||||||
derivationSchemeSettings.Source = "BSMS";
|
derivationSchemeSettings.Source = "BSMS";
|
||||||
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
|
var line = derivationSchemeSettings.AccountDerivation.GetLineFor(DerivationFeature.Deposit).Derive(0);
|
||||||
var line = derivationSchemeSettings.AccountDerivation.GetLineFor(deposit).Derive(0);
|
|
||||||
return testAddress.ScriptPubKey == line.ScriptPubKey;
|
return testAddress.ScriptPubKey == line.ScriptPubKey;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
public Coin Coin { get; set; }
|
public Coin Coin { get; set; }
|
||||||
public long Confirmations { get; set; }
|
public long Confirmations { get; set; }
|
||||||
public BitcoinAddress Address { get; set; }
|
public BitcoinAddress Address { get; set; }
|
||||||
|
public int KeyIndex { get; set; }
|
||||||
}
|
}
|
||||||
public class NetworkCoins
|
public class NetworkCoins
|
||||||
{
|
{
|
||||||
@@ -500,6 +501,7 @@ namespace BTCPayServer.Services.Wallets
|
|||||||
.Select(c => new ReceivedCoin()
|
.Select(c => new ReceivedCoin()
|
||||||
{
|
{
|
||||||
KeyPath = c.KeyPath,
|
KeyPath = c.KeyPath,
|
||||||
|
KeyIndex = c.KeyIndex,
|
||||||
Value = c.Value,
|
Value = c.Value,
|
||||||
Timestamp = c.Timestamp,
|
Timestamp = c.Timestamp,
|
||||||
OutPoint = c.Outpoint,
|
OutPoint = c.Outpoint,
|
||||||
|
|||||||
@@ -81,7 +81,7 @@
|
|||||||
{
|
{
|
||||||
<tr style="@(payment.Replaced ? "text-decoration: line-through" : "")">
|
<tr style="@(payment.Replaced ? "text-decoration: line-through" : "")">
|
||||||
<td>@payment.PaymentMethodId</td>
|
<td>@payment.PaymentMethodId</td>
|
||||||
<td>@(payment.CryptoPaymentData.KeyPath?.ToString()?? StringLocalizer["Unknown"])</td>
|
<td>@(payment.CryptoPaymentData.KeyPath?.ToString() ?? payment.CryptoPaymentData.KeyIndex?.ToString() ?? StringLocalizer["Unknown"])</td>
|
||||||
<td>
|
<td>
|
||||||
<vc:truncate-center text="@payment.DepositAddress.ToString()" classes="truncate-center-id" />
|
<vc:truncate-center text="@payment.DepositAddress.ToString()" classes="truncate-center-id" />
|
||||||
</td>
|
</td>
|
||||||
|
|||||||
Reference in New Issue
Block a user