Skip to content

Commit 231d9b6

Browse files
committed
Merge ElementsProject#27: Introduce introspection operations
3dce073 Add a detailed spec for extensions (sanket1729) df75157 Add integration tests for Introspection opcodes (sanket1729) 6bf9d2c Consider Introspect operations in all Covenants (sanket1729) 995bb33 Introduce introspection operations (sanket1729) Pull request description: - Equality of values, assets, spks(possibly confidential) - Testing where an asset/value is explicit - Checking the current executing input index ACKs for top commit: apoelstra: ACK 3dce073 Tree-SHA512: 0282c2ec48739f7a1d122fd5a51191f3424a1ecee10d7e5823a05dcbcca92b1af11d03feff470bd3e10f48a162c180cfb14b26f86b3837617714a18dad4ed61e
2 parents 6cf7711 + 3dce073 commit 231d9b6

File tree

6 files changed

+1681
-5
lines changed

6 files changed

+1681
-5
lines changed

doc/extension_spec.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# Miniscript Extensions:
2+
3+
Extensions allow users to extend miniscript to have new leaf nodes. This document lists
4+
extensions implemented for elements-miniscript with the tapscript opcodes. Users can
5+
also implement custom extensions using [`Extension`] trait.
6+
7+
# Value Arithmetic extensions (`NumExpr`)
8+
9+
- Pushes single singed 64 bit LE number on stack top. Since these expressions push a 8 byte number, it does not directly
10+
fit in the miniscript model. These are used in fragments in one of the comparison fragment listed in the next section.
11+
- All of introspection opcodes explicitly assert the amount is explicit.
12+
- This will abort when
13+
- Any of operations are on confidential amounts. The Null case is automatically converted to explicit zero.
14+
- Supplied index is out of bounds.
15+
- Any of the operations overflow. Refer to tapscript [opcodes](https://github.com/ElementsProject/elements/blob/master/doc/tapscript_opcodes.md) spec for overflow specification
16+
17+
Name | Script
18+
--- | ---
19+
i(i64 number) | `8-byte-LE-push of <i>`
20+
curr_inp_v | `INSPECTCURRENTINPUTINDEX INPSECTINPUTVALUE <1> EQUALVERIFY`
21+
inp_v(i) | `i INPSECTINPUTVALUE <1> EQUALVERIFY`
22+
out_v(i) | `i INPSECTOUTPUTVALUE <1> EQUALVERIFY`
23+
inp_issue_v(i) | `i OP_INSPECTINPUTISSUANCE DROP DROP <1> EQUALVERIFY NIP NIP`
24+
inp_reissue_v(i) | `i OP_INSPECTINPUTISSUANCE DROP DROP DROP DROP <1> EQUALVERIFY`
25+
bitinv(x) | `[X] INVERT`
26+
neg(x) | `[X] NEG64 <1> EQUALVERIFY`
27+
add(x,y) | `[X] [Y] ADD64 <1> EQUALVERIFY`
28+
sub(x,y) | `[X] [Y] SUB64 <1> EQUALVERIFY`
29+
mul(x,y) | `[X] [Y] MUL64 <1> EQUALVERIFY`
30+
div(x,y) | `[X] [Y] DIV64 <1> EQUALVERIFY NIP`
31+
mod(x,y) | `[X] [Y] DIV64 <1> EQUALVERIFY DROP`
32+
bitand(x,y) | `[X] [Y] AND`
33+
bitor(x,y) | `[X] [Y] OR (cannot fail)`
34+
bitxor(x,y) | `[X] [Y] XOR (cannot fail)`
35+
36+
37+
- The division operation pushes the quotient(a//b) such that the remainder a%b (must be non-negative and less than |b|).
38+
- neg(a) returns -a, whereas bitinv(a) returns ~a.
39+
40+
## Comparison extensions
41+
42+
As mentioned earlier, `NumExpr` directly does not fit in the miniscript model as it pushes a 8 byte computation result.
43+
To use these with miniscript fragments, we can use them inside comparison extensions. These comparison are of type `Bzdu`.
44+
45+
Name | Script
46+
--- | ---
47+
num_eq(NumExpr_X,NumExpr_Y) | `[NumExpr_X] [NumExpr_Y] EQUAL64`
48+
le(NumExpr_X,NumExpr_Y) | `[NumExpr_X] [NumExpr_Y] LESSTHAN64`
49+
ge(NumExpr_X,NumExpr_Y) | `[NumExpr_X] [NumExpr_Y] GREATERTHAN64`
50+
leq(NumExpr_X,NumExpr_Y) | `[NumExpr_X] [NumExpr_Y] LESSTHANOREQUAL64`
51+
geq(NumExpr_X,NumExpr_Y) | `[NumExpr_X] [NumExpr_Y] GREATERTHANOREQUAL64`
52+
53+
- For example, `num_eq(inp_v(1),mul(curr_inp_v,20))` represents second input value is the multiplication of
54+
current input value and fourth output value. This would abort if any of the values are confidential.
55+
56+
### Tx Value introspection
57+
58+
### AssetExpr
59+
60+
- pushes a 32 byte asset + 1 byte prefix on stack top. These operations also support confidential assets.
61+
- This will abort when
62+
- Supplied index is out of bounds.
63+
64+
Name | Script
65+
--- | ---
66+
`asset`(33 byte hex) | `[32-byte comm] [1 byte pref]` of this asset
67+
curr_inp_asset | `PUSHCURRENTINPUTINDEX INPSECTINPUTASSET`
68+
inp_asset(i) | `i INPSECTINPUTASSET`
69+
out_asset(i) | `i INPSECTOUTPUTASSET`
70+
71+
### ValueExpr
72+
73+
- pushes a 32 byte value(8-byte-LE value if explicit) + 1 byte prefix on stack top. These operations also support confidential values.
74+
- This will abort when
75+
- Supplied index is out of bounds.
76+
77+
Name | Script
78+
--- | ---
79+
`value`(33/9 byte hex) | `[32-byte comm/8 byte LE] [1 byte pref]` of this Value
80+
curr_inp_value | `PUSHCURRENTINPUTINDEX INPSECTINPUTVALUE`
81+
inp_value(i) | `i INPSECTINPUTVALUE`
82+
out_value(i) | `i INPSECTOUTPUTVALUE`
83+
84+
### SpkExpr: Script PubKey Expression
85+
86+
- Pushes a witness program + 1 byte witness version on stack top.
87+
- If the script pubkey is not a witness program. Push a sha256 hash of the script pubkey followed by -1 witness version
88+
- This will abort when
89+
- Supplied index is out of bounds.
90+
91+
Name | Script
92+
--- | ---
93+
`spk`(script_hex) | `[program] [witness version]` of this spk (`<Sha2Hash(Script)> <-1>`) for legacy
94+
curr_inp_spk | `PUSHCURRENTINPUTINDEX INPSECTINPUTSCRIPTPUBKEY`
95+
inp_spk(i) | `i INPSECTINPUTSCRIPTPUBKEY`
96+
out_spk(i) | `i INPSECTOUTPUTASSETSCRIPTPUBKEY`
97+
98+
## Introspection Operations
99+
100+
- `ValueExpr`, `AssetExpr` and `SpkExpr` do not fit in to the miniscript model. To use these
101+
in miniscript, we can use the below defined introspection operations. These are of type `Bzdu`
102+
- Reasoning the safety of covenants using introspection is not possible for miniscript to do as
103+
from point of view of miniscript these are anyone can spend without any signatures. However, in
104+
practice these are usually secured via cross input transactional logic beyond the current executing script.
105+
106+
Name | Script
107+
--- | ---
108+
is_exp_asset(AssetExpr_X) | `[AssetExpr_X] <1> EQUAL NIP`
109+
is_exp_value(ValueExpr_X) | `[ValueExpr_X] <1> EQUAL NIP`
110+
asset_eq(AssetExpr_X,AssetExpr_Y) | `[AssetExpr_X] TOALTSTACK [AssetExpr_Y] FROMALTSTACK EQUAL TOALTSTACK EQUAL FROMALTSTACK BOOLAND`
111+
value_eq(ValueExpr_X,ValueExpr_Y) | `[ValueExpr_X] TOALTSTACK [ValueExpr_Y] FROMALTSTACK EQUAL TOALTSTACK EQUAL FROMALTSTACK BOOLAND`
112+
spk_eq(SpkExpr_X,SpkExpr_Y) | `[SpkExpr_X] TOALTSTACK [SpkExpr_Y] FROMALTSTACK EQUAL TOALTSTACK EQUAL FROMALTSTACK BOOLAND`
113+
curr_idx_eq(i) | `<i> PUSHCURRENTINPUTINDEX EQUAL`

0 commit comments

Comments
 (0)