Skip to content

Commit b3e88cd

Browse files
committed
[MOVE ONLY] covenants: move ExtParams to its own module
Right now ExtParams and Ext are together in one module, and are confused in places. My goal here is to isolate ExtParams within the extension module as much as possible and have users mostly just deal with Ext. Of course, to convert between CovenantExt<A> and CovenantExt<B> they will need to deal with ExtParam, but we will expose that in a narrow sense rather than having Descriptor<ExtParam> and a "TranslateExt" trait that actually manipulates ExtParams. Re-exports things in their own locations to minimize disruption to the rest of the crate. At the end of this PR we will fix all the export paths.
1 parent 240b0c5 commit b3e88cd

File tree

2 files changed

+182
-168
lines changed

2 files changed

+182
-168
lines changed

src/extensions/mod.rs

Lines changed: 4 additions & 168 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,8 @@
44
55
use std::{fmt, hash};
66

7-
use bitcoin::hashes::hex::ToHex;
8-
use elements::encode::serialize;
97
use elements::script::Builder;
10-
use elements::{confidential, Transaction, TxOut};
8+
use elements::{Transaction, TxOut};
119

1210
use crate::expression::Tree;
1311
use crate::interpreter::{self, Stack};
@@ -23,35 +21,17 @@ mod arith;
2321
mod csfs;
2422
mod introspect_ops;
2523
mod outputs_pref;
24+
pub mod param;
2625
mod tx_ver;
2726

2827
pub use arith::{Arith, EvalError, Expr, ExprInner};
2928
pub use csfs::{CheckSigFromStack, CsfsKey, CsfsMsg};
30-
pub use introspect_ops::{AssetExpr, CovOps, SpkExpr, ValueExpr};
29+
pub use introspect_ops::{AssetExpr, CovOps, Spk, SpkExpr, ValueExpr};
3130

32-
use self::introspect_ops::Spk;
3331
pub use self::outputs_pref::LegacyOutputsPref;
32+
pub use self::param::{ArgFromStr, CovExtArgs, ExtParam, NoExtParam};
3433
pub use self::tx_ver::LegacyVerEq;
3534

36-
/// Trait for parsing extension arg from String
37-
/// Parse an argument from `s` given context of parent and argument position
38-
///
39-
/// When parsing all allowed parameters from string, we need to restrict where
40-
/// the parameters can be allowed. For example, csfs() should not have a txout
41-
/// parameter.
42-
///
43-
/// All parameters that should be parsed from extensions need to implement this
44-
pub trait ArgFromStr: Sized {
45-
/// Parse an argument from `s` given context of parent and argument position
46-
fn arg_from_str(s: &str, parent: &str, pos: usize) -> Result<Self, Error>;
47-
}
48-
/// Abstract parameter to Miniscript Extension
49-
pub trait ExtParam: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash + ArgFromStr {}
50-
51-
impl<T> ExtParam for T where
52-
T: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash + ArgFromStr
53-
{
54-
}
5535

5636
/// Extensions to elements-miniscript.
5737
/// Refer to implementations(unimplemented!) for example and tutorials
@@ -138,24 +118,6 @@ pub trait ParseableExt:
138118
S: Satisfier<Pk>;
139119
}
140120

141-
/// No Extensions for elements-miniscript
142-
/// All the implementations for the this function are unreachable
143-
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
144-
pub enum NoExtParam {}
145-
146-
impl fmt::Display for NoExtParam {
147-
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
148-
match *self {}
149-
}
150-
}
151-
152-
impl ArgFromStr for NoExtParam {
153-
fn arg_from_str(_s: &str, _parent: &str, _pos: usize) -> Result<Self, Error> {
154-
// This will be removed in a followup commit
155-
unreachable!("Called ArgFromStr for NoExt")
156-
}
157-
}
158-
159121
/// No Extensions for elements-miniscript
160122
/// All the implementations for the this function are unreachable
161123
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
@@ -263,132 +225,6 @@ pub enum CovenantExt<T: ExtParam> {
263225
Introspect(CovOps<T>),
264226
}
265227

266-
/// All known Extension parameters/arguments
267-
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
268-
pub enum CovExtArgs {
269-
/// XOnlyPublicKey (in CSFS)
270-
XOnlyKey(CsfsKey),
271-
/// Message
272-
CsfsMsg(CsfsMsg),
273-
/// Asset
274-
Asset(confidential::Asset),
275-
/// Value
276-
Value(confidential::Value),
277-
/// Script
278-
Script(Spk),
279-
}
280-
281-
impl From<CsfsMsg> for CovExtArgs {
282-
fn from(v: CsfsMsg) -> Self {
283-
Self::CsfsMsg(v)
284-
}
285-
}
286-
287-
impl From<Spk> for CovExtArgs {
288-
fn from(v: Spk) -> Self {
289-
Self::Script(v)
290-
}
291-
}
292-
293-
impl From<confidential::Value> for CovExtArgs {
294-
fn from(v: confidential::Value) -> Self {
295-
Self::Value(v)
296-
}
297-
}
298-
299-
impl From<confidential::Asset> for CovExtArgs {
300-
fn from(v: confidential::Asset) -> Self {
301-
Self::Asset(v)
302-
}
303-
}
304-
305-
impl From<CsfsKey> for CovExtArgs {
306-
fn from(v: CsfsKey) -> Self {
307-
Self::XOnlyKey(v)
308-
}
309-
}
310-
311-
impl CovExtArgs {
312-
/// Creates a new csfs key variant of [`CovExtArgs`]
313-
pub fn csfs_key(key: bitcoin::XOnlyPublicKey) -> Self {
314-
CovExtArgs::XOnlyKey(CsfsKey(key))
315-
}
316-
317-
/// Creates a csfs message variant of [`CovExtArgs`]
318-
pub fn csfs_msg(msg: elements::secp256k1_zkp::Message) -> Self {
319-
CovExtArgs::CsfsMsg(CsfsMsg::new(msg.as_ref().to_vec()).expect("32 byte size message"))
320-
}
321-
322-
/// Creates a new asset variant of [`CovExtArgs`]
323-
pub fn asset(asset: confidential::Asset) -> Self {
324-
Self::from(asset)
325-
}
326-
327-
/// Creates a new value variant of [`CovExtArgs`]
328-
pub fn value(value: confidential::Value) -> Self {
329-
Self::from(value)
330-
}
331-
332-
/// Creates a new script pubkey of [`CovExtArgs`]
333-
pub fn spk(spk: elements::Script) -> Self {
334-
Self::from(Spk(spk))
335-
}
336-
}
337-
338-
impl PartialOrd for CovExtArgs {
339-
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
340-
// HACKY implementation, need Ord/PartialOrd to make it work with other components
341-
// in the library
342-
self.to_string().partial_cmp(&other.to_string())
343-
}
344-
}
345-
346-
impl Ord for CovExtArgs {
347-
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
348-
// HACKY implementation, need Ord/PartialOrd to make it work with other components
349-
// in the library
350-
self.to_string().cmp(&other.to_string())
351-
}
352-
}
353-
354-
impl fmt::Display for CovExtArgs {
355-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
356-
match self {
357-
CovExtArgs::XOnlyKey(x) => write!(f, "{}", x),
358-
CovExtArgs::CsfsMsg(m) => write!(f, "{}", m),
359-
CovExtArgs::Asset(a) => write!(f, "{}", serialize(a).to_hex()),
360-
CovExtArgs::Value(v) => write!(f, "{}", serialize(v).to_hex()),
361-
CovExtArgs::Script(s) => write!(f, "{}", s),
362-
}
363-
}
364-
}
365-
366-
impl ArgFromStr for CovExtArgs {
367-
fn arg_from_str(s: &str, parent: &str, pos: usize) -> Result<Self, Error> {
368-
let arg = match (parent, pos) {
369-
("csfs", 0) => CovExtArgs::XOnlyKey(CsfsKey::arg_from_str(s, parent, pos)?),
370-
("csfs", 1) => CovExtArgs::CsfsMsg(CsfsMsg::arg_from_str(s, parent, pos)?),
371-
("asset_eq", 0) | ("asset_eq", 1) | ("is_exp_asset", 0) => {
372-
CovExtArgs::Asset(confidential::Asset::arg_from_str(s, parent, pos)?)
373-
}
374-
("value_eq", 0) | ("value_eq", 1) | ("is_exp_value", 0) => {
375-
CovExtArgs::Value(confidential::Value::arg_from_str(s, parent, pos)?)
376-
}
377-
("spk_eq", 0) | ("spk_eq", 1) => CovExtArgs::Script(Spk::arg_from_str(s, parent, pos)?),
378-
_ => return Err(Error::Unexpected(s.to_string())),
379-
};
380-
Ok(arg)
381-
}
382-
}
383-
384-
impl ArgFromStr for String {
385-
fn arg_from_str(s: &str, _parent: &str, _pos: usize) -> Result<Self, Error> {
386-
// Abstract strings are parsed without context as they don't contain any concrete
387-
// information
388-
Ok(String::from(s))
389-
}
390-
}
391-
392228
// Apply the function on each arm
393229
macro_rules! all_arms_fn {
394230
($slf: ident, $trt: ident, $f: ident, $($args:ident, )* ) => {

src/extensions/param.rs

Lines changed: 178 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,178 @@
1+
//! Parameters to certain covenants
2+
3+
use std::{hash, fmt};
4+
5+
use bitcoin::hashes::hex::ToHex;
6+
use elements::confidential;
7+
use elements::encode::serialize;
8+
9+
use crate::Error;
10+
use super::csfs::{CsfsKey, CsfsMsg};
11+
use super::introspect_ops::Spk;
12+
13+
/// Trait for parsing extension arg from String
14+
/// Parse an argument from `s` given context of parent and argument position
15+
///
16+
/// When parsing all allowed parameters from string, we need to restrict where
17+
/// the parameters can be allowed. For example, csfs() should not have a txout
18+
/// parameter.
19+
///
20+
/// All parameters that should be parsed from extensions need to implement this
21+
pub trait ArgFromStr: Sized {
22+
/// Parse an argument from `s` given context of parent and argument position
23+
fn arg_from_str(s: &str, parent: &str, pos: usize) -> Result<Self, Error>;
24+
}
25+
26+
/// Abstract parameter to Miniscript Extension
27+
pub trait ExtParam: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash + ArgFromStr {}
28+
29+
impl<T> ExtParam for T where
30+
T: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash + ArgFromStr
31+
{
32+
}
33+
34+
impl ArgFromStr for String {
35+
fn arg_from_str(s: &str, _parent: &str, _pos: usize) -> Result<Self, Error> {
36+
// Abstract strings are parsed without context as they don't contain any concrete
37+
// information
38+
Ok(String::from(s))
39+
}
40+
}
41+
42+
43+
/// No Extensions for elements-miniscript
44+
/// All the implementations for the this function are unreachable
45+
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)]
46+
pub enum NoExtParam {}
47+
48+
impl fmt::Display for NoExtParam {
49+
fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
50+
match *self {}
51+
}
52+
}
53+
54+
impl ArgFromStr for NoExtParam {
55+
fn arg_from_str(_s: &str, _parent: &str, _pos: usize) -> Result<Self, Error> {
56+
// This will be removed in a followup commit
57+
unreachable!("Called ArgFromStr for NoExt")
58+
}
59+
}
60+
61+
/// All known Extension parameters/arguments
62+
#[derive(Debug, PartialEq, Eq, Clone, Hash)]
63+
pub enum CovExtArgs {
64+
/// XOnlyPublicKey (in CSFS)
65+
XOnlyKey(CsfsKey),
66+
/// Message
67+
CsfsMsg(CsfsMsg),
68+
/// Asset
69+
Asset(confidential::Asset),
70+
/// Value
71+
Value(confidential::Value),
72+
/// Script
73+
Script(Spk),
74+
}
75+
76+
impl From<CsfsMsg> for CovExtArgs {
77+
fn from(v: CsfsMsg) -> Self {
78+
Self::CsfsMsg(v)
79+
}
80+
}
81+
82+
impl From<Spk> for CovExtArgs {
83+
fn from(v: Spk) -> Self {
84+
Self::Script(v)
85+
}
86+
}
87+
88+
impl From<confidential::Value> for CovExtArgs {
89+
fn from(v: confidential::Value) -> Self {
90+
Self::Value(v)
91+
}
92+
}
93+
94+
impl From<confidential::Asset> for CovExtArgs {
95+
fn from(v: confidential::Asset) -> Self {
96+
Self::Asset(v)
97+
}
98+
}
99+
100+
impl From<CsfsKey> for CovExtArgs {
101+
fn from(v: CsfsKey) -> Self {
102+
Self::XOnlyKey(v)
103+
}
104+
}
105+
106+
impl CovExtArgs {
107+
/// Creates a new csfs key variant of [`CovExtArgs`]
108+
pub fn csfs_key(key: bitcoin::XOnlyPublicKey) -> Self {
109+
CovExtArgs::XOnlyKey(CsfsKey(key))
110+
}
111+
112+
/// Creates a csfs message variant of [`CovExtArgs`]
113+
pub fn csfs_msg(msg: elements::secp256k1_zkp::Message) -> Self {
114+
CovExtArgs::CsfsMsg(CsfsMsg::new(msg.as_ref().to_vec()).expect("32 byte size message"))
115+
}
116+
117+
/// Creates a new asset variant of [`CovExtArgs`]
118+
pub fn asset(asset: confidential::Asset) -> Self {
119+
Self::from(asset)
120+
}
121+
122+
/// Creates a new value variant of [`CovExtArgs`]
123+
pub fn value(value: confidential::Value) -> Self {
124+
Self::from(value)
125+
}
126+
127+
/// Creates a new script pubkey of [`CovExtArgs`]
128+
pub fn spk(spk: elements::Script) -> Self {
129+
Self::from(Spk(spk))
130+
}
131+
}
132+
133+
impl PartialOrd for CovExtArgs {
134+
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
135+
// HACKY implementation, need Ord/PartialOrd to make it work with other components
136+
// in the library
137+
self.to_string().partial_cmp(&other.to_string())
138+
}
139+
}
140+
141+
impl Ord for CovExtArgs {
142+
fn cmp(&self, other: &Self) -> std::cmp::Ordering {
143+
// HACKY implementation, need Ord/PartialOrd to make it work with other components
144+
// in the library
145+
self.to_string().cmp(&other.to_string())
146+
}
147+
}
148+
149+
impl fmt::Display for CovExtArgs {
150+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
151+
match self {
152+
CovExtArgs::XOnlyKey(x) => write!(f, "{}", x),
153+
CovExtArgs::CsfsMsg(m) => write!(f, "{}", m),
154+
CovExtArgs::Asset(a) => write!(f, "{}", serialize(a).to_hex()),
155+
CovExtArgs::Value(v) => write!(f, "{}", serialize(v).to_hex()),
156+
CovExtArgs::Script(s) => write!(f, "{}", s),
157+
}
158+
}
159+
}
160+
161+
impl ArgFromStr for CovExtArgs {
162+
fn arg_from_str(s: &str, parent: &str, pos: usize) -> Result<Self, Error> {
163+
let arg = match (parent, pos) {
164+
("csfs", 0) => CovExtArgs::XOnlyKey(CsfsKey::arg_from_str(s, parent, pos)?),
165+
("csfs", 1) => CovExtArgs::CsfsMsg(CsfsMsg::arg_from_str(s, parent, pos)?),
166+
("asset_eq", 0) | ("asset_eq", 1) | ("is_exp_asset", 0) => {
167+
CovExtArgs::Asset(confidential::Asset::arg_from_str(s, parent, pos)?)
168+
}
169+
("value_eq", 0) | ("value_eq", 1) | ("is_exp_value", 0) => {
170+
CovExtArgs::Value(confidential::Value::arg_from_str(s, parent, pos)?)
171+
}
172+
("spk_eq", 0) | ("spk_eq", 1) => CovExtArgs::Script(Spk::arg_from_str(s, parent, pos)?),
173+
_ => return Err(Error::Unexpected(s.to_string())),
174+
};
175+
Ok(arg)
176+
}
177+
}
178+

0 commit comments

Comments
 (0)