Remove LedgerWallet direct integration

This commit is contained in:
nicolas.dorier
2020-05-25 07:41:30 +09:00
parent 6e0c090622
commit 7e5d269c39
17 changed files with 7 additions and 814 deletions

View File

@@ -803,49 +803,6 @@ namespace BTCPayServer.Controllers
return View("PostRedirect", redirectVm);
}
void SetAmbientPSBT(string psbt)
{
if (psbt != null)
TempData["AmbientPSBT"] = psbt;
else
TempData.Remove("AmbientPSBT");
}
PSBT GetAmbientPSBT(Network network, bool peek)
{
if (network == null)
throw new ArgumentNullException(nameof(network));
if ((peek ? TempData.Peek("AmbientPSBT") : TempData["AmbientPSBT"]) is string str)
{
try
{
return PSBT.Parse(str, network);
}
catch { }
}
return null;
}
private ViewResult ViewWalletSendLedger(WalletId walletId, SigningContextModel signingContext)
{
SetAmbientPSBT(signingContext.PSBT);
return View("WalletSendLedger", new WalletSendLedgerModel()
{
SigningContext = signingContext,
WebsocketPath = this.Url.Action(nameof(LedgerConnection), new { walletId = walletId.ToString() })
});
}
[HttpPost]
[Route("{walletId}/ledger")]
public IActionResult SubmitLedger([ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, WalletSendLedgerModel model)
{
return RedirectToWalletPSBTReady(new WalletPSBTReadyViewModel()
{
SigningContext = model.SigningContext
});
}
[HttpGet("{walletId}/psbt/seed")]
public IActionResult SignWithSeed([ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId, SigningContextModel signingContext)
@@ -1074,119 +1031,6 @@ namespace BTCPayServer.Controllers
return _userManager.GetUserId(User);
}
[HttpGet]
[Route("{walletId}/send/ledger/ws")]
public async Task<IActionResult> LedgerConnection(
[ModelBinder(typeof(WalletIdModelBinder))]
WalletId walletId,
string command,
// getinfo
// getxpub
int account = 0,
// sendtoaddress
string hintChange = null
)
{
if (!HttpContext.WebSockets.IsWebSocketRequest)
return NotFound();
var storeData = CurrentStore;
var network = NetworkProvider.GetNetwork<BTCPayNetwork>(walletId.CryptoCode);
if (network == null)
throw new FormatException("Invalid value for crypto code");
PSBT psbt = GetAmbientPSBT(network.NBitcoinNetwork, true);
var derivationSettings = GetDerivationSchemeSettings(walletId);
var webSocket = await HttpContext.WebSockets.AcceptWebSocketAsync();
using (var normalOperationTimeout = new CancellationTokenSource())
using (var signTimeout = new CancellationTokenSource())
{
normalOperationTimeout.CancelAfter(TimeSpan.FromMinutes(30));
var hw = new LedgerHardwareWalletService(webSocket);
object result = null;
try
{
if (command == "test")
{
result = await hw.Test(normalOperationTimeout.Token);
}
if (command == "sendtoaddress")
{
if (!_dashboard.IsFullySynched(network.CryptoCode, out var summary))
throw new Exception($"{network.CryptoCode}: not started or fully synched");
var accountKey = derivationSettings.GetSigningAccountKeySettings();
// Some deployment does not have the AccountKeyPath set, let's fix this...
if (accountKey.AccountKeyPath == null)
{
// If the saved wallet key path is not present or incorrect, let's scan the wallet to see if it can sign strategy
var foundKeyPath = await hw.FindKeyPathFromDerivation(network,
derivationSettings.AccountDerivation,
normalOperationTimeout.Token);
accountKey.AccountKeyPath = foundKeyPath ?? throw new HardwareWalletException($"This store is not configured to use this ledger");
storeData.SetSupportedPaymentMethod(derivationSettings);
await Repository.UpdateStore(storeData);
}
// If it has already the AccountKeyPath, we did not looked up for it, so we need to check if we are on the right ledger
else
{
// Checking if ledger is right with the RootFingerprint is faster as it does not need to make a query to the parent xpub,
// but some deployment does not have it, so let's use AccountKeyPath instead
if (accountKey.RootFingerprint == null)
{
var actualPubKey = await hw.GetExtPubKey(network, accountKey.AccountKeyPath, normalOperationTimeout.Token);
if (!derivationSettings.AccountDerivation.GetExtPubKeys().Any(p => p.GetPublicKey() == actualPubKey.GetPublicKey()))
throw new HardwareWalletException($"This store is not configured to use this ledger");
}
// We have the root fingerprint, we can check the root from it
else
{
var actualPubKey = await hw.GetPubKey(network, new KeyPath(), normalOperationTimeout.Token);
if (actualPubKey.GetHDFingerPrint() != accountKey.RootFingerprint.Value)
throw new HardwareWalletException($"This store is not configured to use this ledger");
}
}
// Some deployment does not have the RootFingerprint set, let's fix this...
if (accountKey.RootFingerprint == null)
{
accountKey.RootFingerprint = (await hw.GetPubKey(network, new KeyPath(), normalOperationTimeout.Token)).GetHDFingerPrint();
storeData.SetSupportedPaymentMethod(derivationSettings);
await Repository.UpdateStore(storeData);
}
derivationSettings.RebaseKeyPaths(psbt);
var changeAddress = string.IsNullOrEmpty(hintChange) ? null : BitcoinAddress.Create(hintChange, network.NBitcoinNetwork);
signTimeout.CancelAfter(TimeSpan.FromMinutes(5));
psbt = await hw.SignTransactionAsync(psbt, accountKey.GetRootedKeyPath(), accountKey.AccountKey, changeAddress?.ScriptPubKey, signTimeout.Token);
SetAmbientPSBT(null);
result = new SendToAddressResult() { PSBT = psbt.ToBase64() };
}
}
catch (OperationCanceledException)
{ result = new LedgerTestResult() { Success = false, Error = "Timeout" }; }
catch (Exception ex)
{ result = new LedgerTestResult() { Success = false, Error = ex.Message }; }
finally { hw.Dispose(); }
try
{
if (result != null)
{
UTF8Encoding UTF8NOBOM = new UTF8Encoding(false);
var bytes = UTF8NOBOM.GetBytes(JsonConvert.SerializeObject(result, _serializerSettings));
await webSocket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, new CancellationTokenSource(2000).Token);
}
}
catch { }
finally
{
await webSocket.CloseSocket();
}
}
return new EmptyResult();
}
[Route("{walletId}/settings")]
public async Task<IActionResult> WalletSettings(
[ModelBinder(typeof(WalletIdModelBinder))]