From 22ad1cc5d1d6da434853e9959a5443e2335a42d8 Mon Sep 17 00:00:00 2001 From: Toporin Date: Tue, 14 Jan 2025 13:00:52 +0100 Subject: [PATCH 1/2] Patch https://github.com/Toporin/SatochipApplet/issues/15 Null exception can be thrown when signing a multisig transaction from a Sparrow wallet reconstructed from a Bitcoin descriptor. This happens when the user did not configure any keystore with the corresponding Satochip card ('import' button). In this case, the 'fullpath' derivation path remains undefined, leading to the exception. --- .../sparrow/io/satochip/SatoCardApi.java | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java b/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java index 132de40d..09e03da9 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java @@ -164,19 +164,12 @@ public class SatoCardApi extends CardApi { for(PSBTInput psbtInput : psbt.getPsbtInputs()) { if(!psbtInput.isSigned()) { WalletNode signingNode = signingNodes.get(psbtInput); - String fullPath = null; List keystores = wallet.getKeystores(); - for(int i = 0; i < keystores.size(); i++) { - Keystore keystore = keystores.get(i); - WalletModel walletModel = keystore.getWalletModel(); - if(walletModel == WalletModel.SATOCHIP) { - String basePath = keystore.getKeyDerivation().getDerivationPath(); - String extendedPath = signingNode.getDerivationPath().substring(1); - fullPath = basePath + extendedPath; - keystore.getPubKey(signingNode); - break; - } - } + // recover full derivation path + Keystore keystore = keystores.get(0); + String basePath = keystore.getKeyDerivation().getDerivationPath(); + String extendedPath = signingNode.getDerivationPath().substring(1); + String fullPath = basePath + extendedPath; psbtInput.sign(new CardPSBTInputSigner(signingNode, fullPath)); } From 91ad82a21cdca6a8720efa8b08e78138d8be256a Mon Sep 17 00:00:00 2001 From: Toporin Date: Tue, 14 Jan 2025 15:23:38 +0100 Subject: [PATCH 2/2] Patch https://github.com/Toporin/SatochipApplet/issues/15 First try to recover derivation path from satochip keystore, otherwise from first keystore as default value. --- .../sparrow/io/satochip/SatoCardApi.java | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java b/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java index 09e03da9..c37a5bb1 100644 --- a/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java +++ b/src/main/java/com/sparrowwallet/sparrow/io/satochip/SatoCardApi.java @@ -165,12 +165,25 @@ public class SatoCardApi extends CardApi { if(!psbtInput.isSigned()) { WalletNode signingNode = signingNodes.get(psbtInput); List keystores = wallet.getKeystores(); - // recover full derivation path - Keystore keystore = keystores.get(0); - String basePath = keystore.getKeyDerivation().getDerivationPath(); - String extendedPath = signingNode.getDerivationPath().substring(1); - String fullPath = basePath + extendedPath; - + // recover derivation path from Satochip keystore + String fullPath = null; + for(int i = 0; i < keystores.size(); i++) { + Keystore keystore = keystores.get(i); + WalletModel walletModel = keystore.getWalletModel(); + if(walletModel == WalletModel.SATOCHIP) { + String basePath = keystore.getKeyDerivation().getDerivationPath(); + String extendedPath = signingNode.getDerivationPath().substring(1); + fullPath = basePath + extendedPath; + break; + } + } + if (fullPath == null) { + // recover a default derivation path from first keystore + Keystore keystore = keystores.get(0); + String basePath = keystore.getKeyDerivation().getDerivationPath(); + String extendedPath = signingNode.getDerivationPath().substring(1); + fullPath = basePath + extendedPath; + } psbtInput.sign(new CardPSBTInputSigner(signingNode, fullPath)); } }