Skip to content

Commit 308f072

Browse files
jgriffithsJamie C. Driver
authored andcommitted
psbt: avoid iterating private keys for outputs
We only need the pubkeys for change detection, so avoid deriving and needing to secure private keys. As a bonus, it's also faster to derive publicly.
1 parent 9995236 commit 308f072

File tree

3 files changed

+20
-12
lines changed

3 files changed

+20
-12
lines changed

main/process/sign_psbt.c

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -463,8 +463,7 @@ static void validate_any_change_outputs(const char* network, struct wally_psbt*
463463

464464
JADE_ASSERT(!multisig_data || !descriptor); // cannot have both
465465

466-
key_iter iter; // Holds any private key in use
467-
SENSITIVE_PUSH(&iter, sizeof(iter));
466+
key_iter iter; // Holds any public key in use
468467

469468
// Check each output in turn
470469
for (size_t index = 0; index < psbt->num_outputs; ++index) {
@@ -474,7 +473,7 @@ static void validate_any_change_outputs(const char* network, struct wally_psbt*
474473
JADE_ASSERT(!(output_info[index].flags & (OUTPUT_FLAG_VALIDATED | OUTPUT_FLAG_CHANGE)));
475474

476475
// Find the first key belonging to this signer
477-
if (!key_iter_output_begin(psbt, index, &iter)) {
476+
if (!key_iter_output_begin_public(psbt, index, &iter)) {
478477
// No key in this output belongs to this signer
479478
JADE_LOGD("No key in output %u, ignoring", index);
480479
continue;
@@ -611,7 +610,6 @@ static void validate_any_change_outputs(const char* network, struct wally_psbt*
611610
"Ignoring multisig output %u as not signing only multisig inputs for a single registration", index);
612611
}
613612
}
614-
SENSITIVE_POP(&iter);
615613
}
616614

617615
// Sign a psbt - the passed wally psbt struct is updated with any signatures.

main/utils/psbt.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,8 @@ static bool key_iter_is_supported_taproot(const key_iter* iter, const struct wal
3232
return true; // One key, no merkle root, no scripts: OK
3333
}
3434

35-
static bool key_iter_init(const struct wally_psbt* psbt, const size_t index, const bool is_input, key_iter* iter)
35+
static bool key_iter_init(
36+
const struct wally_psbt* psbt, const size_t index, const bool is_input, const bool is_private, key_iter* iter)
3637
{
3738
JADE_ASSERT(psbt);
3839
JADE_ASSERT(index <= (is_input ? psbt->num_inputs : psbt->num_outputs));
@@ -42,6 +43,7 @@ static bool key_iter_init(const struct wally_psbt* psbt, const size_t index, con
4243
iter->key_index = 0;
4344
--iter->key_index; // Incrementing will wrap around to 0 i.e. the first key
4445
iter->is_input = is_input;
46+
iter->is_private = is_private;
4547
// We are a taproot key iterator only if we have taproot keypaths
4648
if (is_input) {
4749
iter->is_taproot = psbt->inputs[index].taproot_leaf_paths.num_items != 0;
@@ -54,12 +56,12 @@ static bool key_iter_init(const struct wally_psbt* psbt, const size_t index, con
5456

5557
bool key_iter_input_begin(const struct wally_psbt* psbt, const size_t index, key_iter* iter)
5658
{
57-
return key_iter_init(psbt, index, true, iter);
59+
return key_iter_init(psbt, index, /* is_input */ true, /* is_private */ true, iter);
5860
}
5961

60-
bool key_iter_output_begin(const struct wally_psbt* psbt, const size_t index, key_iter* iter)
62+
bool key_iter_output_begin_public(const struct wally_psbt* psbt, const size_t index, key_iter* iter)
6163
{
62-
return key_iter_init(psbt, index, false, iter);
64+
return key_iter_init(psbt, index, /* is_input */ false, /* is_private */ false, iter);
6365
}
6466

6567
static const struct wally_map* key_iter_get_keypaths(const key_iter* iter)
@@ -83,8 +85,15 @@ bool key_iter_next(key_iter* iter)
8385
iter->is_valid = key_iter_is_supported_taproot(iter, keypaths);
8486
}
8587
if (iter->is_valid) {
86-
JADE_WALLY_VERIFY(wally_map_keypath_get_bip32_key_from(
87-
keypaths, iter->key_index, &keychain_get()->xpriv, &iter->hdkey, &key_index));
88+
int ret;
89+
if (iter->is_private) {
90+
ret = wally_map_keypath_get_bip32_key_from(
91+
keypaths, iter->key_index, &keychain_get()->xpriv, &iter->hdkey, &key_index);
92+
} else {
93+
ret = wally_map_keypath_get_bip32_public_key_from(
94+
keypaths, iter->key_index, &keychain_get()->xpriv, &iter->hdkey, &key_index);
95+
}
96+
JADE_WALLY_VERIFY(ret);
8897
if (key_index) {
8998
iter->is_valid = true; // Found
9099
iter->key_index = key_index - 1; // Adjust to 0-based index

main/utils/psbt.h

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,16 @@ typedef struct key_iter_t {
1919
size_t index;
2020
size_t key_index;
2121
bool is_input;
22+
bool is_private;
2223
bool is_taproot;
2324
bool is_valid;
2425
} key_iter;
2526

2627
// Initialize a key iterator for the `index`th PSBT input
2728
bool key_iter_input_begin(const struct wally_psbt* psbt, size_t index, key_iter* iter);
2829

29-
// Initialize a key iterator for the `index`th PSBT output
30-
bool key_iter_output_begin(const struct wally_psbt* psbt, size_t index, key_iter* iter);
30+
// Initialize a public key iterator for the `index`th PSBT output
31+
bool key_iter_output_begin_public(const struct wally_psbt* psbt, size_t index, key_iter* iter);
3132

3233
/* Advance a key iterator.
3334
* `is_valid` is set to true if a key was found, false otherwise.

0 commit comments

Comments
 (0)