mirror of
https://github.com/btcpayserver/btcpayserver.git
synced 2024-11-20 10:40:29 +01:00
CreatePSBT should always rebase the PSBT
This commit is contained in:
parent
68c1670c70
commit
aa23222339
@ -243,13 +243,13 @@ namespace BTCPayServer.Controllers
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId()));
|
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId()));
|
||||||
var derivationScheme = GetPaymentMethod(walletId, storeData).AccountDerivation;
|
var derivationScheme = GetPaymentMethod(walletId, storeData);
|
||||||
var psbt = await CreatePSBT(network, derivationScheme, sendModel, cancellation);
|
var psbt = await CreatePSBT(network, derivationScheme, sendModel, cancellation);
|
||||||
return File(psbt.PSBT.ToBytes(), "application/octet-stream", $"Send-{vm.Amount.Value}-{network.CryptoCode}-to-{destination[0].ToString()}.psbt");
|
return File(psbt.PSBT.ToBytes(), "application/octet-stream", $"Send-{vm.Amount.Value}-{network.CryptoCode}-to-{destination[0].ToString()}.psbt");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task<CreatePSBTResponse> CreatePSBT(BTCPayNetwork network, DerivationStrategyBase derivationScheme, WalletSendLedgerModel sendModel, CancellationToken cancellationToken)
|
private async Task<CreatePSBTResponse> CreatePSBT(BTCPayNetwork network, DerivationSchemeSettings derivationSettings, WalletSendLedgerModel sendModel, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var nbx = ExplorerClientProvider.GetExplorerClient(network);
|
var nbx = ExplorerClientProvider.GetExplorerClient(network);
|
||||||
CreatePSBTRequest psbtRequest = new CreatePSBTRequest();
|
CreatePSBTRequest psbtRequest = new CreatePSBTRequest();
|
||||||
@ -269,7 +269,7 @@ namespace BTCPayServer.Controllers
|
|||||||
}
|
}
|
||||||
psbtDestination.SubstractFees = sendModel.SubstractFees;
|
psbtDestination.SubstractFees = sendModel.SubstractFees;
|
||||||
|
|
||||||
var psbt = (await nbx.CreatePSBTAsync(derivationScheme, psbtRequest, cancellationToken));
|
var psbt = (await nbx.CreatePSBTAsync(derivationSettings.AccountDerivation, psbtRequest, cancellationToken));
|
||||||
if (psbt == null)
|
if (psbt == null)
|
||||||
throw new NotSupportedException("You need to update your version of NBXplorer");
|
throw new NotSupportedException("You need to update your version of NBXplorer");
|
||||||
|
|
||||||
@ -279,10 +279,28 @@ namespace BTCPayServer.Controllers
|
|||||||
if (fee < network.MinFee)
|
if (fee < network.MinFee)
|
||||||
{
|
{
|
||||||
psbtRequest.FeePreference = new FeePreference() { ExplicitFee = network.MinFee };
|
psbtRequest.FeePreference = new FeePreference() { ExplicitFee = network.MinFee };
|
||||||
psbt = (await nbx.CreatePSBTAsync(derivationScheme, psbtRequest, cancellationToken));
|
psbt = (await nbx.CreatePSBTAsync(derivationSettings.AccountDerivation, psbtRequest, cancellationToken));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (derivationSettings.AccountKeyPath != null && derivationSettings.AccountKeyPath.Indexes.Length != 0)
|
||||||
|
{
|
||||||
|
// NBX only know the path relative to the account xpub.
|
||||||
|
// Here we rebase the hd_keys in the PSBT to have a keypath relative to the root HD so the wallet can sign
|
||||||
|
// Note that the fingerprint of the hd keys are now 0, which is wrong
|
||||||
|
// However, hardware wallets does not give a damn, and sometimes does not even allow us to get this fingerprint anyway.
|
||||||
|
foreach (var o in psbt.PSBT.Inputs.OfType<PSBTCoin>().Concat(psbt.PSBT.Outputs))
|
||||||
|
{
|
||||||
|
var rootFP = derivationSettings.RootFingerprint is HDFingerprint fp ? fp : default;
|
||||||
|
foreach (var keypath in o.HDKeyPaths.ToList())
|
||||||
|
{
|
||||||
|
var newKeyPath = derivationSettings.AccountKeyPath.Derive(keypath.Value.Item2);
|
||||||
|
o.HDKeyPaths.Remove(keypath.Key);
|
||||||
|
o.HDKeyPaths.Add(keypath.Key, Tuple.Create(rootFP, newKeyPath));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return psbt;
|
return psbt;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -461,7 +479,6 @@ namespace BTCPayServer.Controllers
|
|||||||
var cryptoCode = walletId.CryptoCode;
|
var cryptoCode = walletId.CryptoCode;
|
||||||
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId()));
|
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId()));
|
||||||
var derivationSettings = GetPaymentMethod(walletId, storeData);
|
var derivationSettings = GetPaymentMethod(walletId, storeData);
|
||||||
var derivationScheme = GetPaymentMethod(walletId, storeData).AccountDerivation;
|
|
||||||
|
|
||||||
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
|
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
|
||||||
|
|
||||||
@ -527,9 +544,9 @@ namespace BTCPayServer.Controllers
|
|||||||
if (!_dashboard.IsFullySynched(network.CryptoCode, out var summary))
|
if (!_dashboard.IsFullySynched(network.CryptoCode, out var summary))
|
||||||
throw new Exception($"{network.CryptoCode}: not started or fully synched");
|
throw new Exception($"{network.CryptoCode}: not started or fully synched");
|
||||||
|
|
||||||
var psbt = await CreatePSBT(network, derivationScheme, model, normalOperationTimeout.Token);
|
|
||||||
|
|
||||||
var strategy = GetDirectDerivationStrategy(derivationScheme);
|
|
||||||
|
var strategy = GetDirectDerivationStrategy(derivationSettings.AccountDerivation);
|
||||||
// Some deployment have the wallet root key path saved in the store blob
|
// Some deployment have the wallet root key path saved in the store blob
|
||||||
// If it does, we only have to make 1 call to the hw to check if it can sign the given strategy,
|
// If it does, we only have to make 1 call to the hw to check if it can sign the given strategy,
|
||||||
if (derivationSettings.AccountKeyPath == null || !await hw.CanSign(network, strategy, derivationSettings.AccountKeyPath, normalOperationTimeout.Token))
|
if (derivationSettings.AccountKeyPath == null || !await hw.CanSign(network, strategy, derivationSettings.AccountKeyPath, normalOperationTimeout.Token))
|
||||||
@ -543,20 +560,8 @@ namespace BTCPayServer.Controllers
|
|||||||
await Repository.UpdateStore(storeData);
|
await Repository.UpdateStore(storeData);
|
||||||
}
|
}
|
||||||
|
|
||||||
// NBX only know the path relative to the account xpub.
|
|
||||||
// Here we rebase the hd_keys in the PSBT to have a keypath relative to the root HD so the wallet can sign
|
|
||||||
// Note that the fingerprint of the hd keys are now 0, which is wrong
|
|
||||||
// However, hardware wallets does not give a damn, and sometimes does not even allow us to get this fingerprint anyway.
|
|
||||||
foreach (var o in psbt.PSBT.Inputs.OfType<PSBTCoin>().Concat(psbt.PSBT.Outputs))
|
|
||||||
{
|
|
||||||
foreach (var keypath in o.HDKeyPaths.ToList())
|
|
||||||
{
|
|
||||||
var newKeyPath = derivationSettings.AccountKeyPath.Derive(keypath.Value.Item2);
|
|
||||||
o.HDKeyPaths.Remove(keypath.Key);
|
|
||||||
o.HDKeyPaths.Add(keypath.Key, Tuple.Create(default(HDFingerprint), newKeyPath));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
var psbt = await CreatePSBT(network, derivationSettings, model, normalOperationTimeout.Token);
|
||||||
signTimeout.CancelAfter(TimeSpan.FromMinutes(5));
|
signTimeout.CancelAfter(TimeSpan.FromMinutes(5));
|
||||||
psbt.PSBT = await hw.SignTransactionAsync(psbt.PSBT, psbt.ChangeAddress?.ScriptPubKey, signTimeout.Token);
|
psbt.PSBT = await hw.SignTransactionAsync(psbt.PSBT, psbt.ChangeAddress?.ScriptPubKey, signTimeout.Token);
|
||||||
if(!psbt.PSBT.TryFinalize(out var errors))
|
if(!psbt.PSBT.TryFinalize(out var errors))
|
||||||
@ -577,7 +582,7 @@ namespace BTCPayServer.Controllers
|
|||||||
throw new Exception("Error while broadcasting: " + ex.Message);
|
throw new Exception("Error while broadcasting: " + ex.Message);
|
||||||
}
|
}
|
||||||
var wallet = _walletProvider.GetWallet(network);
|
var wallet = _walletProvider.GetWallet(network);
|
||||||
wallet.InvalidateCache(derivationScheme);
|
wallet.InvalidateCache(derivationSettings.AccountDerivation);
|
||||||
result = new SendToAddressResult() { TransactionId = transaction.GetHash().ToString() };
|
result = new SendToAddressResult() { TransactionId = transaction.GetHash().ToString() };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user