-
Add support for BIP389 multi-path descriptors
Using the BIP389
<M;N..>
syntax:XPUB/0/9/<0;1;2>/100
Or using standard Minsc arrays:
XPUB/0/9/[0,1,2]/100
single_descriptors()
can be used to split multi-path descriptors into an array of single descriptors. For exampleaddress(single_descriptors(wpkh(XPUB/0/<1;3;5>/100/*)).2/8)
to generate an address forXPUB/0/5/100/8
-
Add script fragment interpolation syntax
With a space-separated list of expressions enclosed in backticks. For example:
`1 2 OP_DUP OP_ADD 3 OP_EQUAL`
The data types that can be interpolated are:
Script
,Miniscript
andPolicy
(concatenated as script bytes), as well asNumber
,Bool
,PubKey
,Hash
,Duration
,DateTime
andBytes
(as PUSH operations). -
Preliminary Taproot support:
tapLeaf(Script, version=0xc0) -> Hash
(compute the TapLeaf hash of the given Script)tapBranch(Hash, Hash) -> Hash
(compute the TapBranch hash for the two given nodes)tapTweak(PubKey internal_key, Hash|Script|Array script_tree) -> Script
(tweak theinternal_key
with thescript_tree
and return the V1 witness program SPK.script_tree
can be the merkle root hash or any value accepted bytapTreeRoot
)tapTreeRoot(Script|Array tree) -> Hash
(compute the merkle root hash for the script tree. the tree can be a single Script or an Array.)
The
+
operator can be used similarly totapTweak()
. For exampleH_POINT+`OP_TRUE`
for a script-path-only with a single script.Taproot descriptors (
tr()
) are not supported yet. -
Support for CheckTemplateVerify (BIP 119) with a new
ctvHash()
function. For example:`ctvHash([ txOut($alice_pk, 10000), txOut($bob_pk, 25000) ]) OP_CTV OP_DROP`
-
Add anonymous function expressions
With a Rust-like syntax:
|params| body
or|params| { multi statement body }
-
Add if expressions (
if .. then .. else ..
) and statements (if .. { ..; } else { ..; }
) -
New
Bytes
runtime data typeConstructable using a new
0x<hex>
syntax.This can now be used in place of the
Hash
data type, which was removed. To remain compatible with the Miniscript Policy syntax for literal hashes, a Bytes value can be constructed without the0x
prefix when it is exactly 32 or 20 bytes. -
New
Script
runtime data type and new functions for working with it:script(Bytes) -> Script
(get a Script for the given raw opcode bytes. e.g.script(0xb2)
forOP_CSV
)scriptPubkey(Descriptor|TapInfo|PubKey|Address|Script) -> Script
(get the scriptPubKey to be used in the output)explicitScript(Descriptor) -> Script
(get the underlying witness script, before any hashing is done. AKA the redeemScript for P2SH)bytes(Script) -> Bytes
(get the Bytes representation of the Script opcodes)
-
New
String
runtime data type -
New
Transaction
runtime data type, constructable viatransaction()
from bytes or tagged arrays. -
New syntax for BTC amounts:
0.5 BTC
. Evaluates to the amount in satoshis. Supports all the denominations in rust-bitcoin (BTC
,mBTC
,uBTC
,bits
,satoshi
/sat
,msat
). -
Support child derivation with a hash as the child code index using Sapio's
hash_to_child_vec
conversion. For example:pub6AhbqJtv4PXnPfjiFdES7acWysWeaiCQCXeyhAh9KuEMRSNhAUHq9s3Xwu85SbXmt8wAZwpRZFQqWBstcbcvVunvATag4FbmxYYjfRcXZkp/0xd47769f0eab20cd97ad3df71d7849ed21a3c8f49c87e1742635db7d30d8a191f
-
Support Bech32/Base58 addresses format directly in source code (no quoting or explicit
address()
necessary) -
New utility functions:
len(Array|Bytes|Script) -> Number
typeof(Value) -> String
int(Float) -> Integer
float(Int) -> Float
str(Value) -> String
keys(Array) -> Array<Number>
first(Array) -> Any
last(Array) -> Any
map(Array, Function) -> Array
range(Number start, Number end) -> Array
slice(Array, Number start, Number len) -> Array
tail(Array) -> Array
initial(Array) -> Array
concat(Array, Array) -> Array
le64(Number) -> Bytes
(encode the number as 64 bit little-endian)pubkey(Bytes) -> PubKey
(cast a 32/33 long Bytes into a single PubKey)transaction(Bytes|Array) -> Transaction
repeat(Number, Function|Value) -> Array
The second parameter can be a value to fill the array with, or a function that gets called with the index to produce the value.
For example:
repeat(3, 111) == [111, 111, 111]
, or with a function:repeat(3, |$n| 100+$n) == [100, 101, 102]
. -
New function for conditionals:
iif(Bool condition, Any then_value, Any else_value)
-- useif .. then .. else ..
insteadReturns the
then_value
if the condition is true, orelse_value
otherwise.The values may be provided as thunks to be lazily-evaluated. This can be useful to avoid infinite recursion, for example:
fn S(n) = n + iif(n == 0, 0, || S(n - 1));
. -
New functions for writing Scripts:
switch(Array<(Script condition, Script body)>) -> Script
select(Array<Script body>) -> Script
unrollLoop(Number max_iterations, Script condition, Script body) -> Script
unrollFor(Number max_iterations, Script body) -> Script
rollAlt(Number) -> Script
,pickAlt(Number) -> Script
nToAlt(Number max_iterations)
,nFromAlt(Number max_iterators)
- Introspection helpers:
checkSameValue()
,checkSameAsset()
andcheckSameSpk()
(Elements only)
-
New
Bool
type, available as thetrue
andfalse
variables in the root scope -
The
Number
type can now represent floats -
New operators:
+
,-
,*
,!
,==
,!=
,<
,>
,<=
and>=
-
New constants:
MIN_NUMBER
,MAX_NUMBER
,H_POINT
(point with unknown discrete logarithm for script-path-only p2tr),LBTC
,TLBTC
-
Add support for Signet and make it the default
-
Allow using non-literal expressions as the array access index
For example:
$list.$n
or$list.(some complex expression)
-
Add support for negative numbers
-
Support child key derivation for
Policy
andMiniscript
without coercing them intoDescriptor
, as well as forArray
s containing derivable types. -
Remove the
Duration
andDateTime
runtime data types. Their syntax can still be used but get evaluated into aNumber
. -
Allow overriding the
BLOCK_INTERVAL
used forheightwise
durationsFor example,
BLOCK_INTERVAL=60
to makeheightwise 1 day
resolve as 1440 on Elements rather than 144.
-
Ported from sipa-miniscript to rust-miniscript (#1)
-
New native data types:
PubKey
,Hash
,Policy
,Miniscript
,Descriptor
,Address
andNetwork
(#2) -
New functions:
miniscript()
,wsh()
,wpkh()
,sh()
andaddress()
(#2) -
New
/
child derivation operator -
The playground was updated to support descriptors and address generation
Initial release! 💥