Expand description
Miniscript and Output Descriptors
§Bitcoin Script
In Bitcoin, spending policies are defined and enforced by means of a stack-based programming language known as Bitcoin Script. While this language appears to be designed with tractable analysis in mind (e.g. there are no looping or jumping constructions), in practice this is extremely difficult. As a result, typical wallet software supports only a small set of script templates, cannot interoperate with other similar software, and each wallet contains independently written ad-hoc manually verified code to handle these templates. Users who require more complex spending policies, or who want to combine signing infrastructure which was not explicitly designed to work together, are simply out of luck.
§Miniscript
Miniscript is an alternative to Bitcoin Script which eliminates these problems. It can be efficiently and simply encoded as Script to ensure that it works on the Bitcoin blockchain, but its design is very different. Essentially, a Miniscript is a monotone function (tree of ANDs, ORs and thresholds) of signature requirements, hash preimage requirements, and timelocks.
A full description of Miniscript is available here.
Miniscript also admits a more human-readable encoding.
§Elements Miniscript
Elements Miniscript is a fork of miniscript for elements sidechain.
§Output Descriptors
While spending policies in Bitcoin are entirely defined by Script; there are multiple ways of embedding these Scripts in transaction outputs; for example, P2SH or Segwit v0. These different embeddings are expressed by Output Descriptors, which are described here. Elements descriptors are extension of bitcoin Output descriptors with support for blinded descriptors(WIP).
§Examples
§Deriving an address from a descriptor
extern crate bitcoin;
extern crate elements;
extern crate elements_miniscript as miniscript;
use std::str::FromStr;
fn main() {
// Elements descriptors are prefixed by string el
let desc = miniscript::Descriptor::<
bitcoin::PublicKey,
>::from_str("\
elsh(wsh(or_d(\
c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),\
c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)\
)))\
").unwrap();
// Derive the P2SH address.
assert_eq!(
desc.address(&elements::AddressParams::ELEMENTS).unwrap().to_string(),
"XMyBX13qCo5Lp65mymgYVdmsYR5bcznWUa"
);
// Check whether the descriptor is safe
// This checks whether all spend paths are accessible in bitcoin network.
// It maybe possible that some of the spend require more than 100 elements in Wsh scripts
// Or they contain a combination of timelock and heightlock.
assert!(desc.sanity_check().is_ok());
// Estimate the satisfaction cost.
// scriptSig: OP_PUSH34 <OP_0 OP_32 <32-byte-hash>>
// = (1 + 1 + 1 + 32) * 4 = 140 WU
// redeemScript: varint <OP_33 <pk1> OP_CHECKSIG OP_IFDUP OP_NOTIF OP_33 <pk2> OP_CHECKSIG OP_ENDIF>
// = 1 + (1 + 33 + 1 + 1 + 1 + 1 + 33 + 1 + 1) = 74 WU
// stackItem[Sig]: varint <sig+sighash>
// = 1 + 73 = 74 WU
// Expected satisfaction weight: 140 + 74 + 74 = 288
assert_eq!(desc.max_weight_to_satisfy().unwrap(), 288);
}
Re-exports§
pub use crate::confidential::slip77;
pub use crate::confidential::Descriptor as ConfidentialDescriptor;
pub use crate::descriptor::DefiniteDescriptorKey;
pub use crate::descriptor::Descriptor;
pub use crate::descriptor::DescriptorPublicKey;
pub use crate::extensions::CovenantExt;
pub use crate::extensions::Extension;
pub use crate::extensions::NoExt;
pub use crate::extensions::TxEnv;
pub use crate::interpreter::Interpreter;
pub use crate::miniscript::analyzable::AnalysisError;
pub use crate::miniscript::analyzable::ExtParams;
pub use crate::miniscript::decode::Terminal;
pub use crate::miniscript::satisfy::elementssig_from_rawsig;
pub use crate::miniscript::satisfy::elementssig_to_rawsig;
pub use crate::miniscript::satisfy::ElementsSig;
pub use crate::miniscript::satisfy::Preimage32;
pub use crate::miniscript::satisfy::Satisfier;
pub use crate::miniscript::Miniscript;
pub use bitcoin;
pub use elements;
Modules§
- confidential
- Confidential Descriptors
- descriptor
- Output Descriptors
- expression
- Function-like Expression Language
- extensions
- Extensions to elements-miniscript
Users should implement the
Extension
trait to extend miniscript to have newer leaf nodes Look at examples for implementation of ver_eq fragment - hash256
- Provides a Double SHA256
Hash
type that displays forwards. - interpreter
- Interpreter
- miniscript
- Abstract Syntax Tree
- policy
- Script Policies
- psbt
- Partially-Signed Bitcoin Transactions
Macros§
- translate_
hash_ clone - Macro for translation of associated types where the associated type is the same Handy for Derived -> concrete keys where the associated types are the same.
- translate_
hash_ fail - Macro for failing translation for other associated types. Handy for testing String -> concrete keys as we don’t want to specify these functions repeatedly.
Structs§
- AbsLock
Time - An absolute locktime that implements
Ord
. - BtcMiniscript
- The top-level miniscript abstract syntax tree (AST).
Enums§
- BareCtx
- Bare ScriptContext To be used as raw script pubkeys In general, it is not recommended to use Bare descriptors as they as strongly limited by standardness policies.
- BtcDescriptor
- Script descriptor
- BtcError
- Miniscript
- BtcSegwitv0
- Segwitv0 ScriptContext
- BtcTerminal
- All AST elements.
- Error
- Miniscript Error
- Legacy
- Legacy ScriptContext
To be used as P2SH scripts
For creation of Bare scriptpubkeys, construct the Miniscript
under
Bare
ScriptContext - Segwitv0
- Segwitv0 ScriptContext
- SigType
- Signature algorithm type
- Tap
- Tap ScriptContext
Traits§
- BtcSatisfier
- Trait describing a lookup table for signatures, hash preimages, etc.
Every method has a default implementation that simply returns
None
on every query. Users are expected to override the methods that they have data for. - ExtTranslator
- Trait for translation Extensions
- ForEach
Key - Either a key or keyhash, but both contain Pk Trait describing the ability to iterate over every key
- Miniscript
Key - Public key trait which can be converted to Hash type
- Script
Context - The ScriptContext for Miniscript. Additional type information associated with miniscript that is used for carrying out checks that dependent on the context under which the script is used. For example, disallowing uncompressed keys in Segwit context
- ToPublic
Key - Trait describing public key types which can be converted to bitcoin pubkeys
- Translate
Ext - Converts a descriptor using abstract keys to one using specific keys. Uses translator
t
to do the actual translation function calls. - Translate
Pk - Converts a descriptor using abstract keys to one using specific keys. Uses translator
t
to do the actual translation function calls. - Translator
- Describes an object that can translate various keys and hashes from one key to the type
associated with the other key. Used by the
TranslatePk
trait to do the actual translations.
Functions§
- script_
num_ size - The size of an encoding of a number in Script
- tweak_
key - Tweak a MiniscriptKey to obtain the tweaked key