Skip to content

Commit

Permalink
[WIP] Use relative pointers for key placeholders in policy; better ty…
Browse files Browse the repository at this point in the history
…pe for pointers to scripts
  • Loading branch information
bigspider committed Jan 10, 2024
1 parent 1981cb6 commit b967596
Show file tree
Hide file tree
Showing 3 changed files with 112 additions and 69 deletions.
34 changes: 18 additions & 16 deletions src/common/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ static int parse_script(buffer_t *in_buf,
static int parse_child_scripts(buffer_t *in_buf,
buffer_t *out_buf,
size_t depth,
ptr_rel_t child_scripts[],
ptr_rel_node_t child_scripts[],
int n_children,
int version,
unsigned int context_flags) {
Expand All @@ -517,7 +517,7 @@ static int parse_child_scripts(buffer_t *in_buf,

for (int child_index = 0; child_index < n_children; child_index++) {
buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer
init_relative_ptr(&child_scripts[child_index], buffer_get_cur(out_buf));
init_relative_node_ptr(&child_scripts[child_index], buffer_get_cur(out_buf));

if (0 > parse_script(in_buf, out_buf, version, depth + 1, context_flags)) {
// failed while parsing internal script
Expand Down Expand Up @@ -616,7 +616,7 @@ static int parse_script(buffer_t *in_buf,
}

if (inner_wrapper != NULL) {
init_relative_ptr(&inner_wrapper->script, node);
init_relative_node_ptr(&inner_wrapper->script, node);
}
inner_wrapper = node;
}
Expand Down Expand Up @@ -738,7 +738,7 @@ static int parse_script(buffer_t *in_buf,
// the internal script is recursively parsed (if successful) in the current location
// of the output buffer
buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer
init_relative_ptr(&node->script, buffer_get_cur(out_buf));
init_relative_node_ptr(&node->script, buffer_get_cur(out_buf));

if (0 > parse_script(in_buf, out_buf, version, depth + 1, inner_context_flags)) {
// failed while parsing internal script
Expand Down Expand Up @@ -1294,7 +1294,7 @@ static int parse_script(buffer_t *in_buf,
++node->n;
// parse a script into cur->script
buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer
init_relative_ptr(&cur->script, buffer_get_cur(out_buf));
init_relative_node_ptr(&cur->script, buffer_get_cur(out_buf));
if (0 > parse_script(in_buf, out_buf, version, depth + 1, context_flags)) {
// failed while parsing internal script
return -1;
Expand Down Expand Up @@ -1379,12 +1379,13 @@ static int parse_script(buffer_t *in_buf,
return WITH_ERROR(-1, "Out of memory");
}

node->key_placeholder = (policy_node_key_placeholder_t *)
policy_node_key_placeholder_t *key_placeholder =
buffer_alloc(out_buf, sizeof(policy_node_key_placeholder_t), true);

if (node->key_placeholder == NULL) {
if (key_placeholder == NULL) {
return WITH_ERROR(-1, "Out of memory");
}
init_relative_node_key_placeholder_ptr(&node->key_placeholder, key_placeholder);

if (token == TOKEN_WPKH) {
if (depth > 0 && ((context_flags & CONTEXT_WITHIN_SH) == 0)) {
Expand All @@ -1396,7 +1397,7 @@ static int parse_script(buffer_t *in_buf,

node->base.type = token;

if (0 > parse_placeholder(in_buf, version, node->key_placeholder)) {
if (0 > parse_placeholder(in_buf, version, key_placeholder)) {
return WITH_ERROR(-1, "Couldn't parse key placeholder");
}

Expand Down Expand Up @@ -1459,14 +1460,14 @@ static int parse_script(buffer_t *in_buf,
return WITH_ERROR(-1, "Out of memory");
}

node->key_placeholder = (policy_node_key_placeholder_t *)
policy_node_key_placeholder_t *key_placeholder =
buffer_alloc(out_buf, sizeof(policy_node_key_placeholder_t), true);

if (node->key_placeholder == NULL) {
if (key_placeholder == NULL) {
return WITH_ERROR(-1, "Out of memory");
}
init_relative_node_key_placeholder_ptr(&node->key_placeholder, key_placeholder);

if (0 > parse_placeholder(in_buf, version, node->key_placeholder)) {
if (0 > parse_placeholder(in_buf, version, key_placeholder)) {
return WITH_ERROR(-1, "Couldn't parse key placeholder");
}

Expand Down Expand Up @@ -1581,7 +1582,8 @@ static int parse_script(buffer_t *in_buf,
// We allocate the array of key indices at the current position in the output buffer
// (on success)
buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer
node->key_placeholders = (policy_node_key_placeholder_t *) buffer_get_cur(out_buf);
init_relative_node_key_placeholder_ptr(&node->key_placeholders,
buffer_get_cur(out_buf));

node->n = 0;
while (true) {
Expand Down Expand Up @@ -1658,7 +1660,7 @@ static int parse_script(buffer_t *in_buf,
// if there was one or more wrappers, the script of the most internal node must point
// to the parsed node
if (inner_wrapper != NULL) {
init_relative_ptr(&inner_wrapper->script, parsed_node);
init_relative_node_ptr(&inner_wrapper->script, parsed_node);
}

// Validate and compute the flags (miniscript type and modifiers) for all the wrapper, if any
Expand All @@ -1670,7 +1672,7 @@ static int parse_script(buffer_t *in_buf,
// find the actual node by traversing the list
policy_node_with_script_t *node = (policy_node_with_script_t *) outermost_node;
for (int j = 0; j < i; j++) {
node = (policy_node_with_script_t *) resolve_ptr(&node->script);
node = (policy_node_with_script_t *) resolve_node_ptr(&node->script);
}

if (!resolve_node_ptr(&node->script)->flags.is_miniscript) {
Expand Down Expand Up @@ -1864,7 +1866,7 @@ static int parse_tree(buffer_t *in_buf, buffer_t *out_buf, int version, size_t d
tree_node->is_leaf = true;

buffer_alloc(out_buf, 0, true); // ensure alignment of current pointer
init_relative_ptr(&tree_node->script, buffer_get_cur(out_buf));
init_relative_node_ptr(&tree_node->script, buffer_get_cur(out_buf));
if (0 > parse_script(in_buf, out_buf, version, depth + 1, CONTEXT_WITHIN_TR)) {
return -1;
}
Expand Down
53 changes: 42 additions & 11 deletions src/common/wallet.h
Original file line number Diff line number Diff line change
Expand Up @@ -223,6 +223,18 @@ typedef struct ptr_rel_s {
uint16_t offset;
} ptr_rel_t;

// Typed versions for each of the kinds of pointers

// relative pointer to policy_node_s
typedef struct ptr_rel_node_s {
uint16_t offset;
} ptr_rel_node_t;

// relative pointer to policy_node_key_placeholder_s
typedef struct ptr_rel_node_key_placeholder_s {
uint16_t offset;
} ptr_rel_node_key_placeholder_t;

#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wcomment"
// The compiler doesn't like /** inside a block comment, so we disable this warning temporarily.
Expand Down Expand Up @@ -253,19 +265,19 @@ typedef struct {
// 4 bytes
typedef struct {
struct policy_node_s base;
ptr_rel_t script;
ptr_rel_node_t script;
} policy_node_with_script_t;

// 6 bytes
typedef struct {
struct policy_node_s base;
ptr_rel_t scripts[2];
ptr_rel_node_t scripts[2];
} policy_node_with_script2_t;

// 8 bytes
typedef struct {
struct policy_node_s base;
ptr_rel_t scripts[3];
ptr_rel_node_t scripts[3];
} policy_node_with_script3_t;

// generic type with pointer for up to 3 (but constant) number of child scripts
Expand All @@ -274,7 +286,7 @@ typedef policy_node_with_script3_t policy_node_with_scripts_t;
// 4 bytes
typedef struct {
struct policy_node_s base;
policy_node_key_placeholder_t *key_placeholder;
ptr_rel_node_key_placeholder_t key_placeholder;
} policy_node_with_key_t;

// 8 bytes
Expand All @@ -288,21 +300,23 @@ typedef struct {
struct policy_node_s base; // type is TOKEN_MULTI or TOKEN_SORTEDMULTI
int16_t k; // threshold
int16_t n; // number of keys
policy_node_key_placeholder_t
*key_placeholders; // pointer to array of exactly n key placeholders
ptr_rel_node_key_placeholder_t
key_placeholders; // pointer to array of exactly n key placeholders
} policy_node_multisig_t;

// 8 bytes
typedef struct policy_node_scriptlist_s {
// TODO: change to relative pointers
struct policy_node_scriptlist_s *next;
ptr_rel_t script;
ptr_rel_node_t script;
} policy_node_scriptlist_t;

// 12 bytes, (+ 8 bytes for every script)
typedef struct {
struct policy_node_s base; // type is TOKEN_THRESH
int16_t k; // threshold
int16_t n; // number of child scripts
// TODO: change to relative pointers
policy_node_scriptlist_t
*scriptlist; // pointer to array of exactly n pointers to child scripts
} policy_node_thresh_t;
Expand All @@ -322,7 +336,7 @@ 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 {
ptr_rel_t script; // pointer to a policy_node_with_script_t
ptr_rel_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
Expand All @@ -332,7 +346,8 @@ typedef struct policy_node_tree_s {

typedef struct {
struct policy_node_s base;
policy_node_key_placeholder_t *key_placeholder;
ptr_rel_node_key_placeholder_t key_placeholder;
// TODO: change to relative pointers
policy_node_tree_t *tree; // NULL if tr(KP)
} policy_node_tr_t;

Expand All @@ -344,8 +359,14 @@ static inline const void *resolve_ptr(const ptr_rel_t *ptr) {
}

// Syntactic sugar for resolve_ptr when the return value is a pointer to policy_node_t
static inline const policy_node_t *resolve_node_ptr(const ptr_rel_t *ptr) {
return (const void *) ((const uint8_t *) ptr + ptr->offset);
static inline const policy_node_t *resolve_node_ptr(const ptr_rel_node_t *ptr) {
return (const policy_node_t *) ((const uint8_t *) ptr + ptr->offset);
}

// Syntactic sugar for resolve_ptr when the return value is a pointer to policy_node_t
static inline const policy_node_key_placeholder_t *resolve_node_key_placeholder_ptr(
const ptr_rel_node_key_placeholder_t *ptr) {
return (const policy_node_key_placeholder_t *) ((const uint8_t *) ptr + ptr->offset);
}

// Initializes a relative pointer so that it points to node.
Expand All @@ -356,6 +377,16 @@ static inline void init_relative_ptr(ptr_rel_t *relative_ptr, void *node) {
relative_ptr->offset = (uint16_t) ((uint8_t *) node - (uint8_t *) relative_ptr);
}

static inline void init_relative_node_ptr(ptr_rel_node_t *relative_ptr, void *node) {
relative_ptr->offset = (uint16_t) ((uint8_t *) node - (uint8_t *) relative_ptr);
}

static inline void init_relative_node_key_placeholder_ptr(
ptr_rel_node_key_placeholder_t *relative_ptr,
void *node) {
relative_ptr->offset = (uint16_t) ((uint8_t *) node - (uint8_t *) relative_ptr);
}

/**
* Parses the string in the `buffer` as a serialized policy map into `header`
*
Expand Down
Loading

0 comments on commit b967596

Please sign in to comment.