simplicity/node/
mod.rs

1// SPDX-License-Identifier: CC0-1.0
2
3//! Simplicity Program Nodes
4//!
5//! The types in this module are used to represent Simplicity expressions as
6//! DAGs. The nodes of this DAG are individual combinators along with some
7//! cached data about the node, which depends on the specific node type.
8//!
9//! All nodes represent the root of an expression. Expressions whose source
10//! and target types are both unit are called "programs". Generally speaking,
11//! any nodes that users hold directly will be programs.
12//!
13//! There are three main node types:
14//!
15//! 1. [`crate::RedeemNode`] represents a Simplicity node as it exists on the blockchain.
16//!    Every witness node is populated with a correctly-typed [`Value`], every
17//!    disconnect node has a child, every non-executed branch of a `case` combinator
18//!    is pruned, and there is nothing you can do to modify the expression.
19//!
20//!    `RedeemNode`s can be executed on the bit machine and have complete types
21//!    and resource bounds, and can be serialized in the consensus bit-encoding.
22//!
23//! 2. [`CommitNode`] represents a Simplicity node as it is *committed to* on
24//!    the blockchain. This means that witness and (TODO) disconnect nodes are not
25//!    populated, but type inference is complete and resource bounds are
26//!    available. `case` combinators may have pruned children (in which case they
27//!    are instead considered `assertl` or `assertr` combinators), or not.
28//!
29//!    There is a bit-encoding for `CommitNode`s which is essentially only used
30//!    by this library. It consists of the bit-encoding.of the combinators, fully
31//!    shared *except* that witness and disconnect nodes (and their ancestors)
32//!    are unshared. No witness data is included.
33//!
34//!    TODO there is also a human-readable encoding.
35//!
36//! 3. [`ConstructNode`] represents an "under-construction" Simplicity expression.
37//!    These nodes' types are not necessarily complete, and are inferred as the
38//!    program is constructed. This is the only node that you can programmatically
39//!    construct. It has no encoding, human-readable or bitwise, and is intended
40//!    to exist only ephemerally.
41//!
42//! The following conversions are possible between the node types:
43//!
44//! 1. [`ConstructNode::finalize_types`] converts a [`ConstructNode`] to a
45//!    [`CommitNode`] by setting any free variables, as well as the source and
46//!    target of the root node, to unit.
47//!
48//!    This conversion requires no input from the user but may fail with a type
49//!    error, in case of infinitely-sized types or in the case that the unit
50//!    bounds cannot be applied.
51//!
52//! 2. [`CommitNode::finalize`] converts a [`CommitNode`] to a [`RedeemNode`]
53//!    by attaching witnesses to each witness node, and deciding whether to hide
54//!    branches for each `case` node.
55//!
56//! 3. [`CommitNode::unfinalize_types`] converts a [`CommitNode`] to a
57//!    [`ConstructNode`] by throwing away all types and re-inferring them. It
58//!    cannot fail.
59//!
60//! 4. [`RedeemNode::unfinalize`] converts a [`RedeemNode`] to a [`CommitNode`]
61//!    by throwing away witness and (TODO) disconnect data. It cannot recover
62//!    pruned branches so is of limited usefulness, but it is included for
63//!    completeness.
64//!
65
66use crate::dag::{DagLike, MaxSharing, SharingTracker};
67use crate::encode;
68use crate::jet::Jet;
69use crate::{types, BitWriter, Cmr, FailEntropy, HasCmr, Value};
70
71use std::sync::Arc;
72use std::{fmt, hash, io};
73
74mod commit;
75mod construct;
76mod convert;
77mod disconnect;
78mod display;
79mod hiding;
80mod inner;
81mod redeem;
82
83use crate::value::Word;
84pub use commit::{Commit, CommitData, CommitNode};
85pub use construct::{Construct, ConstructData, ConstructNode};
86pub use convert::{Converter, Hide, SimpleFinalizer};
87pub use disconnect::{Disconnectable, NoDisconnect};
88pub use display::{Display, DisplayExpr};
89pub use hiding::Hiding;
90pub use inner::Inner;
91pub use redeem::{Redeem, RedeemData, RedeemNode};
92
93// This trait should only be implemented on empty types, so we can demand
94// every trait bound under the sun. Doing so will make #[derive]s easier
95// for downstream users.
96pub trait Marker:
97    Copy + Clone + PartialEq + Eq + PartialOrd + Ord + fmt::Debug + hash::Hash
98{
99    /// Precomputed data about the node, such as its type arrow or various Merkle roots.
100    type CachedData: Clone;
101
102    /// Type of witness data attached to DAGs of this node type. Typically either [`Value`]
103    /// or [`NoWitness`].
104    type Witness: Clone;
105
106    /// Type of disconnect data attached to DAGs of this node type.
107    type Disconnect: Disconnectable<Node<Self>> + Clone;
108
109    /// A type which uniquely identifies a node, for purposes of sharing
110    /// during iteration over the DAG.
111    type SharingId: hash::Hash + Clone + Eq;
112
113    /// The jet catalogue used with this node type.
114    type Jet: Jet;
115
116    /// Yields the sharing ID for a given type, starting from its CMR and its cached data.
117    ///
118    /// If the type cannot be uniquely identified (e.g. because it is missing data), then
119    /// this method returns `None`. In this case, the node will not be shared with any
120    /// other node.
121    fn compute_sharing_id(cmr: Cmr, cached_data: &Self::CachedData) -> Option<Self::SharingId>;
122}
123
124/// Null data type used as dummy for [`Marker::Witness`]
125#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
126pub struct NoWitness;
127
128impl From<NoWitness> for Option<Value> {
129    fn from(_: NoWitness) -> Self {
130        None
131    }
132}
133
134pub trait Constructible<'brand, J, X, W>:
135    JetConstructible<'brand, J>
136    + DisconnectConstructible<'brand, X>
137    + WitnessConstructible<'brand, W>
138    + CoreConstructible<'brand>
139    + Sized
140{
141    fn from_inner(
142        inference_context: &types::Context<'brand>,
143        inner: Inner<&Self, J, &X, W>,
144    ) -> Result<Self, types::Error> {
145        match inner {
146            Inner::Iden => Ok(Self::iden(inference_context)),
147            Inner::Unit => Ok(Self::unit(inference_context)),
148            Inner::InjL(child) => Ok(Self::injl(child)),
149            Inner::InjR(child) => Ok(Self::injr(child)),
150            Inner::Take(child) => Ok(Self::take(child)),
151            Inner::Drop(child) => Ok(Self::drop_(child)),
152            Inner::Comp(left, right) => Self::comp(left, right),
153            Inner::Case(left, right) => Self::case(left, right),
154            Inner::AssertL(left, r_cmr) => Self::assertl(left, r_cmr),
155            Inner::AssertR(l_cmr, right) => Self::assertr(l_cmr, right),
156            Inner::Pair(left, right) => Self::pair(left, right),
157            Inner::Disconnect(left, right) => Self::disconnect(left, right),
158            Inner::Fail(entropy) => Ok(Self::fail(inference_context, entropy)),
159            Inner::Word(ref w) => Ok(Self::const_word(inference_context, w.shallow_clone())),
160            Inner::Jet(j) => Ok(Self::jet(inference_context, j)),
161            Inner::Witness(w) => Ok(Self::witness(inference_context, w)),
162        }
163    }
164}
165
166impl<'brand, J, X, W, T> Constructible<'brand, J, X, W> for T where
167    T: DisconnectConstructible<'brand, X>
168        + JetConstructible<'brand, J>
169        + WitnessConstructible<'brand, W>
170        + CoreConstructible<'brand>
171        + Sized
172{
173}
174
175pub trait CoreConstructible<'brand>: Sized {
176    fn iden(inference_context: &types::Context<'brand>) -> Self;
177    fn unit(inference_context: &types::Context<'brand>) -> Self;
178    fn injl(child: &Self) -> Self;
179    fn injr(child: &Self) -> Self;
180    fn take(child: &Self) -> Self;
181    fn drop_(child: &Self) -> Self;
182    fn comp(left: &Self, right: &Self) -> Result<Self, types::Error>;
183    fn case(left: &Self, right: &Self) -> Result<Self, types::Error>;
184    fn assertl(left: &Self, right: Cmr) -> Result<Self, types::Error>;
185    fn assertr(left: Cmr, right: &Self) -> Result<Self, types::Error>;
186    fn pair(left: &Self, right: &Self) -> Result<Self, types::Error>;
187    fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self;
188    fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self;
189
190    /// Accessor for the type inference context used to create the object.
191    fn inference_context(&self) -> &types::Context<'brand>;
192
193    /// Create an expression that produces the given `value`.
194    ///
195    /// The expression is minimized by using as many word jets as possible.
196    fn scribe(ctx: &types::Context<'brand>, value: &Value) -> Self {
197        use crate::value::ValueRef;
198
199        #[derive(Debug, Clone)]
200        enum Task<'v> {
201            Process(ValueRef<'v>),
202            MakeLeft,
203            MakeRight,
204            MakeProduct,
205        }
206
207        let mut input = vec![Task::Process(value.as_ref())];
208        let mut output = vec![];
209        while let Some(top) = input.pop() {
210            match top {
211                Task::Process(value) => {
212                    if value.is_unit() {
213                        output.push(Self::unit(ctx));
214                    } else if let Some(word) = value.to_word() {
215                        output.push(Self::const_word(ctx, word));
216                    } else if let Some(left) = value.as_left() {
217                        input.push(Task::MakeLeft);
218                        input.push(Task::Process(left));
219                    } else if let Some(right) = value.as_right() {
220                        input.push(Task::MakeRight);
221                        input.push(Task::Process(right));
222                    } else if let Some((left, right)) = value.as_product() {
223                        input.push(Task::MakeProduct);
224                        input.push(Task::Process(right));
225                        input.push(Task::Process(left));
226                    }
227                }
228                Task::MakeLeft => {
229                    let inner = output.pop().unwrap();
230                    output.push(Self::injl(&inner));
231                }
232                Task::MakeRight => {
233                    let inner = output.pop().unwrap();
234                    output.push(Self::injr(&inner));
235                }
236                Task::MakeProduct => {
237                    let right = output.pop().unwrap();
238                    let left = output.pop().unwrap();
239                    // simfony::PairBuilder would remove this `.expect()` call
240                    output.push(
241                        Self::pair(&left, &right).expect(
242                            "`pair` should always succeed because input type is unrestricted",
243                        ),
244                    );
245                }
246            }
247        }
248        debug_assert_eq!(output.len(), 1);
249        output.pop().unwrap()
250    }
251
252    /// Create a DAG that takes any input and returns bit `0` as constant output.
253    ///
254    /// _Overall type: A → 2_
255    fn bit_false(inference_context: &types::Context<'brand>) -> Self {
256        let unit = Self::unit(inference_context);
257        Self::injl(&unit)
258    }
259
260    /// Create a DAG that takes any input and returns bit `1` as constant output.
261    ///
262    /// _Overall type: A → 2_
263    fn bit_true(inference_context: &types::Context<'brand>) -> Self {
264        let unit = Self::unit(inference_context);
265        Self::injr(&unit)
266    }
267
268    /// Create a DAG that takes a bit and an input,
269    /// such that the `left` child is evaluated on the input if the bit is `1` _(if branch)_
270    /// and the `right` child is evaluated on the input otherwise _(else branch)_.
271    ///
272    /// _Overall type: 2 × A → B where `left`: A → B and `right`: A → B_
273    ///
274    /// _Type inference will fail if children are not of the correct type._
275    fn cond(left: &Self, right: &Self) -> Result<Self, types::Error> {
276        let drop_left = Self::drop_(left);
277        let drop_right = Self::drop_(right);
278        Self::case(&drop_right, &drop_left)
279    }
280
281    /// Create a DAG that asserts that its child returns `true`, and fails otherwise.
282    /// The `hash` identifies the assertion and is returned upon failure.
283    ///
284    /// _Overall type: A → 1 where `child`: A → 2_
285    ///
286    /// _Type inference will fail if children are not of the correct type._
287    fn assert(child: &Self, hash: Cmr) -> Result<Self, types::Error> {
288        let unit = Self::unit(child.inference_context());
289        let pair_child_unit = Self::pair(child, &unit)?;
290        let assertr_hidden_unit = Self::assertr(hash, &unit)?;
291
292        Self::comp(&pair_child_unit, &assertr_hidden_unit)
293    }
294
295    /// Create a DAG that computes Boolean _NOT_ of the `child`.
296    ///
297    /// _Overall type: A → 2 where `child`: A → 2_
298    ///
299    /// _Type inference will fail if children are not of the correct type._
300    #[allow(clippy::should_implement_trait)]
301    fn not(child: &Self) -> Result<Self, types::Error> {
302        let unit = Self::unit(child.inference_context());
303        let pair_child_unit = Self::pair(child, &unit)?;
304        let bit_true = Self::bit_true(child.inference_context());
305        let bit_false = Self::bit_false(child.inference_context());
306        let case_true_false = Self::case(&bit_true, &bit_false)?;
307
308        Self::comp(&pair_child_unit, &case_true_false)
309    }
310
311    /// Create a DAG that computes Boolean _AND_ of the `left` and `right` child.
312    ///
313    /// _Overall type: A → 2 where `left`: A → 2 and `right`: A → 2_
314    ///
315    /// _Type inference will fail if children are not of the correct type._
316    fn and(left: &Self, right: &Self) -> Result<Self, types::Error> {
317        left.inference_context()
318            .check_eq(right.inference_context())?;
319        let iden = Self::iden(left.inference_context());
320        let pair_left_iden = Self::pair(left, &iden)?;
321        let bit_false = Self::bit_false(left.inference_context());
322        let drop_right = Self::drop_(right);
323        let case_false_right = Self::case(&bit_false, &drop_right)?;
324
325        Self::comp(&pair_left_iden, &case_false_right)
326    }
327
328    /// Create a DAG that computes Boolean _OR_ of the `left` and `right`.
329    ///
330    /// _Overall type: A → 2 where `left`: A → 2 and `right`: A → 2_
331    ///
332    /// _Type inference will fail if children are not of the correct type._
333    fn or(left: &Self, right: &Self) -> Result<Self, types::Error> {
334        left.inference_context()
335            .check_eq(right.inference_context())?;
336        let iden = Self::iden(left.inference_context());
337        let pair_left_iden = Self::pair(left, &iden)?;
338        let drop_right = Self::drop_(right);
339        let bit_true = Self::bit_true(left.inference_context());
340        let case_right_true = Self::case(&drop_right, &bit_true)?;
341
342        Self::comp(&pair_left_iden, &case_right_true)
343    }
344}
345
346pub trait DisconnectConstructible<'brand, X>: Sized {
347    fn disconnect(left: &Self, right: &X) -> Result<Self, types::Error>;
348}
349
350pub trait JetConstructible<'brand, J>: Sized {
351    fn jet(inference_context: &types::Context<'brand>, jet: J) -> Self;
352}
353
354pub trait WitnessConstructible<'brand, W>: Sized {
355    fn witness(inference_context: &types::Context<'brand>, witness: W) -> Self;
356}
357
358/// A node in a Simplicity expression.
359///
360/// There are three node types provided by this library: `ConstructNode`, `CommitNode`,
361/// and `RedeemNode`, which represent Simplicty programs during construction, at
362/// commitment time, and at redemption time, respectively.
363///
364/// This generic structure is used to define conversions and mapping functions over
365/// nodes and DAGs, and allows users to define their own custom node types.
366///
367/// For equality and hashing purposes, nodes are characterized entirely by their
368/// CMR and cached data. Users who create custom nodes should define a custom type
369/// for [`Marker::CachedData`] and think carefully about whether and how to
370/// implement the [`std::hash::Hash`] or equality traits.
371pub struct Node<N: Marker> {
372    inner: Inner<Arc<Node<N>>, N::Jet, N::Disconnect, N::Witness>,
373    cmr: Cmr,
374    data: N::CachedData,
375}
376
377impl<N: Marker> PartialEq for Node<N>
378where
379    N::CachedData: PartialEq,
380{
381    fn eq(&self, other: &Self) -> bool {
382        self.cmr == other.cmr && self.data == other.data
383    }
384}
385impl<N: Marker> Eq for Node<N> where N::CachedData: Eq {}
386
387impl<N: Marker> hash::Hash for Node<N>
388where
389    N::CachedData: hash::Hash,
390{
391    fn hash<H: hash::Hasher>(&self, h: &mut H) {
392        self.cmr.hash(h);
393        self.data.hash(h);
394    }
395}
396
397impl<N: Marker> fmt::Debug for Node<N>
398where
399    for<'a> &'a Node<N>: DagLike,
400{
401    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402        self.post_order_iter::<MaxSharing<N>>().into_display(
403            f,
404            |node, f| fmt::Display::fmt(&node.inner, f),
405            |_, _| Ok(()),
406        )
407    }
408}
409
410#[cfg(feature = "base64")]
411impl<N: Marker> fmt::Display for Node<N> {
412    /// Displays the program data in base64.
413    ///
414    /// If you need witness data as well, then use [`Node::display`].
415    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416        use crate::base64::display::Base64Display;
417        use crate::base64::engine::general_purpose;
418
419        let v = self.to_vec_without_witness();
420        Base64Display::new(&v, &general_purpose::STANDARD).fmt(f)
421    }
422}
423
424impl<N: Marker> HasCmr for Node<N> {
425    fn cmr(&self) -> Cmr {
426        self.cmr
427    }
428}
429
430impl<N: Marker> HasCmr for Arc<Node<N>> {
431    fn cmr(&self) -> Cmr {
432        self.cmr
433    }
434}
435
436impl<'brand, N> CoreConstructible<'brand> for Arc<Node<N>>
437where
438    N: Marker,
439    N::CachedData: CoreConstructible<'brand>,
440{
441    fn iden(inference_context: &types::Context<'brand>) -> Self {
442        Arc::new(Node {
443            cmr: Cmr::iden(),
444            data: N::CachedData::iden(inference_context),
445            inner: Inner::Iden,
446        })
447    }
448
449    fn unit(inference_context: &types::Context<'brand>) -> Self {
450        Arc::new(Node {
451            cmr: Cmr::unit(),
452            data: N::CachedData::unit(inference_context),
453            inner: Inner::Unit,
454        })
455    }
456
457    fn injl(child: &Self) -> Self {
458        Arc::new(Node {
459            cmr: Cmr::injl(child.cmr()),
460            data: N::CachedData::injl(&child.data),
461            inner: Inner::InjL(Arc::clone(child)),
462        })
463    }
464
465    fn injr(child: &Self) -> Self {
466        Arc::new(Node {
467            cmr: Cmr::injr(child.cmr()),
468            data: N::CachedData::injr(&child.data),
469            inner: Inner::InjR(Arc::clone(child)),
470        })
471    }
472
473    fn take(child: &Self) -> Self {
474        Arc::new(Node {
475            cmr: Cmr::take(child.cmr()),
476            data: N::CachedData::take(&child.data),
477            inner: Inner::Take(Arc::clone(child)),
478        })
479    }
480
481    fn drop_(child: &Self) -> Self {
482        Arc::new(Node {
483            cmr: Cmr::drop(child.cmr()),
484            data: N::CachedData::drop_(&child.data),
485            inner: Inner::Drop(Arc::clone(child)),
486        })
487    }
488
489    fn comp(left: &Self, right: &Self) -> Result<Self, types::Error> {
490        Ok(Arc::new(Node {
491            cmr: Cmr::comp(left.cmr(), right.cmr()),
492            data: N::CachedData::comp(&left.data, &right.data)?,
493            inner: Inner::Comp(Arc::clone(left), Arc::clone(right)),
494        }))
495    }
496
497    fn case(left: &Self, right: &Self) -> Result<Self, types::Error> {
498        Ok(Arc::new(Node {
499            cmr: Cmr::case(left.cmr(), right.cmr()),
500            data: N::CachedData::case(&left.data, &right.data)?,
501            inner: Inner::Case(Arc::clone(left), Arc::clone(right)),
502        }))
503    }
504
505    fn assertl(left: &Self, r_cmr: Cmr) -> Result<Self, types::Error> {
506        Ok(Arc::new(Node {
507            cmr: Cmr::case(left.cmr(), r_cmr),
508            data: N::CachedData::assertl(&left.data, r_cmr)?,
509            inner: Inner::AssertL(Arc::clone(left), r_cmr),
510        }))
511    }
512
513    fn assertr(l_cmr: Cmr, right: &Self) -> Result<Self, types::Error> {
514        Ok(Arc::new(Node {
515            cmr: Cmr::case(l_cmr, right.cmr()),
516            data: N::CachedData::assertr(l_cmr, &right.data)?,
517            inner: Inner::AssertR(l_cmr, Arc::clone(right)),
518        }))
519    }
520
521    fn pair(left: &Self, right: &Self) -> Result<Self, types::Error> {
522        Ok(Arc::new(Node {
523            cmr: Cmr::pair(left.cmr(), right.cmr()),
524            data: N::CachedData::pair(&left.data, &right.data)?,
525            inner: Inner::Pair(Arc::clone(left), Arc::clone(right)),
526        }))
527    }
528
529    fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self {
530        Arc::new(Node {
531            cmr: Cmr::fail(entropy),
532            data: N::CachedData::fail(inference_context, entropy),
533            inner: Inner::Fail(entropy),
534        })
535    }
536
537    fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self {
538        Arc::new(Node {
539            cmr: Cmr::const_word(&word),
540            data: N::CachedData::const_word(inference_context, word.shallow_clone()),
541            inner: Inner::Word(word),
542        })
543    }
544
545    fn inference_context(&self) -> &types::Context<'brand> {
546        self.data.inference_context()
547    }
548}
549
550impl<'brand, N> DisconnectConstructible<'brand, N::Disconnect> for Arc<Node<N>>
551where
552    N: Marker,
553    N::CachedData: DisconnectConstructible<'brand, N::Disconnect>,
554{
555    fn disconnect(left: &Self, right: &N::Disconnect) -> Result<Self, types::Error> {
556        Ok(Arc::new(Node {
557            cmr: Cmr::disconnect(left.cmr()),
558            data: N::CachedData::disconnect(&left.data, right)?,
559            inner: Inner::Disconnect(Arc::clone(left), right.clone()),
560        }))
561    }
562}
563
564impl<'brand, N> WitnessConstructible<'brand, N::Witness> for Arc<Node<N>>
565where
566    N: Marker,
567    N::CachedData: WitnessConstructible<'brand, N::Witness>,
568{
569    fn witness(inference_context: &types::Context<'brand>, value: N::Witness) -> Self {
570        Arc::new(Node {
571            cmr: Cmr::witness(),
572            data: N::CachedData::witness(inference_context, value.clone()),
573            inner: Inner::Witness(value),
574        })
575    }
576}
577
578impl<'brand, N> JetConstructible<'brand, N::Jet> for Arc<Node<N>>
579where
580    N: Marker,
581    N::CachedData: JetConstructible<'brand, N::Jet>,
582{
583    fn jet(inference_context: &types::Context<'brand>, jet: N::Jet) -> Self {
584        Arc::new(Node {
585            cmr: Cmr::jet(jet),
586            data: N::CachedData::jet(inference_context, jet),
587            inner: Inner::Jet(jet),
588        })
589    }
590}
591
592impl<N: Marker> Node<N> {
593    /// Accessor for the node's "inner value", i.e. its combinator
594    pub fn inner(&self) -> &Inner<Arc<Node<N>>, N::Jet, N::Disconnect, N::Witness> {
595        &self.inner
596    }
597
598    /// Accessor for the node's CMR
599    pub fn cmr(&self) -> Cmr {
600        self.cmr
601    }
602
603    /// Accessor for the node's cached data
604    pub fn sharing_id(&self) -> Option<N::SharingId> {
605        N::compute_sharing_id(self.cmr, &self.data)
606    }
607
608    /// Accessor for the node's cached data
609    pub fn cached_data(&self) -> &N::CachedData {
610        &self.data
611    }
612
613    /// Contruct a node from its constituent parts.
614    ///
615    /// This method can be used to directly costruct a node. It will compute the CMR
616    /// automatically based on the value of `inner` but requires that `cached_data`
617    /// be provided.
618    ///
619    /// If available, [`Constructible`] and its dependent traits will be easier to
620    /// use.
621    pub fn from_parts(
622        inner: Inner<Arc<Self>, N::Jet, N::Disconnect, N::Witness>,
623        data: N::CachedData,
624    ) -> Self {
625        let cmr = match inner {
626            Inner::Unit => Cmr::unit(),
627            Inner::Iden => Cmr::iden(),
628            Inner::InjL(ref c) => Cmr::injl(c.cmr()),
629            Inner::InjR(ref c) => Cmr::injr(c.cmr()),
630            Inner::Take(ref c) => Cmr::take(c.cmr()),
631            Inner::Drop(ref c) => Cmr::drop(c.cmr()),
632            Inner::Comp(ref cl, ref cr) => Cmr::comp(cl.cmr(), cr.cmr()),
633            Inner::Case(ref cl, ref cr) => Cmr::case(cl.cmr(), cr.cmr()),
634            Inner::AssertL(ref c, cmr) => Cmr::case(c.cmr(), cmr),
635            Inner::AssertR(cmr, ref c) => Cmr::case(cmr, c.cmr()),
636            Inner::Pair(ref cl, ref cr) => Cmr::pair(cl.cmr(), cr.cmr()),
637            Inner::Disconnect(ref cl, _) => Cmr::disconnect(cl.cmr()),
638            Inner::Witness(_) => Cmr::witness(),
639            Inner::Fail(entropy) => Cmr::fail(entropy),
640            Inner::Jet(j) => Cmr::jet(j),
641            Inner::Word(ref w) => Cmr::const_word(w),
642        };
643
644        Node { cmr, inner, data }
645    }
646
647    /// Generic conversion function from one type of node to another, with the
648    /// ability to prune during the conversion.
649    ///
650    /// Parameterized over what kind of sharing to use when iterating over the
651    /// DAG, and what conversion logic to use.
652    ///
653    /// See the documentation for [`Converter`] for details.
654    pub fn convert<S, M, C>(&self, converter: &mut C) -> Result<Arc<Node<M>>, C::Error>
655    where
656        S: for<'a> SharingTracker<&'a Self> + Default,
657        M: Marker<Jet = <N as Marker>::Jet>,
658        C: Converter<N, M>,
659    {
660        let mut converted: Vec<Arc<Node<M>>> = vec![];
661        for data in self.post_order_iter::<S>() {
662            // First, tell the converter about the iterator state..
663            converter.visit_node(&data);
664
665            // Construct an Inner<usize> where pointers are replaced by indices.
666            // Note that `map_left_right`'s internal logic will ensure that these
667            // `unwrap`s are only called when they will succeed.
668            let indexed_inner: Inner<usize, N::Jet, &N::Disconnect, &N::Witness> = data
669                .node
670                .inner
671                .as_ref()
672                .map_left_right(|_| data.left_index.unwrap(), |_| data.right_index.unwrap());
673
674            // Then, convert witness data, if this is a witness node.
675            let witness_inner: Inner<&usize, M::Jet, &&N::Disconnect, M::Witness> = indexed_inner
676                .as_ref()
677                .map_witness_result(|wit| converter.convert_witness(&data, wit))?;
678
679            // Then convert disconnect nodes data.
680            let maybe_converted = data.right_index.map(|idx| &converted[idx]);
681            let witness_inner: Inner<&usize, N::Jet, M::Disconnect, M::Witness> = witness_inner
682                .map_disconnect_result(|disc| {
683                    converter.convert_disconnect(&data, maybe_converted, disc)
684                })?;
685
686            // Then put the converted nodes in place (it's easier to do this in this
687            // order because of the way the reference types work out).
688            let converted_inner: Inner<Arc<Node<M>>, M::Jet, M::Disconnect, M::Witness> =
689                witness_inner.map(|idx| Arc::clone(&converted[*idx]));
690
691            // Next, prune case nodes into asserts, if applicable
692            let pruned_inner = if let Inner::Case(left, right) = converted_inner {
693                let hide = converter.prune_case(&data, &left, &right)?;
694
695                match hide {
696                    Hide::Neither => Inner::Case(left, right),
697                    Hide::Left => Inner::AssertR(left.cmr(), right),
698                    Hide::Right => Inner::AssertL(left, right.cmr()),
699                }
700            } else {
701                converted_inner
702            };
703
704            // Finally, construct the node
705            converted.push(Arc::new(Node {
706                data: converter.convert_data(&data, pruned_inner.as_ref())?,
707                cmr: data.node.cmr,
708                inner: pruned_inner,
709            }));
710        }
711        Ok(converted.pop().unwrap())
712    }
713
714    pub fn display(&self) -> Display<'_, N> {
715        Display::from(self)
716    }
717
718    /// Display the Simplicity expression as a linear string.
719    ///
720    /// The linear string has no sharing and may be **exponentially larger**
721    /// than the originally shared expression!
722    pub fn display_expr(&self) -> DisplayExpr<'_, N> {
723        DisplayExpr::from(self)
724    }
725
726    /// Encode a Simplicity expression to bits without any witness data.
727    pub fn encode_without_witness<W: io::Write>(&self, prog: W) -> io::Result<usize> {
728        let mut w = BitWriter::new(prog);
729        let program_bits = encode::encode_program(self, &mut w)?;
730        w.flush_all()?;
731        Ok(program_bits)
732    }
733
734    /// Encode a Simplicity expression to a vector of bytes, without any witness data.
735    pub fn to_vec_without_witness(&self) -> Vec<u8> {
736        let mut program = Vec::<u8>::new();
737        self.encode_without_witness(&mut program)
738            .expect("Vec::write is infallible");
739        debug_assert!(!program.is_empty());
740        program
741    }
742}
743
744impl<N: Marker<Witness = Value>> Node<N> {
745    /// Encode the program and witness data to bits.
746    ///
747    /// Returns the number of written bits for the program and witness, respectively.
748    pub fn encode_with_witness<W1: io::Write, W2: io::Write>(
749        &self,
750        prog: W1,
751        witness: W2,
752    ) -> io::Result<(usize, usize)> {
753        let mut prog = BitWriter::new(prog);
754        let mut witness = BitWriter::new(witness);
755
756        let sharing_iter = self.post_order_iter::<MaxSharing<N>>();
757        let program_bits = encode::encode_program(self, &mut prog)?;
758        prog.flush_all()?;
759        let witness_bits = encode::encode_witness(sharing_iter.into_witnesses(), &mut witness)?;
760        witness.flush_all()?;
761        Ok((program_bits, witness_bits))
762    }
763
764    /// Encode the program and witness data to byte vectors.
765    pub fn to_vec_with_witness(&self) -> (Vec<u8>, Vec<u8>) {
766        let mut ret_1 = vec![];
767        let mut ret_2 = vec![];
768        self.encode_with_witness(&mut ret_1, &mut ret_2)
769            .expect("Vec::write is infallible");
770        (ret_1, ret_2)
771    }
772}
773
774#[cfg(test)]
775#[cfg(all(feature = "test-utils", feature = "elements"))]
776mod tests {
777    use ffi::tests::TestData;
778
779    use crate::analysis::Cost;
780    use crate::ffi;
781    use crate::jet::Elements;
782    use crate::BitIter;
783    use crate::RedeemNode;
784
785    fn check_merkle_roots(test: &TestData) {
786        let prog = BitIter::from(test.prog.as_slice());
787        let witness = BitIter::from(test.witness.as_slice());
788        ffi::tests::run_program(
789            &test.prog,
790            &test.witness,
791            ffi::tests::TestUpTo::CheckOneOne,
792            None,
793            None,
794        )
795        .unwrap();
796        let prog = RedeemNode::<Elements>::decode(prog, witness).unwrap();
797        assert_eq!(prog.cmr().to_byte_array(), test.cmr);
798        assert_eq!(prog.amr().to_byte_array(), test.amr);
799        assert_eq!(prog.ihr().to_byte_array(), test.ihr);
800        assert_eq!(prog.bounds().cost, Cost::from_milliweight(test.cost))
801    }
802
803    #[test]
804    fn progs_cmr() {
805        let schnorr0 = ffi::tests::schnorr0_test_data();
806        let schnorr6 = ffi::tests::schnorr6_test_data();
807        let ctx8_unpruned = ffi::tests::ctx8_unpruned_test_data();
808        let ctx8_pruned = ffi::tests::ctx8_pruned_test_data();
809        // check_merkle_roots(&hash_block); Need 1 -> 1 for now.
810        check_merkle_roots(&schnorr0);
811        check_merkle_roots(&schnorr6);
812        check_merkle_roots(&ctx8_unpruned);
813        check_merkle_roots(&ctx8_pruned);
814    }
815}