Always rebase keys before signing, refacotring some code

This commit is contained in:
nicolas.dorier
2019-05-12 11:07:41 +09:00
parent b214e3f6df
commit ff82f15246
2 changed files with 42 additions and 25 deletions

View File

@@ -117,8 +117,7 @@ namespace BTCPayServer.Controllers
[ModelBinder(typeof(WalletIdModelBinder))] [ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId) WalletId walletId)
{ {
var store = await Repository.FindStore(walletId.StoreId, GetUserId()); DerivationSchemeSettings paymentMethod = await GetDerivationSchemeSettings(walletId);
DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store);
if (paymentMethod == null) if (paymentMethod == null)
return NotFound(); return NotFound();
@@ -151,7 +150,7 @@ namespace BTCPayServer.Controllers
if (walletId?.StoreId == null) if (walletId?.StoreId == null)
return NotFound(); return NotFound();
var store = await Repository.FindStore(walletId.StoreId, GetUserId()); var store = await Repository.FindStore(walletId.StoreId, GetUserId());
DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store); DerivationSchemeSettings paymentMethod = GetDerivationSchemeSettings(walletId, store);
if (paymentMethod == null) if (paymentMethod == null)
return NotFound(); return NotFound();
var network = this.NetworkProvider.GetNetwork(walletId?.CryptoCode); var network = this.NetworkProvider.GetNetwork(walletId?.CryptoCode);
@@ -227,8 +226,7 @@ namespace BTCPayServer.Controllers
if (!ModelState.IsValid) if (!ModelState.IsValid)
return View(vm); return View(vm);
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId())); DerivationSchemeSettings derivationScheme = await GetDerivationSchemeSettings(walletId);
var derivationScheme = GetPaymentMethod(walletId, storeData);
var psbt = await CreatePSBT(network, derivationScheme, vm, cancellation); var psbt = await CreatePSBT(network, derivationScheme, vm, cancellation);
if (command == "ledger") if (command == "ledger")
@@ -241,6 +239,7 @@ namespace BTCPayServer.Controllers
{ {
if (command == "analyze-psbt") if (command == "analyze-psbt")
return ViewPSBT(psbt.PSBT); return ViewPSBT(psbt.PSBT);
derivationScheme.RebaseKeyPaths(psbt.PSBT);
return FilePSBT(psbt.PSBT, $"Send-{vm.Amount.Value}-{network.CryptoCode}-to-{destination[0].ToString()}.psbt"); return FilePSBT(psbt.PSBT, $"Send-{vm.Amount.Value}-{network.CryptoCode}-to-{destination[0].ToString()}.psbt");
} }
catch (NBXplorerException ex) catch (NBXplorerException ex)
@@ -306,18 +305,7 @@ namespace BTCPayServer.Controllers
psbtRequest.ExplicitChangeAddress = psbtDestination.Destination; psbtRequest.ExplicitChangeAddress = psbtDestination.Destination;
} }
psbtDestination.SubstractFees = sendModel.SubstractFees; psbtDestination.SubstractFees = sendModel.SubstractFees;
if (derivationSettings.AccountKeyPath != null && derivationSettings.AccountKeyPath.Indexes.Length != 0) psbtRequest.RebaseKeyPaths = derivationSettings.GetPSBTRebaseKeyRules().ToList();
{
psbtRequest.RebaseKeyPaths = new List<PSBTRebaseKeyRules>()
{
new PSBTRebaseKeyRules()
{
AccountKeyPath = derivationSettings.AccountKeyPath,
AccountKey = derivationSettings.AccountKey,
MasterFingerprint = derivationSettings.RootFingerprint is HDFingerprint fp ? fp : default
}
};
}
var psbt = (await nbx.CreatePSBTAsync(derivationSettings.AccountDerivation, 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");
@@ -400,6 +388,7 @@ namespace BTCPayServer.Controllers
} }
else else
{ {
(await GetDerivationSchemeSettings(walletId)).RebaseKeyPaths(psbt);
return FilePSBT(psbt, "psbt-export.psbt"); return FilePSBT(psbt, "psbt-export.psbt");
} }
} }
@@ -410,8 +399,7 @@ namespace BTCPayServer.Controllers
if (transaction != null) if (transaction != null)
{ {
var wallet = _walletProvider.GetWallet(network); var wallet = _walletProvider.GetWallet(network);
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId())); var derivationSettings = await GetDerivationSchemeSettings(walletId);
var derivationSettings = GetPaymentMethod(walletId, storeData);
wallet.InvalidateCache(derivationSettings.AccountDerivation); wallet.InvalidateCache(derivationSettings.AccountDerivation);
StatusMessage = $"Transaction broadcasted successfully ({transaction.GetHash().ToString()})"; StatusMessage = $"Transaction broadcasted successfully ({transaction.GetHash().ToString()})";
} }
@@ -492,8 +480,7 @@ namespace BTCPayServer.Controllers
{ {
if (walletId?.StoreId == null) if (walletId?.StoreId == null)
return NotFound(); return NotFound();
var store = await Repository.FindStore(walletId.StoreId, GetUserId()); DerivationSchemeSettings paymentMethod = await GetDerivationSchemeSettings(walletId);
DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store);
if (paymentMethod == null) if (paymentMethod == null)
return NotFound(); return NotFound();
@@ -536,8 +523,7 @@ namespace BTCPayServer.Controllers
{ {
if (walletId?.StoreId == null) if (walletId?.StoreId == null)
return NotFound(); return NotFound();
var store = await Repository.FindStore(walletId.StoreId, GetUserId()); DerivationSchemeSettings paymentMethod = await GetDerivationSchemeSettings(walletId);
DerivationSchemeSettings paymentMethod = GetPaymentMethod(walletId, store);
if (paymentMethod == null) if (paymentMethod == null)
return NotFound(); return NotFound();
var explorer = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode); var explorer = ExplorerClientProvider.GetExplorerClient(walletId.CryptoCode);
@@ -565,7 +551,7 @@ namespace BTCPayServer.Controllers
return null; return null;
} }
private DerivationSchemeSettings GetPaymentMethod(WalletId walletId, StoreData store) private DerivationSchemeSettings GetDerivationSchemeSettings(WalletId walletId, StoreData store)
{ {
if (store == null || !store.HasClaim(Policies.CanModifyStoreSettings.Key)) if (store == null || !store.HasClaim(Policies.CanModifyStoreSettings.Key))
return null; return null;
@@ -577,6 +563,12 @@ namespace BTCPayServer.Controllers
return paymentMethod; return paymentMethod;
} }
private async Task<DerivationSchemeSettings> GetDerivationSchemeSettings(WalletId walletId)
{
var store = (await Repository.FindStore(walletId.StoreId, GetUserId()));
return GetDerivationSchemeSettings(walletId, store);
}
private static async Task<string> GetBalanceString(BTCPayWallet wallet, DerivationStrategyBase derivationStrategy) private static async Task<string> GetBalanceString(BTCPayWallet wallet, DerivationStrategyBase derivationStrategy)
{ {
using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10))) using (CancellationTokenSource cts = new CancellationTokenSource(TimeSpan.FromSeconds(10)))
@@ -618,7 +610,7 @@ namespace BTCPayServer.Controllers
if (network == null) if (network == null)
throw new FormatException("Invalid value for crypto code"); throw new FormatException("Invalid value for crypto code");
var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId())); var storeData = (await Repository.FindStore(walletId.StoreId, GetUserId()));
var derivationSettings = GetPaymentMethod(walletId, storeData); var derivationSettings = GetDerivationSchemeSettings(walletId, storeData);
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync(); var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
@@ -685,6 +677,10 @@ namespace BTCPayServer.Controllers
PSBT = PSBT.Parse(psbt, network.NBitcoinNetwork), PSBT = PSBT.Parse(psbt, network.NBitcoinNetwork),
ChangeAddress = string.IsNullOrEmpty(hintChange) ? null : BitcoinAddress.Create(hintChange, network.NBitcoinNetwork) ChangeAddress = string.IsNullOrEmpty(hintChange) ? null : BitcoinAddress.Create(hintChange, network.NBitcoinNetwork)
}; };
derivationSettings.RebaseKeyPaths(psbtResponse.PSBT);
signTimeout.CancelAfter(TimeSpan.FromMinutes(5)); signTimeout.CancelAfter(TimeSpan.FromMinutes(5));
psbtResponse.PSBT = await hw.SignTransactionAsync(psbtResponse.PSBT, psbtResponse.ChangeAddress?.ScriptPubKey, signTimeout.Token); psbtResponse.PSBT = await hw.SignTransactionAsync(psbtResponse.PSBT, psbtResponse.ChangeAddress?.ScriptPubKey, signTimeout.Token);
result = new SendToAddressResult() { PSBT = psbtResponse.PSBT.ToBase64() }; result = new SendToAddressResult() { PSBT = psbtResponse.PSBT.ToBase64() };

View File

@@ -143,6 +143,19 @@ namespace BTCPayServer
} }
} }
public IEnumerable<NBXplorer.Models.PSBTRebaseKeyRules> GetPSBTRebaseKeyRules()
{
if (AccountKey != null && AccountKeyPath != null && RootFingerprint is HDFingerprint fp)
{
yield return new NBXplorer.Models.PSBTRebaseKeyRules()
{
AccountKey = AccountKey,
AccountKeyPath = AccountKeyPath,
MasterFingerprint = fp
};
}
}
public string Label { get; set; } public string Label { get; set; }
[JsonIgnore] [JsonIgnore]
@@ -163,5 +176,13 @@ namespace BTCPayServer
{ {
return Network.NBXplorerNetwork.Serializer.ToString(this); return Network.NBXplorerNetwork.Serializer.ToString(this);
} }
public void RebaseKeyPaths(PSBT psbt)
{
foreach (var rebase in GetPSBTRebaseKeyRules())
{
psbt.RebaseKeyPaths(rebase.AccountKey, rebase.AccountKeyPath, rebase.MasterFingerprint);
}
}
} }
} }