Skip to content

Commit f609d58

Browse files
committed
descriptor: add rawtr constant, add support for x-only hex keys
We must differentiate between x-only being allowed, mandatory, and not allowed, so the logic is a little more complex. If we get a non-x-only hex key for a rawtr() expression, convert it in-place to an x-only key to make future handling simpler.
1 parent f8a0a5e commit f609d58

File tree

1 file changed

+32
-22
lines changed

1 file changed

+32
-22
lines changed

src/descriptor.c

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
#define KIND_DESCRIPTOR_COMBO (0x00030000 | KIND_DESCRIPTOR)
8787
#define KIND_DESCRIPTOR_ADDR (0x00040000 | KIND_DESCRIPTOR)
8888
#define KIND_DESCRIPTOR_RAW (0x00050000 | KIND_DESCRIPTOR)
89+
#define KIND_DESCRIPTOR_RAW_TR (0x00060000 | KIND_DESCRIPTOR)
8990

9091
/* miniscript */
9192
#define KIND_MINISCRIPT_PK (0x00000100 | KIND_MINISCRIPT)
@@ -2028,41 +2029,50 @@ static int analyze_address(ms_ctx *ctx, const char *str, size_t str_len,
20282029
static int analyze_pubkey_hex(ms_ctx *ctx, ms_node *node,
20292030
uint32_t flags, bool *is_hex)
20302031
{
2031-
unsigned char pubkey[EC_PUBLIC_KEY_UNCOMPRESSED_LEN + 1];
2032-
size_t offset = flags & WALLY_MINISCRIPT_TAPSCRIPT ? 1 : 0;
2033-
size_t written;
2034-
2035-
*is_hex = false;
2036-
if (offset) {
2037-
if (node->data_len != EC_XONLY_PUBLIC_KEY_LEN * 2)
2032+
unsigned char pubkey[EC_PUBLIC_KEY_UNCOMPRESSED_LEN];
2033+
size_t pubkey_len;
2034+
bool allow_xonly, make_xonly = false;
2035+
2036+
*is_hex = wally_hex_n_to_bytes(node->data, node->data_len,
2037+
pubkey, sizeof(pubkey), &pubkey_len) == WALLY_OK;
2038+
if (!is_hex || pubkey_len > sizeof(pubkey))
2039+
return WALLY_OK; /* Not hex, or too long */
2040+
2041+
if (wally_ec_public_key_verify(pubkey, pubkey_len) != WALLY_OK &&
2042+
wally_ec_xonly_public_key_verify(pubkey, pubkey_len) != WALLY_OK)
2043+
return WALLY_OK; /* Not a valid pubkey */
2044+
2045+
make_xonly = node->parent && (node->parent->kind == KIND_DESCRIPTOR_RAW_TR);
2046+
allow_xonly = make_xonly || flags & WALLY_MINISCRIPT_TAPSCRIPT;
2047+
if (pubkey_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN && allow_xonly)
2048+
return WALLY_OK; /* Uncompressed key not allowed here */
2049+
if (pubkey_len == EC_XONLY_PUBLIC_KEY_LEN && !allow_xonly)
2050+
return WALLY_OK; /* X-only not allowed here */
2051+
if (pubkey_len != EC_XONLY_PUBLIC_KEY_LEN) {
2052+
if (flags & WALLY_MINISCRIPT_TAPSCRIPT)
20382053
return WALLY_OK; /* Only X-only pubkeys allowed under tapscript */
2039-
pubkey[0] = 2; /* Non-X-only pubkey prefix, for validation below */
2040-
} else {
2041-
if (node->data_len != EC_PUBLIC_KEY_LEN * 2 &&
2042-
node->data_len != EC_PUBLIC_KEY_UNCOMPRESSED_LEN * 2)
2043-
return WALLY_OK; /* Unknown public key size */
2054+
if (make_xonly) {
2055+
/* Convert to x-only */
2056+
--pubkey_len;
2057+
memmove(pubkey, pubkey + 1, pubkey_len);
2058+
}
20442059
}
20452060

2046-
if (wally_hex_n_to_bytes(node->data, node->data_len,
2047-
pubkey + offset, sizeof(pubkey) - offset, &written) != WALLY_OK ||
2048-
wally_ec_public_key_verify(pubkey, written + offset) != WALLY_OK)
2049-
return WALLY_OK; /* Not hex, or not a pubkey */
2050-
2051-
if (!clone_bytes((unsigned char **)&node->data, pubkey + offset, written))
2061+
if (!clone_bytes((unsigned char **)&node->data, pubkey, pubkey_len))
20522062
return WALLY_ENOMEM;
2053-
node->data_len = node->data_len / 2;
2054-
if (node->data_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN) {
2063+
node->data_len = pubkey_len;
2064+
2065+
if (pubkey_len == EC_PUBLIC_KEY_UNCOMPRESSED_LEN) {
20552066
node->flags |= WALLY_MS_IS_UNCOMPRESSED;
20562067
ctx->features |= WALLY_MS_IS_UNCOMPRESSED;
20572068
}
2058-
if (node->data_len == EC_XONLY_PUBLIC_KEY_LEN) {
2069+
if (pubkey_len == EC_XONLY_PUBLIC_KEY_LEN) {
20592070
node->flags |= WALLY_MS_IS_X_ONLY;
20602071
ctx->features |= WALLY_MS_IS_X_ONLY;
20612072
}
20622073
ctx->features |= WALLY_MS_IS_RAW;
20632074
node->kind = KIND_PUBLIC_KEY;
20642075
node->flags |= WALLY_MS_IS_RAW;
2065-
*is_hex = true;
20662076
return ctx_add_key_node(ctx, node);
20672077
}
20682078

0 commit comments

Comments
 (0)