Skip to content

Commit

Permalink
Refactored policy_node_tree_t to use relative pointers
Browse files Browse the repository at this point in the history
  • Loading branch information
bigspider committed Jan 10, 2024
1 parent c7a2b86 commit ce0c13e
Show file tree
Hide file tree
Showing 4 changed files with 41 additions and 34 deletions.
10 changes: 5 additions & 5 deletions src/common/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand All @@ -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;
}
Expand Down
10 changes: 6 additions & 4 deletions src/common/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,24 +396,26 @@ 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;
// otherwise, it contains two pointers to TREE expressions.
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;

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;

/**
Expand Down
49 changes: 27 additions & 22 deletions src/handler/lib/policy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1356,15 +1360,17 @@ 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;
}

kp = r_policy_node_key_placeholder(
&((const policy_node_tr_t *) descriptor_template)->key_placeholder);
purpose = 86; // standard single-key P2TR
break;
}
default:
return -1;
}
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
}
}
Expand All @@ -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;
}
Expand Down
6 changes: 3 additions & 3 deletions src/handler/sign_psbt.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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(
Expand All @@ -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);
Expand Down

0 comments on commit ce0c13e

Please sign in to comment.