Skip to content

Commit

Permalink
[WIP] Support for tapminiscript
Browse files Browse the repository at this point in the history
  • Loading branch information
bigspider committed Apr 26, 2023
1 parent 308f51b commit e677531
Show file tree
Hide file tree
Showing 4 changed files with 147 additions and 60 deletions.
148 changes: 95 additions & 53 deletions src/common/wallet.c
Original file line number Diff line number Diff line change
Expand Up @@ -527,8 +527,12 @@ static int parse_script(buffer_t *in_buf,
policy_node_t *outermost_node = (policy_node_t *) buffer_get_cur(out_buf);
policy_node_with_script_t *inner_wrapper = NULL; // pointer to the inner wrapper, if any

// miniscript-related parsing only within top-level WSH
if ((context_flags & CONTEXT_WITHIN_WSH) != 0 && (context_flags & CONTEXT_WITHIN_SH) == 0) {
// miniscript-related parsing only within top-level WSH, or within tr
bool parse_as_miniscript =
((context_flags & CONTEXT_WITHIN_WSH) != 0 && (context_flags & CONTEXT_WITHIN_SH) == 0) ||
(context_flags & CONTEXT_WITHIN_TR) != 0;

if (parse_as_miniscript) {
// look ahead to finds out if the buffer starts with alphanumeric digits that could be
// wrappers, followed by a colon
char c;
Expand Down Expand Up @@ -603,19 +607,6 @@ static int parse_script(buffer_t *in_buf,
// We read the token, we'll do different parsing based on what token we find
PolicyNodeType token = parse_token(in_buf);

if (context_flags & CONTEXT_WITHIN_TR) {
// whitelist of allowed tokens within tr scripts
// more will be added with taproot miniscript support
switch (token) {
case TOKEN_PK:
case TOKEN_MULTI_A:
case TOKEN_SORTEDMULTI_A:
break;
default:
return WITH_ERROR(-1, "Token not allowed within tr");
}
}

if (context_flags & CONTEXT_WITHIN_SH) {
// whitelist of allowed tokens within sh; in particular, no miniscript
switch (token) {
Expand Down Expand Up @@ -1526,6 +1517,20 @@ static int parse_script(buffer_t *in_buf,
return WITH_ERROR(-1, "Out of memory");
}

if ((context_flags & CONTEXT_WITHIN_TR) != 0) {
if (token != TOKEN_MULTI_A && token != TOKEN_SORTEDMULTI_A) {
return WITH_ERROR(
-1,
"multi and sortedmulti can only be used legacy or segwit scripts");
}
} else { // legacy or segwit scripts
if (token != TOKEN_MULTI && token != TOKEN_SORTEDMULTI) {
return WITH_ERROR(
-1,
"multi_a and sortedmulti_a can only be used in taproot scripts");
}
}

if (token == TOKEN_SORTEDMULTI) {
size_t n_sh_wrappers = 0;
if (context_flags & CONTEXT_WITHIN_SH) ++n_sh_wrappers;
Expand Down Expand Up @@ -1587,16 +1592,24 @@ static int parse_script(buffer_t *in_buf,
return WITH_ERROR(-1, "Invalid k and/or n");
}

if (token == TOKEN_SORTEDMULTI) {
if (token == TOKEN_SORTEDMULTI || token == TOKEN_SORTEDMULTI_A) {
node->base.flags.is_miniscript = 0;
} else {
} else if (token == TOKEN_MULTI) {
node->base.flags.is_miniscript = 1;
node->base.flags.miniscript_type = MINISCRIPT_TYPE_B;
node->base.flags.miniscript_mod_z = 0;
node->base.flags.miniscript_mod_o = 0;
node->base.flags.miniscript_mod_n = 1;
node->base.flags.miniscript_mod_d = 1;
node->base.flags.miniscript_mod_u = 1;
} else if (token == TOKEN_MULTI_A) {
node->base.flags.is_miniscript = 1;
node->base.flags.miniscript_type = MINISCRIPT_TYPE_B;
node->base.flags.miniscript_mod_z = 0;
node->base.flags.miniscript_mod_o = 0;
node->base.flags.miniscript_mod_n = 0;
node->base.flags.miniscript_mod_d = 1;
node->base.flags.miniscript_mod_u = 1;
}

break;
Expand Down Expand Up @@ -1714,7 +1727,7 @@ static int parse_script(buffer_t *in_buf,
node->base.flags.miniscript_mod_o = 1;
node->base.flags.miniscript_mod_n = 1;
node->base.flags.miniscript_mod_d = 1;
node->base.flags.miniscript_mod_u = 0;
node->base.flags.miniscript_mod_u = (context_flags & CONTEXT_WITHIN_TR) ? 1 : 0;
break;
case TOKEN_V:
if (X_type != MINISCRIPT_TYPE_B) {
Expand Down Expand Up @@ -1926,7 +1939,9 @@ static int16_t maxcheck(int16_t a, int16_t b) {

// Separated from the main function as it is stack-intensive, therefore we allocate large buffers
// into the CXRAM section. There is some repeated work ()
static int compute_thresh_ops(const policy_node_thresh_t *node, miniscript_ops_t *out) {
static int compute_thresh_ops(const policy_node_thresh_t *node,
miniscript_ops_t *out,
MiniscriptContext ctx) {
#ifdef USE_CXRAM_SECTION
// allocate buffers inside the cxram section; safe as there are no syscalls here
uint16_t *sats = (uint16_t *) get_cxram_buffer();
Expand All @@ -1948,7 +1963,8 @@ static int compute_thresh_ops(const policy_node_thresh_t *node, miniscript_ops_t

while (cur != NULL) {
policy_node_ext_info_t t;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&cur->script), &t)) return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&cur->script), &t, ctx))
return -1;

out->count += t.ops.count + 1;

Expand All @@ -1972,7 +1988,9 @@ static int compute_thresh_ops(const policy_node_thresh_t *node, miniscript_ops_t

// Separated from the main function as it is stack-intensive, therefore we allocate large buffers
// into the CXRAM section. There is some repeated work ()
static int compute_thresh_stacksize(const policy_node_thresh_t *node, miniscript_stacksize_t *out) {
static int compute_thresh_stacksize(const policy_node_thresh_t *node,
miniscript_stacksize_t *out,
MiniscriptContext ctx) {
#ifdef USE_CXRAM_SECTION
// allocate buffers inside the cxram section; safe as there are no syscalls here
uint16_t *sats = (uint16_t *) get_cxram_buffer();
Expand All @@ -1992,7 +2010,8 @@ static int compute_thresh_stacksize(const policy_node_thresh_t *node, miniscript

while (cur != NULL) {
policy_node_ext_info_t t;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&cur->script), &t)) return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&cur->script), &t, ctx))
return -1;

next_sats[0] = sumcheck(sats[0], t.ss.dsat);
for (int j = 1; j < sats_size; j++) {
Expand All @@ -2011,12 +2030,18 @@ static int compute_thresh_stacksize(const policy_node_thresh_t *node, miniscript
return 0;
}

// TODO: generalize stack size computation for tapminiscript
int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t *out) {
policy_node_ext_info_t *out,
MiniscriptContext ctx) {
if (!policy_node->flags.is_miniscript) {
return WITH_ERROR(-1, "Not miniscript");
}

if (ctx != MINISCRIPT_CONTEXT_P2WSH && ctx != MINISCRIPT_CONTEXT_TAPSCRIPT) {
return WITH_ERROR(-1, "Unknown miniscript context");
}

memset(out, 0, sizeof(policy_node_ext_info_t));

// set flags that are 1 in most cases (they will be zeroed when appropriate)
Expand Down Expand Up @@ -2048,7 +2073,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
out->s = 1;
out->e = 1;

out->script_size = 34;
out->script_size = (ctx == MINISCRIPT_CONTEXT_TAPSCRIPT ? 33 : 34);

out->ops = (miniscript_ops_t){0, 0, 0};
out->ss = (miniscript_stacksize_t){1, 1};
Expand All @@ -2070,7 +2095,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,

out->x = 0;

out->script_size = 34 + 1;
out->script_size = (ctx == MINISCRIPT_CONTEXT_TAPSCRIPT ? 34 : 35);

out->ops = (miniscript_ops_t){1, 0, 0};
out->ss = (miniscript_stacksize_t){1, 1};
Expand Down Expand Up @@ -2167,11 +2192,14 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t y;
policy_node_ext_info_t z;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[2]), &z))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[2]), &z, ctx))
return -1;

out->s = z.s & (x.s | y.s);
Expand Down Expand Up @@ -2207,9 +2235,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t y;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y, ctx))
return -1;

out->s = x.s | y.s;
Expand Down Expand Up @@ -2241,9 +2271,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t y;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y, ctx))
return -1;

out->s = x.s | y.s;
Expand Down Expand Up @@ -2277,9 +2309,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t y;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &y, ctx))
return -1;

out->s = x.s | y.s;
Expand Down Expand Up @@ -2310,9 +2344,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t z;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z, ctx))
return -1;

out->s = x.s & z.s;
Expand Down Expand Up @@ -2344,9 +2380,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t z;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z, ctx))
return -1;

out->s = x.s & z.s;
Expand Down Expand Up @@ -2376,9 +2414,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t z;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z, ctx))
return -1;

out->s = x.s & z.s;
Expand Down Expand Up @@ -2409,9 +2449,11 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
policy_node_ext_info_t x;
policy_node_ext_info_t z;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[0]), &x, ctx))
return -1;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z))
if (0 >
compute_miniscript_policy_ext_info(resolve_node_ptr(&node->scripts[1]), &z, ctx))
return -1;

out->s = x.s & z.s;
Expand Down Expand Up @@ -2452,7 +2494,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
++n_children;

policy_node_ext_info_t t;
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&cur->script), &t))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&cur->script), &t, ctx))
return -1;

if (t.e) {
Expand Down Expand Up @@ -2493,16 +2535,16 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,

out->script_size = children_scriptsize + n_children + get_push_script_size(node->k);

if (0 > compute_thresh_ops(node, &out->ops)) return -1;
if (0 > compute_thresh_stacksize(node, &out->ss)) return -1;
if (0 > compute_thresh_ops(node, &out->ops, ctx)) return -1;
if (0 > compute_thresh_stacksize(node, &out->ss, ctx)) return -1;

return 0;
}
case TOKEN_A: {
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand All @@ -2529,7 +2571,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand Down Expand Up @@ -2557,7 +2599,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = 1;
Expand Down Expand Up @@ -2587,7 +2629,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand All @@ -2612,7 +2654,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand All @@ -2638,7 +2680,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand All @@ -2663,7 +2705,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand All @@ -2689,7 +2731,7 @@ int compute_miniscript_policy_ext_info(const policy_node_t *policy_node,
const policy_node_with_script_t *node = (const policy_node_with_script_t *) policy_node;
policy_node_ext_info_t x;

if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x))
if (0 > compute_miniscript_policy_ext_info(resolve_node_ptr(&node->script), &x, ctx))
return -1;

out->s = x.s;
Expand Down
Loading

0 comments on commit e677531

Please sign in to comment.