Skip to content

Commit 73c385f

Browse files
committed
Verify that the number of keys in policy being registered is correct
1 parent a1fe503 commit 73c385f

File tree

5 files changed

+50
-0
lines changed

5 files changed

+50
-0
lines changed

bitcoin_client_js/src/__tests__/appClient.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ describe("test AppClient", () => {
267267
[
268268
"[76223a6e/48'/1'/0'/2']tpubDE7NQymr4AFtewpAsWtnreyq9ghkzQBXpCZjWLFVRAvnbf7vya2eMTvT2fPapNqL8SuVvLQdbUbMfWLVDCZKnsEBqp6UK93QEzL8Ck23AwF",
269269
"[f5acc2fd/48'/1'/0'/2']tpubDFAqEGNyad35aBCKUAXbQGDjdVhNueno5ZZVEn3sQbW5ci457gLR7HyTmHBg93oourBssgUxuWz1jX5uhc1qaqFo9VsybY1J5FuedLfm4dK",
270+
"tpubDCoDDpHR1MYXcFrarTcwBufQvWPXSSZpGxjnhRaW612TMxs5TWDEPdbYRHtQdZ9z1UqtKGQKVQ4FqejzbFSdvQvJsD75yrgh7thVoFho6jE",
270271
]
271272
);
272273

src/handler/lib/policy.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1645,6 +1645,21 @@ int get_key_placeholder_by_index(const policy_node_t *policy,
16451645
return -1;
16461646
}
16471647

1648+
int count_distinct_keys_info(const policy_node_t *policy) {
1649+
policy_node_key_placeholder_t placeholder;
1650+
int ret = -1, cur, n_placeholders;
1651+
1652+
for (cur = 0;
1653+
cur < (n_placeholders = get_key_placeholder_by_index(policy, cur, NULL, &placeholder));
1654+
++cur) {
1655+
if (n_placeholders < 0) {
1656+
return -1;
1657+
}
1658+
ret = MAX(ret, placeholder.key_index + 1);
1659+
}
1660+
return ret;
1661+
}
1662+
16481663
// Utility function to extract and decode the i-th xpub from the keys information vector
16491664
static int get_pubkey_from_merkle_tree(dispatcher_context_t *dispatcher_context,
16501665
int wallet_version,

src/handler/lib/policy.h

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,18 @@ __attribute__((warn_unused_result)) int get_key_placeholder_by_index(
195195
const policy_node_t **out_tapleaf_ptr,
196196
policy_node_key_placeholder_t *out_placeholder);
197197

198+
/**
199+
* Determines the expected number of unique keys in the provided policy's key information.
200+
* The function calculates this by finding the maximum key index from placeholders and increments it
201+
* by 1. For instance, if the maximum key index found in the placeholders is `n`, then the result
202+
* would be `n + 1`.
203+
*
204+
* @param[in] policy
205+
* Pointer to the root node of the policy
206+
* @return the expected number of items in the keys information vector; -1 in case of error.
207+
*/
208+
__attribute__((warn_unused_result)) int count_distinct_keys_info(const policy_node_t *policy);
209+
198210
/**
199211
* Checks if a wallet policy is sane, verifying that pubkeys are never repeated and (if miniscript)
200212
* that the miniscript is "sane".

src/handler/register_wallet.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,18 @@ void handler_register_wallet(dispatcher_context_t *dc, uint8_t protocol_version)
8888
return;
8989
}
9090

91+
if (count_distinct_keys_info(&policy_map.parsed) != (int) wallet_header.n_keys) {
92+
PRINTF("Number of keys in descriptor template doesn't provided keys\n");
93+
SEND_SW(dc, SW_INCORRECT_DATA);
94+
return;
95+
}
96+
9197
// Compute the wallet id (sha256 of the serialization)
9298
get_policy_wallet_id(&wallet_header, wallet_id);
9399

94100
// Verify that the name is acceptable
95101
if (!is_policy_name_acceptable(wallet_header.name, wallet_header.name_len)) {
102+
PRINTF("Policy name is not acceptable\n");
96103
SEND_SW(dc, SW_INCORRECT_DATA);
97104
return;
98105
}

tests/test_register_wallet.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,21 @@ def test_register_wallet_invalid_names(client: Client):
117117
client.register_wallet(wallet)
118118

119119

120+
@has_automation("automations/register_wallet_accept.json")
121+
def test_register_wallet_missing_key(client: Client):
122+
wallet = WalletPolicy(
123+
name="Missing a key",
124+
descriptor_template="wsh(multi(2,@0/**,@1/**))",
125+
keys_info=[
126+
"[f5acc2fd/48'/1'/0'/2']tpubDFAqEGNyad35aBCKUAXbQGDjdVhNueno5ZZVEn3sQbW5ci457gLR7HyTmHBg93oourBssgUxuWz1jX5uhc1qaqFo9VsybY1J5FuedLfm4dK",
127+
# the second key is missing
128+
],
129+
)
130+
131+
with pytest.raises(IncorrectDataError):
132+
client.register_wallet(wallet)
133+
134+
120135
@has_automation("automations/register_wallet_accept.json")
121136
def test_register_wallet_unsupported_policy(client: Client):
122137
# valid policies, but not supported (might change in the future)

0 commit comments

Comments
 (0)