diff --git a/src/common/wallet.c b/src/common/wallet.c index 91cc010c9..f482f0456 100644 --- a/src/common/wallet.c +++ b/src/common/wallet.c @@ -1481,17 +1481,17 @@ static int parse_script(buffer_t *in_buf, buffer_seek_cur(in_buf, 1); // skip ',' buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer - node->tree = (policy_node_tree_t *) buffer_get_cur(out_buf); - + policy_node_tree_t *tree = (policy_node_tree_t *) buffer_get_cur(out_buf); if (0 > parse_tree(in_buf, out_buf, version, depth + 1)) { return WITH_ERROR(-1, "Failed to parse TREE expression"); } + i_policy_node_tree(&node->tree, tree); } else { // no TREE, only tr(KP) if (c != ')') { return WITH_ERROR(-1, "Failed to parse tr"); } - node->tree = NULL; + i_policy_node_tree(&node->tree, NULL); } parsed_node = (policy_node_t *) node; @@ -1877,7 +1877,7 @@ static int parse_tree(buffer_t *in_buf, buffer_t *out_buf, int version, size_t d // parse first TREE expression buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer - init_relative_ptr(&tree_node->left_tree, buffer_get_cur(out_buf)); + i_policy_node_tree(&tree_node->left_tree, buffer_get_cur(out_buf)); if (0 > parse_tree(in_buf, out_buf, version, depth + 1)) { return -1; } @@ -1889,7 +1889,7 @@ static int parse_tree(buffer_t *in_buf, buffer_t *out_buf, int version, size_t d // parse the second TREE expression buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer - init_relative_ptr(&tree_node->right_tree, buffer_get_cur(out_buf)); + i_policy_node_tree(&tree_node->right_tree, buffer_get_cur(out_buf)); if (0 > parse_tree(in_buf, out_buf, version, depth + 1)) { return -1; } diff --git a/src/common/wallet.h b/src/common/wallet.h index 582209937..7a3a945bb 100644 --- a/src/common/wallet.h +++ b/src/common/wallet.h @@ -396,6 +396,9 @@ typedef struct { uint8_t h[32]; } policy_node_with_hash_256_t; +struct policy_node_tree_s; // forward declaration, as the struct is recursive +DEFINE_REL_PTR(policy_node_tree, struct policy_node_tree_s) + // a TREE is either a script, or a {TREE,TREE} typedef struct policy_node_tree_s { bool is_leaf; // if this is a leaf, then it contains a pointer to a SCRIPT; @@ -403,8 +406,8 @@ typedef struct policy_node_tree_s { union { rptr_policy_node_t script; // pointer to a policy_node_with_script_t struct { - ptr_rel_t left_tree; // pointer to a policy_node_tree_s - ptr_rel_t right_tree; // pointer to a policy_node_tree_s + rptr_policy_node_tree_t left_tree; // pointer to a policy_node_tree_s + rptr_policy_node_tree_t right_tree; // pointer to a policy_node_tree_s }; }; } policy_node_tree_t; @@ -412,8 +415,7 @@ typedef struct policy_node_tree_s { typedef struct { struct policy_node_s base; rptr_policy_node_key_placeholder_t key_placeholder; - // TODO: change to relative pointers - policy_node_tree_t *tree; // NULL if tr(KP) + rptr_policy_node_tree_t tree; // NULL if tr(KP) } policy_node_tr_t; /** diff --git a/src/handler/lib/policy.c b/src/handler/lib/policy.c index 12aaa4733..97c4fdda0 100644 --- a/src/handler/lib/policy.c +++ b/src/handler/lib/policy.c @@ -978,8 +978,9 @@ __attribute__((warn_unused_result, noinline)) static int compute_and_combine_tap const policy_node_tree_t *tree, uint8_t out[static 32]) { uint8_t left_h[32], right_h[32]; - if (0 > compute_taptree_hash(dc, wdi, resolve_ptr(&tree->left_tree), left_h)) return -1; - if (0 > compute_taptree_hash(dc, wdi, resolve_ptr(&tree->right_tree), right_h)) return -1; + if (0 > compute_taptree_hash(dc, wdi, r_policy_node_tree(&tree->left_tree), left_h)) return -1; + if (0 > compute_taptree_hash(dc, wdi, r_policy_node_tree(&tree->right_tree), right_h)) + return -1; crypto_tr_combine_taptree_hashes(left_h, right_h, out); return 0; } @@ -1123,8 +1124,11 @@ int get_wallet_script(dispatcher_context_t *dispatcher_context, uint8_t *h = out + 2; // hack: re-use the output array to save memory int h_length = 0; - if (tr_policy->tree != NULL) { - if (0 > compute_taptree_hash(dispatcher_context, wdi, tr_policy->tree, h)) { + if (!isnull_policy_node_tree(&tr_policy->tree)) { + if (0 > compute_taptree_hash(dispatcher_context, + wdi, + r_policy_node_tree(&tr_policy->tree), + h)) { return -1; } h_length = 32; @@ -1356,8 +1360,9 @@ static int get_bip44_purpose(const policy_node_t *descriptor_template) { purpose = 49; // nested segwit break; } - case TOKEN_TR: - if (((const policy_node_tr_t *) descriptor_template)->tree != NULL) { + case TOKEN_TR: { + const policy_node_tr_t *tr = (const policy_node_tr_t *) descriptor_template; + if (!isnull_policy_node_tree(&tr->tree)) { return -1; } @@ -1365,6 +1370,7 @@ static int get_bip44_purpose(const policy_node_t *descriptor_template) { &((const policy_node_tr_t *) descriptor_template)->key_placeholder); purpose = 86; // standard single-key P2TR break; + } default: return -1; } @@ -1510,20 +1516,18 @@ static int get_key_placeholder_by_index_in_tree(const policy_node_tree_t *tree, } return ret; } else { - int ret1 = get_key_placeholder_by_index_in_tree( - (policy_node_tree_t *) resolve_ptr(&tree->left_tree), - i, - out_tapleaf_ptr, - out_placeholder); + int ret1 = get_key_placeholder_by_index_in_tree(r_policy_node_tree(&tree->left_tree), + i, + out_tapleaf_ptr, + out_placeholder); if (ret1 < 0) return -1; bool found = i < (unsigned int) ret1; - int ret2 = get_key_placeholder_by_index_in_tree( - (policy_node_tree_t *) resolve_ptr(&tree->right_tree), - found ? 0 : i - ret1, - found ? NULL : out_tapleaf_ptr, - found ? NULL : out_placeholder); + int ret2 = get_key_placeholder_by_index_in_tree(r_policy_node_tree(&tree->right_tree), + found ? 0 : i - ret1, + found ? NULL : out_tapleaf_ptr, + found ? NULL : out_placeholder); if (ret2 < 0) return -1; return ret1 + ret2; @@ -1567,15 +1571,15 @@ int get_key_placeholder_by_index(const policy_node_t *policy, return 1; } case TOKEN_TR: { + policy_node_tr_t *tr = (policy_node_tr_t *) policy; if (i == 0) { - policy_node_tr_t *tr = (policy_node_tr_t *) policy; memcpy(out_placeholder, r_policy_node_key_placeholder(&tr->key_placeholder), sizeof(policy_node_key_placeholder_t)); } - if (((policy_node_tr_t *) policy)->tree != NULL) { + if (!isnull_policy_node_tree(&tr->tree)) { int ret_tree = get_key_placeholder_by_index_in_tree( - ((policy_node_tr_t *) policy)->tree, + r_policy_node_tree(&tr->tree), i == 0 ? 0 : i - 1, i == 0 ? NULL : out_tapleaf_ptr, i == 0 ? NULL : out_placeholder); // if i == 0, we already found it; so we @@ -1825,10 +1829,10 @@ static int is_taptree_miniscript_sane(const policy_node_tree_t *taptree) { return -1; } } else { - if (0 > is_taptree_miniscript_sane(r_policy_node(&taptree->left_tree))) { + if (0 > is_taptree_miniscript_sane(r_policy_node_tree(&taptree->left_tree))) { return -1; } - if (0 > is_taptree_miniscript_sane(r_policy_node(&taptree->right_tree))) { + if (0 > is_taptree_miniscript_sane(r_policy_node_tree(&taptree->right_tree))) { return -1; } } @@ -1851,7 +1855,8 @@ int is_policy_sane(dispatcher_context_t *dispatcher_context, } } else if (policy->type == TOKEN_TR) { // if there is a taptree, we check the sanity of every miniscript leaf - const policy_node_tree_t *taptree = ((const policy_node_tr_t *) policy)->tree; + const policy_node_tr_t *tr = (const policy_node_tr_t *) policy; + const policy_node_tree_t *taptree = r_policy_node_tree(&tr->tree); if (taptree != NULL && 0 > is_taptree_miniscript_sane(taptree)) { return -1; } diff --git a/src/handler/sign_psbt.c b/src/handler/sign_psbt.c index 09eb49fea..81cd4424b 100644 --- a/src/handler/sign_psbt.c +++ b/src/handler/sign_psbt.c @@ -1962,7 +1962,7 @@ sign_sighash_schnorr_and_yield(dispatcher_context_t *dc, policy_node_tr_t *policy = (policy_node_tr_t *) st->wallet_policy_map; if (!placeholder_info->is_tapscript) { - if (policy->tree == NULL) { + if (isnull_policy_node_tree(&policy->tree)) { // tweak as specified in BIP-86 and BIP-386 crypto_tr_tweak_seckey(seckey, (uint8_t[]){}, 0, seckey); } else { @@ -2299,7 +2299,7 @@ static bool __attribute__((noinline)) sign_transaction_input(dispatcher_context_ return false; policy_node_tr_t *policy = (policy_node_tr_t *) st->wallet_policy_map; - if (!placeholder_info->is_tapscript && policy->tree != NULL) { + if (!placeholder_info->is_tapscript && !isnull_policy_node_tree(&policy->tree)) { // keypath spend, we compute the taptree hash so that we find it ready // later in sign_sighash_schnorr_and_yield (which has less available stack). if (0 > compute_taptree_hash( @@ -2310,7 +2310,7 @@ static bool __attribute__((noinline)) sign_transaction_input(dispatcher_context_ .keys_merkle_root = st->wallet_header_keys_info_merkle_root, .n_keys = st->wallet_header_n_keys, .wallet_version = st->wallet_header_version}, - policy->tree, + r_policy_node_tree(&policy->tree), input->taptree_hash)) { PRINTF("Error while computing taptree hash\n"); SEND_SW(dc, SW_BAD_STATE);