Skip to content

Commit 3347986

Browse files
author
Jamie C. Driver
committed
wallet keychain: cache ga service path roots for network in use
Should improve performance of generating Green multisig addresses, which should in turn improve change detection and hence the signing operation.
1 parent 98176a0 commit 3347986

File tree

4 files changed

+59
-23
lines changed

4 files changed

+59
-23
lines changed

main/keychain.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,27 @@ bool keychain_is_network_type_consistent(const char* network)
242242
return network_type_restriction == NETWORK_TYPE_NONE || network_type == network_type_restriction;
243243
}
244244

245+
const struct ext_key* keychain_cached_service(const struct ext_key* const service, const bool subaccount_root)
246+
{
247+
JADE_ASSERT(keychain_data);
248+
249+
// If no service passed, invalidate cache
250+
if (!service) {
251+
keychain_data->cached_service = NULL;
252+
return NULL;
253+
}
254+
255+
// Recompute cached values if service mismatch
256+
if (service != keychain_data->cached_service) {
257+
wallet_get_gaservice_root_key(service, false, &keychain_data->cached_gaservice_main_root);
258+
wallet_get_gaservice_root_key(service, true, &keychain_data->cached_gaservice_subact_root);
259+
keychain_data->cached_service = service;
260+
}
261+
262+
// Return cached value
263+
return subaccount_root ? &keychain_data->cached_gaservice_subact_root : &keychain_data->cached_gaservice_main_root;
264+
}
265+
245266
void keychain_get_new_mnemonic(char** mnemonic, const size_t nwords)
246267
{
247268
JADE_INIT_OUT_PPTR(mnemonic);
@@ -284,6 +305,9 @@ void keychain_derive_from_seed(const uint8_t* seed, const size_t seed_len, keych
284305

285306
// Compute and cache the path the GA server will use to sign
286307
wallet_calculate_gaservice_path(&keydata->xpriv, keydata->gaservice_path, GASERVICE_PATH_LEN);
308+
309+
// Ensure cached green-multisig service path roots are unset
310+
keydata->cached_service = NULL;
287311
}
288312

289313
// Derive master key from mnemonic if passed a valid mnemonic

main/keychain.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ typedef struct {
1515
uint8_t master_unblinding_key[HMAC_SHA512_LEN];
1616
uint8_t seed[BIP32_ENTROPY_LEN_512];
1717
struct ext_key xpriv;
18+
struct ext_key cached_gaservice_main_root;
19+
struct ext_key cached_gaservice_subact_root;
20+
const struct ext_key* cached_service;
1821
size_t seed_len;
1922
} keychain_t;
2023

@@ -24,6 +27,7 @@ typedef enum { PASSPHRASE_WORDLIST, PASSPHRASE_FREETEXT } passphrase_type_t;
2427
void keychain_init_cache(void);
2528
bool keychain_init_unit_key(void);
2629
void keychain_set(const keychain_t* src, uint8_t userdata, bool temporary);
30+
const struct ext_key* keychain_cached_service(const struct ext_key* service, bool subaccount_root);
2731
void keychain_clear(void);
2832

2933
const keychain_t* keychain_get(void);

main/wallet.c

Lines changed: 30 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -654,6 +654,22 @@ bool wallet_get_gaservice_path(
654654
return true;
655655
}
656656

657+
bool wallet_get_gaservice_root_key(
658+
const struct ext_key* const service, const bool subaccount_root, struct ext_key* gakey)
659+
{
660+
if (!service || !gakey) {
661+
return false;
662+
}
663+
664+
uint32_t root_path[GASERVICE_ROOT_PATH_LEN];
665+
wallet_get_gaservice_path_root(subaccount_root, root_path, GASERVICE_ROOT_PATH_LEN);
666+
667+
JADE_WALLY_VERIFY(
668+
bip32_key_from_parent_path(service, root_path, GASERVICE_ROOT_PATH_LEN, BIP32_FLAG_KEY_PUBLIC, gakey));
669+
670+
return true;
671+
}
672+
657673
// Helper to validate the user-path, and fetch the wallet's relevant gait service pubkey
658674
static bool wallet_get_gaservice_key(
659675
const char* network, const uint32_t* path, const size_t path_len, struct ext_key* gakey)
@@ -663,37 +679,28 @@ static bool wallet_get_gaservice_key(
663679
JADE_ASSERT(path_len);
664680
JADE_ASSERT(gakey);
665681

666-
uint32_t ga_path[MAX_GASERVICE_PATH_LEN]; // 32 + 3 max
667-
size_t ga_path_len = 0;
668-
if (!wallet_get_gaservice_path(path, path_len, ga_path, MAX_GASERVICE_PATH_LEN, &ga_path_len)) {
669-
// Cannot get ga service path from user path
670-
return false;
671-
}
682+
const keychain_t* const keychain = keychain_get();
683+
JADE_ASSERT(keychain);
672684

673-
// Derive ga account pubkey for the path, except the ptr (so we can log it).
674685
const struct ext_key* const service = networkToGaService(network);
675686
if (!service) {
676687
JADE_LOGE("Unknown network: %s", network);
677688
return false;
678689
}
679-
/*
680-
// This outputs the parent service xpub to match what the gdk has in its txn data
681-
struct ext_key garoot;
682-
JADE_WALLY_VERIFY(bip32_key_from_parent_path(service, ga_path, ga_path_len-1, BIP32_FLAG_KEY_PUBLIC |
683-
BIP32_FLAG_SKIP_HASH, &garoot));
684690

685-
// Log this xpub
686-
char *logbuf;
687-
JADE_WALLY_VERIFY(bip32_key_to_base58(&garoot, BIP32_FLAG_KEY_PUBLIC, &logbuf));
688-
JADE_LOGI("service xpub: %s", logbuf);
689-
JADE_WALLY_VERIFY(wally_free_string(logbuf));
691+
uint32_t ga_path_tail[MAX_GASERVICE_PATH_TAIL_LEN];
692+
size_t ga_path_tail_len = 0;
693+
bool is_subaccount_path = false;
694+
if (!wallet_get_gaservice_path_tail(
695+
path, path_len, ga_path_tail, MAX_GASERVICE_PATH_TAIL_LEN, &ga_path_tail_len, &is_subaccount_path)) {
696+
// Path pattern not recognised
697+
return false;
698+
}
699+
700+
const struct ext_key* const cached_service_root = keychain_cached_service(service, is_subaccount_path);
701+
JADE_WALLY_VERIFY(bip32_key_from_parent_path(
702+
cached_service_root, ga_path_tail, ga_path_tail_len, BIP32_FLAG_KEY_PUBLIC | BIP32_FLAG_SKIP_HASH, gakey));
690703

691-
// Derive final part of the path into the output
692-
JADE_WALLY_VERIFY(bip32_key_from_parent_path(&garoot, &ga_path[ga_path_len-1], 1, BIP32_FLAG_KEY_PUBLIC |
693-
BIP32_FLAG_SKIP_HASH, gakey));
694-
*/
695-
JADE_WALLY_VERIFY(
696-
bip32_key_from_parent_path(service, ga_path, ga_path_len, BIP32_FLAG_KEY_PUBLIC | BIP32_FLAG_SKIP_HASH, gakey));
697704
return true;
698705
}
699706

main/wallet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ bool wallet_unserialize_gaservice_path(
9999
bool wallet_get_gaservice_fingerprint(const char* network, uint8_t* output, size_t output_len);
100100
bool wallet_get_gaservice_path(
101101
const uint32_t* path, size_t path_len, uint32_t* ga_path, size_t ga_path_len, size_t* written);
102+
bool wallet_get_gaservice_root_key(const struct ext_key* service, bool subaccount_root, struct ext_key* gakey);
102103

103104
bool wallet_get_message_hash(const uint8_t* bytes, size_t bytes_len, uint8_t* output, size_t output_len);
104105
bool wallet_sign_message_hash(const uint8_t* signature_hash, size_t signature_hash_len, const uint32_t* path,

0 commit comments

Comments
 (0)