Skip to main content

simplicity/merkle/
cmr.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use crate::jet::Jet;
4#[cfg(feature = "elements")]
5use crate::node::{CoreConstructible, WitnessConstructible};
6#[cfg(feature = "elements")]
7use crate::types::{self, Arrow, Error};
8use crate::value::Word;
9use crate::{FailEntropy, Tmr};
10use hashes::sha256::Midstate;
11
12use super::{bip340_iv, impl_mr_type, MidstateExt as _};
13
14impl_mr_type! {
15    /// Commitment Merkle root
16    ///
17    /// A Merkle root that commits to a node's combinator and recursively its children.
18    ///
19    /// Importantly, witness data and right disconnect branches are _not_ included in the hash.
20    /// This makes these elements malleable while preserving program identity (SegWit, delegation).
21    ///
22    /// Uniquely identifies a program's structure in terms of combinators at commitment time.
23    #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
24    pub struct Cmr([u8; 32]);
25}
26
27impl From<Tmr> for Cmr {
28    fn from(tmr: Tmr) -> Self {
29        Cmr::from_byte_array(tmr.to_byte_array())
30    }
31}
32
33impl Cmr {
34    /// Produce a CMR for an iden combinator
35    pub const fn iden() -> Self {
36        Self::from_byte_array(Self::IDEN_IV.to_parts().0)
37    }
38
39    /// Produce a CMR for a unit combinator
40    pub const fn unit() -> Self {
41        Self::from_byte_array(Self::UNIT_IV.to_parts().0)
42    }
43
44    /// Produce a CMR for an injl combinator
45    pub fn injl(child: Cmr) -> Self {
46        Self::INJL_IV.update_0_then_32(child).into_merkle_root()
47    }
48
49    /// Produce a CMR for an injr combinator
50    pub fn injr(child: Cmr) -> Self {
51        Self::INJR_IV.update_0_then_32(child).into_merkle_root()
52    }
53
54    /// Produce a CMR for a take combinator
55    pub fn take(child: Cmr) -> Self {
56        Self::TAKE_IV.update_0_then_32(child).into_merkle_root()
57    }
58
59    /// Produce a CMR for a drop combinator
60    pub fn drop(child: Cmr) -> Self {
61        Self::DROP_IV.update_0_then_32(child).into_merkle_root()
62    }
63
64    /// Produce a CMR for a comp combinator
65    pub fn comp(left: Cmr, right: Cmr) -> Self {
66        Self::COMP_IV.zz_update_2x32(left, right).into_merkle_root()
67    }
68
69    /// Produce a CMR for a case combinator
70    pub fn case(left: Cmr, right: Cmr) -> Self {
71        Self::CASE_IV.zz_update_2x32(left, right).into_merkle_root()
72    }
73
74    /// Produce a CMR for a pair combinator
75    pub fn pair(left: Cmr, right: Cmr) -> Self {
76        Self::PAIR_IV.zz_update_2x32(left, right).into_merkle_root()
77    }
78
79    /// Produce a CMR for a disconnect combinator
80    pub fn disconnect(left: Cmr) -> Self {
81        Self::DISCONNECT_IV
82            .update_0_then_32(left)
83            .into_merkle_root()
84    }
85
86    /// Produce a CMR for a witness combinator
87    pub const fn witness() -> Self {
88        Self::from_byte_array(Self::WITNESS_IV.to_parts().0)
89    }
90
91    /// Produce a CMR for a fail combinator
92    pub fn fail(entropy: FailEntropy) -> Self {
93        Self::FAIL_IV
94            .zz_update_64(entropy.to_byte_array())
95            .into_merkle_root()
96    }
97
98    /// Produce a CMR for a jet
99    pub fn jet(jet: &dyn Jet) -> Self {
100        jet.cmr()
101    }
102
103    /// Compute the CMR of a constant word jet
104    ///
105    /// This is equal to the IHR of the equivalent scribe, converted to a CMR in
106    /// the usual way for jets.
107    pub fn const_word(word: &Word) -> Self {
108        let w = 1 + word.n();
109
110        let mut cmr_stack = Vec::with_capacity(33);
111        // 1. Compute the CMR for the `scribe` corresponding to this word jet
112        for (bit_idx, bit) in word.iter().enumerate() {
113            cmr_stack.push(Cmr::BITS[usize::from(bit)]);
114            let mut j = bit_idx;
115            while j & 1 == 1 {
116                let right_cmr = cmr_stack.pop().unwrap();
117                let left_cmr = cmr_stack.pop().unwrap();
118                cmr_stack.push(Cmr::pair(left_cmr, right_cmr));
119                j >>= 1;
120            }
121        }
122        assert_eq!(cmr_stack.len(), 1);
123
124        let ihr_iv = Self::CONST_WORD_IV;
125        let ihr_pass1 = ihr_iv.update_0_then_32(cmr_stack[0]);
126        // 2. Add TMRs to get the pass-two IHR
127        let ihr_pass2 = ihr_pass1.zz_update_2x32(Tmr::unit(), Tmr::TWO_TWO_N[w - 1]);
128        // 3. Convert to a jet CMR
129        bip340_iv(b"Simplicity\x1fJet")
130            .update_weight_then_32(word.len() as u64, ihr_pass2.to_parts().0)
131            .into_merkle_root()
132    }
133
134    #[rustfmt::skip]
135    const UNIT_IV: Midstate = Midstate::new([
136        0xc4, 0x0a, 0x10, 0x26, 0x3f, 0x74, 0x36, 0xb4,
137        0x16, 0x0a, 0xcb, 0xef, 0x1c, 0x36, 0xfb, 0xa4,
138        0xbe, 0x4d, 0x95, 0xdf, 0x18, 0x1a, 0x96, 0x8a,
139        0xfe, 0xab, 0x5e, 0xac, 0x24, 0x7a, 0xdf, 0xf7,
140    ], 64);
141
142    #[rustfmt::skip]
143    const IDEN_IV: Midstate = Midstate::new([
144        0x54, 0x1a, 0x1a, 0x69, 0xbd, 0x4b, 0xcb, 0xda,
145        0x7f, 0x34, 0x31, 0x0e, 0x30, 0x78, 0xf7, 0x26,
146        0x44, 0x31, 0x22, 0xfb, 0xcc, 0x1c, 0xb5, 0x36,
147        0x0c, 0x78, 0x64, 0xec, 0x0d, 0x32, 0x3a, 0xc0,
148    ], 64);
149
150    #[rustfmt::skip]
151    const INJL_IV: Midstate = Midstate::new([
152        0x54, 0xe9, 0x1d, 0x18, 0xd8, 0xf8, 0x1f, 0x6d,
153        0x29, 0x86, 0xbb, 0x58, 0x47, 0x9a, 0x54, 0xeb,
154        0x63, 0x0e, 0x95, 0x23, 0xb6, 0x9e, 0xe8, 0x53,
155        0x29, 0x80, 0xd0, 0x55, 0x58, 0x19, 0x4f, 0x15,
156    ], 64);
157
158    #[rustfmt::skip]
159    const INJR_IV: Midstate = Midstate::new([
160        0xd7, 0x0f, 0xfd, 0xce, 0x97, 0x77, 0x7b, 0x4d,
161        0xfe, 0x31, 0xfd, 0x9f, 0xf5, 0xd0, 0x17, 0xa6,
162        0x30, 0x5d, 0x7e, 0xc6, 0x0d, 0xf3, 0xb1, 0xbf,
163        0x6d, 0x25, 0xe8, 0x16, 0x33, 0xde, 0xd4, 0xbf,
164    ], 64);
165
166    #[rustfmt::skip]
167    const TAKE_IV: Midstate = Midstate::new([
168        0x50, 0x5f, 0xc0, 0x81, 0xb5, 0xba, 0x2a, 0xcd,
169        0x09, 0x50, 0x67, 0xc3, 0xdf, 0xb8, 0xea, 0x12,
170        0x6f, 0xa1, 0x5d, 0x55, 0xcb, 0x21, 0x1e, 0x6a,
171        0xed, 0x34, 0xe8, 0xd1, 0xe3, 0x7a, 0xf0, 0xfa,
172    ], 64);
173
174    #[rustfmt::skip]
175    const DROP_IV: Midstate = Midstate::new([
176        0x8a, 0x30, 0x8d, 0x38, 0xa1, 0x13, 0xa2, 0x60,
177        0xb4, 0xc7, 0x14, 0x5a, 0xbd, 0xc5, 0x22, 0x4d,
178        0xeb, 0x70, 0x13, 0x79, 0x59, 0x0e, 0x0c, 0x8c,
179        0x38, 0x86, 0x0b, 0xab, 0x12, 0x71, 0xa8, 0xa8,
180    ], 64);
181
182    #[rustfmt::skip]
183    const COMP_IV: Midstate = Midstate::new([
184        0x57, 0xec, 0x23, 0xa2, 0xa4, 0x77, 0x8e, 0x01,
185        0x58, 0xa6, 0x21, 0x7a, 0xea, 0x3e, 0xf7, 0x42,
186        0x8b, 0xa0, 0x90, 0x92, 0x73, 0xb9, 0x73, 0xfa,
187        0x14, 0x32, 0xa9, 0x27, 0x84, 0x3e, 0x92, 0x7a,
188    ], 64);
189
190    #[rustfmt::skip]
191    const CASE_IV: Midstate = Midstate::new([
192        0x29, 0x5e, 0x2a, 0x6d, 0xc8, 0xc5, 0xce, 0x59,
193        0xe4, 0xed, 0xcf, 0xe9, 0xb4, 0xd8, 0xf7, 0x64,
194        0x13, 0x3a, 0xa5, 0x51, 0x4b, 0xd3, 0xee, 0x8b,
195        0x4b, 0x75, 0xec, 0x8f, 0x4d, 0xeb, 0x08, 0xbe,
196    ], 64);
197
198    #[rustfmt::skip]
199    const PAIR_IV: Midstate = Midstate::new([
200        0x7d, 0x5e, 0x6d, 0xac, 0x15, 0xb1, 0x42, 0x8a,
201        0x0d, 0x26, 0x0c, 0x94, 0x29, 0xdb, 0xe8, 0x89,
202        0x65, 0x93, 0xf3, 0x1f, 0x70, 0x86, 0x27, 0xee,
203        0x75, 0xb2, 0x7e, 0xee, 0xfd, 0xd0, 0x50, 0x05,
204    ], 64);
205
206    #[rustfmt::skip]
207    const DISCONNECT_IV: Midstate = Midstate::new([
208        0x35, 0x33, 0x8b, 0x5b, 0x81, 0x74, 0x0c, 0x6d,
209        0x67, 0xdc, 0x1e, 0xa3, 0xc8, 0x31, 0xe4, 0xc0,
210        0xaf, 0xd8, 0x64, 0x09, 0xbc, 0x04, 0xd0, 0xdd,
211        0x43, 0x24, 0xb7, 0xd9, 0xd5, 0x83, 0xf4, 0xeb,
212    ], 64);
213
214    #[rustfmt::skip]
215    const WITNESS_IV: Midstate = Midstate::new([
216        0xa0, 0xfc, 0x8d, 0xeb, 0xd6, 0x79, 0x69, 0x17,
217        0xc8, 0x6b, 0x77, 0xad, 0xed, 0x82, 0xe6, 0xc6,
218        0x16, 0x49, 0x88, 0x9a, 0xe8, 0xf2, 0xed, 0x65,
219        0xb5, 0x7b, 0x41, 0xaa, 0x9d, 0x90, 0xe3, 0x75,
220    ], 64);
221
222    #[rustfmt::skip]
223    const FAIL_IV: Midstate = Midstate::new([
224        0x22, 0x83, 0xc1, 0x81, 0x9e, 0x69, 0x2f, 0x96,
225        0x85, 0xfe, 0x95, 0x40, 0x76, 0xc5, 0x16, 0x7c,
226        0x03, 0xbd, 0xe7, 0xcc, 0xda, 0xab, 0x00, 0x5e,
227        0x55, 0x36, 0x12, 0x2e, 0x18, 0xf7, 0x23, 0x7a,
228    ], 64);
229
230    #[rustfmt::skip]
231    const CONST_WORD_IV: Midstate = Midstate::new([
232        0x0c, 0x5b, 0xc1, 0xce, 0xc8, 0xf1, 0x41, 0x85,
233        0x0e, 0x33, 0x3e, 0x28, 0xea, 0x01, 0xc0, 0x5a,
234        0xc6, 0x42, 0xeb, 0x30, 0xb4, 0x9e, 0x69, 0x2c,
235        0x56, 0xb1, 0x22, 0xbb, 0x69, 0x49, 0xc5, 0xcd,
236    ], 64);
237
238    /// CMRs for the bits 0 and 1 -- injl(unit) and injr(unit) respectively
239    #[rustfmt::skip]
240    const BITS: [Cmr; 2] = [
241        Cmr([
242            0x88, 0x81, 0xaf, 0xf5, 0x16, 0x0c, 0xc0, 0xc9,
243            0xf8, 0xec, 0xea, 0xd8, 0xb4, 0x01, 0xfa, 0x97,
244            0xee, 0xf5, 0xfc, 0x60, 0x75, 0x2e, 0x98, 0xd2,
245            0x47, 0x56, 0x1a, 0x4d, 0xa6, 0xce, 0x96, 0x5e,
246        ]),
247        Cmr([
248            0xa0, 0x43, 0x8b, 0x72, 0x36, 0x48, 0x72, 0x7b,
249            0x3f, 0x2d, 0x18, 0x5f, 0xcd, 0x95, 0x69, 0xe0,
250            0x22, 0xa4, 0x47, 0x8e, 0xb2, 0x5f, 0xdf, 0xa5,
251            0x38, 0xea, 0xc5, 0x9d, 0x81, 0x7c, 0x31, 0x1c,
252        ]),
253    ];
254}
255
256/// Wrapper around a CMR which allows it to be constructed with the
257/// `*Constructible*` traits, allowing CMRs to be computed using the
258/// same generic construction code that nodes are.
259#[cfg(feature = "elements")] // only used by policy module
260pub struct ConstructibleCmr<'brand> {
261    pub cmr: Cmr,
262    pub arrow: Arrow<'brand>,
263}
264
265#[cfg(feature = "elements")] // only used by policy module
266impl<'brand> CoreConstructible<'brand> for ConstructibleCmr<'brand> {
267    fn iden(inference_context: &types::Context<'brand>) -> Self {
268        ConstructibleCmr {
269            cmr: Cmr::iden(),
270            arrow: Arrow::iden(inference_context),
271        }
272    }
273
274    fn unit(inference_context: &types::Context<'brand>) -> Self {
275        ConstructibleCmr {
276            cmr: Cmr::unit(),
277            arrow: Arrow::unit(inference_context),
278        }
279    }
280
281    fn injl(child: &Self) -> Self {
282        ConstructibleCmr {
283            cmr: Cmr::injl(child.cmr),
284            arrow: Arrow::injl(child.arrow()),
285        }
286    }
287
288    fn injr(child: &Self) -> Self {
289        ConstructibleCmr {
290            cmr: Cmr::injr(child.cmr),
291            arrow: Arrow::injr(child.arrow()),
292        }
293    }
294
295    fn take(child: &Self) -> Self {
296        ConstructibleCmr {
297            cmr: Cmr::take(child.cmr),
298            arrow: Arrow::take(child.arrow()),
299        }
300    }
301
302    fn drop_(child: &Self) -> Self {
303        ConstructibleCmr {
304            cmr: Cmr::drop(child.cmr),
305            arrow: Arrow::drop_(child.arrow()),
306        }
307    }
308
309    fn comp(left: &Self, right: &Self) -> Result<Self, Error> {
310        Ok(ConstructibleCmr {
311            cmr: Cmr::comp(left.cmr, right.cmr),
312            arrow: Arrow::comp(left.arrow(), right.arrow())?,
313        })
314    }
315
316    fn case(left: &Self, right: &Self) -> Result<Self, Error> {
317        Ok(ConstructibleCmr {
318            cmr: Cmr::case(left.cmr, right.cmr),
319            arrow: Arrow::case(left.arrow(), right.arrow())?,
320        })
321    }
322
323    fn assertl(left: &Self, right: Cmr) -> Result<Self, Error> {
324        Ok(ConstructibleCmr {
325            cmr: Cmr::case(left.cmr, right),
326            arrow: Arrow::assertl(left.arrow())?,
327        })
328    }
329
330    fn assertr(left: Cmr, right: &Self) -> Result<Self, Error> {
331        Ok(ConstructibleCmr {
332            cmr: Cmr::case(left, right.cmr),
333            arrow: Arrow::assertr(right.arrow())?,
334        })
335    }
336
337    fn pair(left: &Self, right: &Self) -> Result<Self, Error> {
338        Ok(ConstructibleCmr {
339            cmr: Cmr::pair(left.cmr, right.cmr),
340            arrow: Arrow::pair(left.arrow(), right.arrow())?,
341        })
342    }
343
344    fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self {
345        ConstructibleCmr {
346            cmr: Cmr::fail(entropy),
347            arrow: Arrow::fail(inference_context),
348        }
349    }
350
351    fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self {
352        ConstructibleCmr {
353            cmr: Cmr::const_word(&word),
354            arrow: Arrow::const_word(inference_context, &word),
355        }
356    }
357
358    fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self {
359        ConstructibleCmr {
360            cmr: jet.cmr(),
361            arrow: Arrow::jet(inference_context, jet),
362        }
363    }
364
365    fn arrow(&self) -> &Arrow<'brand> {
366        &self.arrow
367    }
368}
369
370#[cfg(feature = "elements")] // only used by policy module
371impl<'brand, W> WitnessConstructible<'brand, W> for ConstructibleCmr<'brand> {
372    fn witness(inference_context: &types::Context<'brand>, _witness: W) -> Self {
373        ConstructibleCmr {
374            arrow: Arrow::witness(inference_context),
375            cmr: Cmr::witness(),
376        }
377    }
378}
379
380#[cfg(test)]
381mod tests {
382    use super::*;
383
384    use crate::node::{ConstructNode, CoreConstructible};
385    use crate::types;
386
387    use std::str::FromStr;
388    use std::sync::Arc;
389
390    #[test]
391    fn cmr_display_unit() {
392        types::Context::with_context(|ctx| {
393            let c = Arc::<ConstructNode>::unit(&ctx);
394
395            assert_eq!(
396                c.cmr().to_string(),
397                "c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7"
398            );
399            assert_eq!(format!("{:.8}", c.cmr()), "c40a1026");
400
401            assert_eq!(
402                Cmr::from_str("c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7"),
403                Ok(c.cmr()),
404            );
405        });
406    }
407
408    #[test]
409    fn fixed_const_word_cmr() {
410        // Checked against C implementation
411        let bit0 = Word::u1(0);
412        #[rustfmt::skip]
413        assert_eq!(
414            Cmr::const_word(&bit0),
415            Cmr::from_str("a51cfd799d0bc368f48208032fc3881953f35aa7fd2b985cb237cbad143e30d2").unwrap(),
416        );
417    }
418
419    #[test]
420    fn bit_cmr() {
421        types::Context::with_context(|ctx| {
422            let unit = Arc::<ConstructNode>::unit(&ctx);
423            let bit0 = Arc::<ConstructNode>::injl(&unit);
424            assert_eq!(bit0.cmr(), Cmr::BITS[0]);
425
426            let bit1 = Arc::<ConstructNode>::injr(&unit);
427            assert_eq!(bit1.cmr(), Cmr::BITS[1]);
428        });
429    }
430
431    #[test]
432    fn ivs() {
433        fn check_iv(target: Midstate, s: &'static str) {
434            let name = s
435                .trim_start_matches("Simplicity\x1f")
436                .strip_prefix("Commitment\x1f")
437                .unwrap_or("const_word");
438            // Uncomment this if the IVs ever change
439            /*
440            let target = Cmr(bip340_iv(s.as_bytes()));
441            println!("    #[rustfmt::skip]");
442            println!("    const {}_IV: Midstate = Midstate::new([", name.to_ascii_uppercase());
443            print!("       "); for ch in &target.0[0..8] { print!(" 0x{:02x},", ch); }; println!();
444            print!("       "); for ch in &target.0[8..16] { print!(" 0x{:02x},", ch); }; println!();
445            print!("       "); for ch in &target.0[16..24] { print!(" 0x{:02x},", ch); }; println!();
446            print!("       "); for ch in &target.0[24..32] { print!(" 0x{:02x},", ch); }; println!();
447            println!("    ], 64);");
448            println!();
449            */
450            assert_eq!(
451                target,
452                bip340_iv(s.as_bytes()),
453                "mismatch on IV for {}",
454                name
455            );
456        }
457
458        check_iv(Cmr::UNIT_IV, "Simplicity\x1fCommitment\x1funit");
459        check_iv(Cmr::IDEN_IV, "Simplicity\x1fCommitment\x1fiden");
460        check_iv(Cmr::INJL_IV, "Simplicity\x1fCommitment\x1finjl");
461        check_iv(Cmr::INJR_IV, "Simplicity\x1fCommitment\x1finjr");
462        check_iv(Cmr::TAKE_IV, "Simplicity\x1fCommitment\x1ftake");
463        check_iv(Cmr::DROP_IV, "Simplicity\x1fCommitment\x1fdrop");
464        check_iv(Cmr::COMP_IV, "Simplicity\x1fCommitment\x1fcomp");
465        check_iv(Cmr::CASE_IV, "Simplicity\x1fCommitment\x1fcase");
466        check_iv(Cmr::PAIR_IV, "Simplicity\x1fCommitment\x1fpair");
467        check_iv(Cmr::DISCONNECT_IV, "Simplicity\x1fCommitment\x1fdisconnect");
468        check_iv(Cmr::WITNESS_IV, "Simplicity\x1fCommitment\x1fwitness");
469        check_iv(Cmr::FAIL_IV, "Simplicity\x1fCommitment\x1ffail");
470        check_iv(Cmr::CONST_WORD_IV, "Simplicity\x1fIdentity");
471    }
472
473    #[test]
474    fn const_bits() {
475        /// The scribe expression, as defined in the Simplicity tech report.
476        fn scribe<'brand>(ctx: &types::Context<'brand>, bit: u8) -> Arc<ConstructNode<'brand>> {
477            match bit {
478                0 => Arc::<ConstructNode>::injl(&Arc::<ConstructNode>::unit(ctx)),
479                1 => Arc::<ConstructNode>::injr(&Arc::<ConstructNode>::unit(ctx)),
480                _ => panic!("Unexpected bit {bit}"),
481            }
482        }
483
484        fn check_bit(target: Cmr, index: u8) {
485            // Uncomment this if the IVs ever change
486            /*
487            let target = scribe(index).cmr();
488            println!("    Cmr(Midstate([");
489            print!("       "); for ch in &target.0[0..8] { print!(" 0x{:02x},", ch); }; println!();
490            print!("       "); for ch in &target.0[8..16] { print!(" 0x{:02x},", ch); }; println!();
491            print!("       "); for ch in &target.0[16..24] { print!(" 0x{:02x},", ch); }; println!();
492            print!("       "); for ch in &target.0[24..32] { print!(" 0x{:02x},", ch); }; println!();
493            println!("    ])),");
494            */
495            types::Context::with_context(|ctx| {
496                assert_eq!(
497                    target,
498                    scribe(&ctx, index).cmr(),
499                    "mismatch on CMR for bit {index}",
500                );
501            });
502        }
503
504        for index in 0..2u8 {
505            check_bit(Cmr::BITS[usize::from(index)], index)
506        }
507    }
508}