What changed, and why it matters
This commit refactors how the Keystone hardware wallet exports Bitcoin account data (extended public keys) when pairing with BlueWallet and other apps. Previously BlueWallet received only three key types (Native SegWit, SegWit, Legacy). Now it uses the same function as Sparrow/Zeus/UniSat, which also includes the Taproot key type. This is a feature addition, not a vulnerability fix, and does not change how secrets are handled.
No security action required. Treat as a normal feature/refactor review. If desired, verify that BlueWallet correctly handles the additional Taproot key in the exported UR and that the wallet's UI labels match the new capability.
Security signals we found
Feature addition: adds Taproot xpub export for BlueWallet
Code consolidation: removes duplicate wallet-specific export functions
No secret material handling changes
No bounds-checking, parsing, or authentication logic changes
Evidence from the diff
The patch removes separate GuiGetBlueWalletBtcData() implementations across btc_only, cypherpunk, and web3 firmware variants and redirects BlueWallet (and Nunchuk) to use GuiGetStandardBtcData(), which already included XPUB_TYPE_BTC_TAPROOT for Sparrow/Zeus/UniSat. The change adds Taproot (BIP-86 / m/86’/0’/0’) to the exported crypto-account UR for BlueWallet. No cryptographic code, key derivation, or memory handling logic was altered beyond consolidating the exported key list.
Changed components
src/ui/gui_wallet/btc_only/gui_wallet.csrc/ui/gui_wallet/btc_only/gui_wallet.hsrc/ui/gui_wallet/multi/cypherpunk/gui_wallet.csrc/ui/gui_wallet/multi/cypherpunk/gui_wallet.hsrc/ui/gui_wallet/multi/web3/gui_wallet.csrc/ui/gui_wallet/multi/web3/gui_wallet.hsrc/ui/gui_widgets/btc_only/gui_connect_wallet_widgets.csrc/ui/gui_widgets/multi/cypherpunk/gui_connect_wallet_widgets.csrc/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.cInspect captured patch +16 / −92
diff --git a/src/ui/gui_wallet/btc_only/gui_wallet.c b/src/ui/gui_wallet/btc_only/gui_wallet.c
index ed50ea4..d0f6aed 100644
--- a/src/ui/gui_wallet/btc_only/gui_wallet.c
+++ b/src/ui/gui_wallet/btc_only/gui_wallet.c
@@ -9,42 +9,7 @@
#include "presetting.h"
#include "version.h"
-UREncodeResult *GuiGetBlueWalletBtcData(void)
-{
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- if (GetCurrentWalletIndex() != SINGLE_WALLET) {
- return export_multi_sig_wallet_by_ur(mfp, sizeof(mfp), GetDefaultMultisigWallet()->walletConfig);
- }
- PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey));
- int length = 3;
- ExtendedPublicKey keys[length];
- public_keys->data = keys;
- public_keys->size = length;
-
- if (GetIsTestNet()) {
- keys[0].path = "m/84'/1'/0'";
- keys[1].path = "m/49'/1'/0'";
- keys[2].path = "m/44'/1'/0'";
- keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT_TEST);
- keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_TEST);
- keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY_TEST);
- } else {
- keys[0].path = "m/84'/0'/0'";
- keys[1].path = "m/49'/0'/0'";
- keys[2].path = "m/44'/0'/0'";
- keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT);
- keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC);
- keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY);
- }
-
- UREncodeResult *urEncode = generate_btc_crypto_account_ur(mfp, sizeof(mfp), public_keys);
- CHECK_CHAIN_PRINT(urEncode);
- SRAM_FREE(public_keys);
- return urEncode;
-}
-
-UREncodeResult *GuiGetSparrowWalletBtcData(void)
+UREncodeResult *GuiGetStandardBtcData(void)
{
uint8_t mfp[4] = {0};
GetMasterFingerPrint(mfp);
@@ -76,6 +41,7 @@ UREncodeResult *GuiGetSparrowWalletBtcData(void)
keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY);
keys[3].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_TAPROOT);
}
+
UREncodeResult *urEncode = generate_btc_crypto_account_ur(mfp, sizeof(mfp), public_keys);
CHECK_CHAIN_PRINT(urEncode);
SRAM_FREE(public_keys);
diff --git a/src/ui/gui_wallet/btc_only/gui_wallet.h b/src/ui/gui_wallet/btc_only/gui_wallet.h
index 353964f..b39d7c5 100644
--- a/src/ui/gui_wallet/btc_only/gui_wallet.h
+++ b/src/ui/gui_wallet/btc_only/gui_wallet.h
@@ -4,8 +4,7 @@
#include "rust.h"
#include "gui_chain.h"
-UREncodeResult *GuiGetBlueWalletBtcData(void);
-UREncodeResult *GuiGetSparrowWalletBtcData(void);
+UREncodeResult *GuiGetStandardBtcData(void);
UREncodeResult *GuiGetSpecterWalletBtcData(void);
#endif
diff --git a/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.c b/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.c
index d0a9ec4..2745010 100644
--- a/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.c
+++ b/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.c
@@ -13,28 +13,7 @@ void GenerateCakeWalletEncryptPincode(void);
static uint8_t *g_pincode = NULL;
-UREncodeResult *GuiGetBlueWalletBtcData(void)
-{
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- PtrT_CSliceFFI_ExtendedPublicKey public_keys = SRAM_MALLOC(sizeof(CSliceFFI_ExtendedPublicKey));
- int length = 3;
- ExtendedPublicKey keys[length];
- public_keys->data = keys;
- public_keys->size = length;
- keys[0].path = "m/84'/0'/0'";
- keys[0].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_NATIVE_SEGWIT);
- keys[1].path = "m/49'/0'/0'";
- keys[1].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC);
- keys[2].path = "m/44'/0'/0'";
- keys[2].xpub = GetCurrentAccountPublicKey(XPUB_TYPE_BTC_LEGACY);
- UREncodeResult *urEncode = generate_btc_crypto_account_ur(mfp, sizeof(mfp), public_keys);
- CHECK_CHAIN_PRINT(urEncode);
- SRAM_FREE(public_keys);
- return urEncode;
-}
-
-UREncodeResult *GuiGetSparrowWalletBtcData(void)
+UREncodeResult *GuiGetStandardBtcData(void)
{
uint8_t mfp[4] = {0};
GetMasterFingerPrint(mfp);
diff --git a/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.h b/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.h
index a4209bb..bd3071b 100644
--- a/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.h
+++ b/src/ui/gui_wallet/multi/cypherpunk/gui_wallet.h
@@ -6,8 +6,7 @@
#include "rsa.h"
#include "gui_attention_hintbox.h"
-UREncodeResult *GuiGetBlueWalletBtcData(void);
-UREncodeResult *GuiGetSparrowWalletBtcData(void);
+UREncodeResult *GuiGetStandardBtcData(void);
UREncodeResult *GuiGetCompanionAppData(void);
UREncodeResult *GuiGetBitgetWalletData(void);
UREncodeResult *GuiGetCakeData(void);
diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.c b/src/ui/gui_wallet/multi/web3/gui_wallet.c
index a43e0d8..f34de31 100644
--- a/src/ui/gui_wallet/multi/web3/gui_wallet.c
+++ b/src/ui/gui_wallet/multi/web3/gui_wallet.c
@@ -113,25 +113,7 @@ PtrT_CSliceFFI_ExtendedPublicKey BuildChainPaths(ChainPath_t *chainPaths, Extend
return public_keys;
}
-UREncodeResult *GuiGetBlueWalletBtcData(void)
-{
- ChainPath_t chainPaths[] = {
- {.path = "m/84'/0'/0'", .chainType = XPUB_TYPE_BTC_NATIVE_SEGWIT},
- {.path = "m/49'/0'/0'", .chainType = XPUB_TYPE_BTC},
- {.path = "m/44'/0'/0'", .chainType = XPUB_TYPE_BTC_LEGACY},
- };
- int length = NUMBER_OF_ARRAYS(chainPaths);
- ExtendedPublicKey keys[length];
- uint8_t mfp[4] = {0};
- GetMasterFingerPrint(mfp);
- PtrT_CSliceFFI_ExtendedPublicKey public_keys = BuildChainPaths(chainPaths, keys, length);
- UREncodeResult *urEncode = generate_btc_crypto_account_ur(mfp, sizeof(mfp), public_keys);
- CHECK_CHAIN_PRINT(urEncode);
- SRAM_FREE(public_keys);
- return urEncode;
-}
-
-UREncodeResult *GuiGetSparrowWalletBtcData(void)
+UREncodeResult *GuiGetStandardBtcData(void)
{
ChainPath_t chainPaths[] = {
{.path = "m/84'/0'/0'", .chainType = XPUB_TYPE_BTC_NATIVE_SEGWIT},
diff --git a/src/ui/gui_wallet/multi/web3/gui_wallet.h b/src/ui/gui_wallet/multi/web3/gui_wallet.h
index 87e7aba..f144300 100644
--- a/src/ui/gui_wallet/multi/web3/gui_wallet.h
+++ b/src/ui/gui_wallet/multi/web3/gui_wallet.h
@@ -6,8 +6,7 @@
#include "rsa.h"
#include "gui_attention_hintbox.h"
-UREncodeResult *GuiGetBlueWalletBtcData(void);
-UREncodeResult *GuiGetSparrowWalletBtcData(void);
+UREncodeResult *GuiGetStandardBtcData(void);
UREncodeResult *GuiGetKeplrDataByIndex(uint32_t index);
UREncodeResult *GuiGetLeapData(void);
UREncodeResult *GuiGetWanderData(void);
diff --git a/src/ui/gui_widgets/btc_only/gui_connect_wallet_widgets.c b/src/ui/gui_widgets/btc_only/gui_connect_wallet_widgets.c
index 98aa5ba..19195e2 100644
--- a/src/ui/gui_widgets/btc_only/gui_connect_wallet_widgets.c
+++ b/src/ui/gui_widgets/btc_only/gui_connect_wallet_widgets.c
@@ -196,20 +196,20 @@ void GuiConnectWalletSetQrdata(WALLET_LIST_INDEX_ENUM index)
case WALLET_LIST_BLUE:
case WALLET_LIST_NUNCHUK:
// 84 49 44
- func = GuiGetBlueWalletBtcData;
+ func = GuiGetStandardBtcData;
break;
case WALLET_LIST_ZEUS:
case WALLET_LIST_SPARROW:
case WALLET_LIST_BITCOIN_SAFE:
// 84 49 44 86
- func = GuiGetSparrowWalletBtcData;
+ func = GuiGetStandardBtcData;
break;
case WALLET_LIST_SPECTER:
// 84 49
func = GuiGetSpecterWalletBtcData;
break;
case WALLET_LIST_UNISAT:
- func = GuiGetSparrowWalletBtcData;
+ func = GuiGetStandardBtcData;
break;
default:
return;
diff --git a/src/ui/gui_widgets/multi/cypherpunk/gui_connect_wallet_widgets.c b/src/ui/gui_widgets/multi/cypherpunk/gui_connect_wallet_widgets.c
index eafc698..8f5c299 100644
--- a/src/ui/gui_widgets/multi/cypherpunk/gui_connect_wallet_widgets.c
+++ b/src/ui/gui_widgets/multi/cypherpunk/gui_connect_wallet_widgets.c
@@ -387,17 +387,17 @@ void GuiConnectWalletSetQrdata(WALLET_LIST_INDEX_ENUM index)
lv_obj_clear_flag(g_bottomCont, LV_OBJ_FLAG_CLICKABLE);
switch (index) {
case WALLET_LIST_BLUE:
- func = GuiGetBlueWalletBtcData;
+ func = GuiGetStandardBtcData;
AddBlueWalletCoins();
break;
// todo zeus wallet use same ur logic as sparrow wallet (m/49'/0'/0' 、 m/44'/0'/0' 、 m/84'/0'/0' and m/86'/0'/0' )
case WALLET_LIST_ZEUS:
case WALLET_LIST_SPARROW:
- func = GuiGetSparrowWalletBtcData;
+ func = GuiGetStandardBtcData;
AddBlueWalletCoins();
break;
case WALLET_LIST_UNISAT:
- func = GuiGetSparrowWalletBtcData;
+ func = GuiGetStandardBtcData;
AddUniSatWalletCoins();
lv_label_set_text(g_coinTitleLabel, _("connect_wallet_supported_tokens"));
break;
diff --git a/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c b/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c
index c8caaf3..7888a01 100644
--- a/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c
+++ b/src/ui/gui_widgets/multi/web3/gui_connect_wallet_widgets.c
@@ -1036,18 +1036,18 @@ void GuiConnectWalletSetQrdata(WALLET_LIST_INDEX_ENUM index)
AddCoinsFromArray(g_okxWalletCoinArray, NUMBER_OF_ARRAYS(g_okxWalletCoinArray), true, 132);
break;
case WALLET_LIST_BLUE:
- func = GuiGetBlueWalletBtcData;
+ func = GuiGetStandardBtcData;
AddCoinsFromArray(g_blueWalletCoinArray, NUMBER_OF_ARRAYS(g_blueWalletCoinArray), false, 0);
break;
// todo zeus wallet use same ur logic as sparrow wallet (m/49'/0'/0' 、 m/44'/0'/0' 、 m/84'/0'/0' and m/86'/0'/0' )
case WALLET_LIST_ZEUS:
case WALLET_LIST_SPARROW:
case WALLET_LIST_BABYLON:
- func = GuiGetSparrowWalletBtcData;
+ func = GuiGetStandardBtcData;
AddCoinsFromArray(g_blueWalletCoinArray, NUMBER_OF_ARRAYS(g_blueWalletCoinArray), false, 0);
break;
case WALLET_LIST_UNISAT:
- func = GuiGetSparrowWalletBtcData;
+ func = GuiGetStandardBtcData;
AddCoinsFromArray(g_UniSatCoinArray, NUMBER_OF_ARRAYS(g_UniSatCoinArray), true, 32 * 5);
lv_label_set_text(g_coinTitleLabel, _("connect_wallet_supported_tokens"));
break;
Why this scored 20/100
Community notes
Notes can correct, qualify, or add evidence to the AI analysis. Every note shown here has been validated by a human moderator.
The AI analysis stands alone for now. Submit a note if you can add evidence or important context.