Skip to main content

simplicity/merkle/
ihr.rs

1// SPDX-License-Identifier: CC0-1.0
2
3use crate::jet::Jet;
4use crate::types::FinalArrow;
5use crate::value::Word;
6use crate::{Cmr, Tmr, Value};
7use hashes::sha256::Midstate;
8
9use super::{bip340_iv, compact_value, impl_mr_type, FailEntropy, MidstateExt as _};
10
11impl_mr_type! {
12    /// Identity Merkle Root
13    ///
14    /// A Merkle root that commits to a node's combinator, its witness data (if present),
15    /// and recursively its children. Used as input to the [`Ihr`] type which is probably
16    /// actually what you want.
17    #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
18    pub struct Imr([u8; 32]);
19}
20
21impl_mr_type! {
22    /// Identity Hash Root
23    ///
24    /// A Merkle root that commits to a node's [`Imr`] (which recursively commits to its
25    /// childrens' [`Imr`]s) as well as its source and target types.
26    ///
27    /// Uniquely identifies a program's structure in terms of combinators at redemption time.
28    #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
29    pub struct Ihr([u8; 32]);
30}
31
32impl From<Cmr> for Imr {
33    fn from(cmr: Cmr) -> Self {
34        Imr::from_byte_array(cmr.to_byte_array())
35    }
36}
37
38impl From<Cmr> for Ihr {
39    fn from(cmr: Cmr) -> Self {
40        Ihr::from_byte_array(cmr.to_byte_array())
41    }
42}
43
44impl From<Tmr> for Ihr {
45    fn from(tmr: Tmr) -> Self {
46        Ihr::from_byte_array(tmr.to_byte_array())
47    }
48}
49
50impl Imr {
51    /// Produce a CMR for an iden combinator
52    pub const fn iden() -> Self {
53        Self::from_byte_array(Self::IDEN_IV.to_parts().0)
54    }
55
56    /// Produce a CMR for a unit combinator
57    pub const fn unit() -> Self {
58        Self::from_byte_array(Self::UNIT_IV.to_parts().0)
59    }
60
61    /// Produce a CMR for an injl combinator
62    pub fn injl(child: Self) -> Self {
63        Self::INJL_IV.update_0_then_32(child).into_merkle_root()
64    }
65
66    /// Produce a CMR for an injr combinator
67    pub fn injr(child: Self) -> Self {
68        Self::INJR_IV.update_0_then_32(child).into_merkle_root()
69    }
70
71    /// Produce a CMR for a take combinator
72    pub fn take(child: Self) -> Self {
73        Self::TAKE_IV.update_0_then_32(child).into_merkle_root()
74    }
75
76    /// Produce a CMR for a drop combinator
77    pub fn drop(child: Self) -> Self {
78        Self::DROP_IV.update_0_then_32(child).into_merkle_root()
79    }
80
81    /// Produce a CMR for a comp combinator
82    pub fn comp(left: Self, right: Self) -> Self {
83        Self::COMP_IV.zz_update_2x32(left, right).into_merkle_root()
84    }
85
86    /// Produce a CMR for a case combinator
87    pub fn case(left: Self, right: Self) -> Self {
88        Self::CASE_IV.zz_update_2x32(left, right).into_merkle_root()
89    }
90
91    /// Produce a CMR for a pair combinator
92    pub fn pair(left: Self, right: Self) -> Self {
93        Self::PAIR_IV.zz_update_2x32(left, right).into_merkle_root()
94    }
95
96    /// Produce a CMR for a disconnect combinator
97    pub fn disconnect(left: Self, right: Self) -> Self {
98        Self::DISCONNECT_IV
99            .zz_update_2x32(left, right)
100            .into_merkle_root()
101    }
102
103    /// Produce a CMR for a witness combinator
104    pub fn witness(ty: &FinalArrow, value: &Value) -> Self {
105        Self::WITNESS_IV
106            .zz_update_2x32(compact_value(value), ty.target.tmr())
107            .into_merkle_root()
108    }
109
110    /// Produce an IHR for a fail combinator
111    pub fn fail(entropy: FailEntropy) -> Self {
112        Self::FAIL_IV
113            .zz_update_64(entropy.to_byte_array())
114            .into_merkle_root()
115    }
116
117    /// Produce a CMR for a jet
118    pub fn jet(jet: &dyn Jet) -> Self {
119        Cmr::jet(jet).into()
120    }
121
122    /// Compute the CMR of a constant word jet
123    ///
124    /// This is equal to the IHR of the equivalent scribe, converted to a CMR in
125    /// the usual way for jets.
126    pub fn const_word(word: &Word) -> Self {
127        Cmr::const_word(word).into()
128    }
129
130    #[rustfmt::skip]
131    const IDEN_IV: Midstate = Midstate::new([
132        0x54, 0x1a, 0x1a, 0x69, 0xbd, 0x4b, 0xcb, 0xda,
133        0x7f, 0x34, 0x31, 0x0e, 0x30, 0x78, 0xf7, 0x26,
134        0x44, 0x31, 0x22, 0xfb, 0xcc, 0x1c, 0xb5, 0x36,
135        0x0c, 0x78, 0x64, 0xec, 0x0d, 0x32, 0x3a, 0xc0,
136    ], 64);
137
138    #[rustfmt::skip]
139    const UNIT_IV: Midstate = Midstate::new([
140        0xc4, 0x0a, 0x10, 0x26, 0x3f, 0x74, 0x36, 0xb4,
141        0x16, 0x0a, 0xcb, 0xef, 0x1c, 0x36, 0xfb, 0xa4,
142        0xbe, 0x4d, 0x95, 0xdf, 0x18, 0x1a, 0x96, 0x8a,
143        0xfe, 0xab, 0x5e, 0xac, 0x24, 0x7a, 0xdf, 0xf7,
144    ], 64);
145
146    #[rustfmt::skip]
147    const INJL_IV: Midstate = Midstate::new([
148        0x54, 0xe9, 0x1d, 0x18, 0xd8, 0xf8, 0x1f, 0x6d,
149        0x29, 0x86, 0xbb, 0x58, 0x47, 0x9a, 0x54, 0xeb,
150        0x63, 0x0e, 0x95, 0x23, 0xb6, 0x9e, 0xe8, 0x53,
151        0x29, 0x80, 0xd0, 0x55, 0x58, 0x19, 0x4f, 0x15,
152    ], 64);
153
154    #[rustfmt::skip]
155    const INJR_IV: Midstate = Midstate::new([
156        0xd7, 0x0f, 0xfd, 0xce, 0x97, 0x77, 0x7b, 0x4d,
157        0xfe, 0x31, 0xfd, 0x9f, 0xf5, 0xd0, 0x17, 0xa6,
158        0x30, 0x5d, 0x7e, 0xc6, 0x0d, 0xf3, 0xb1, 0xbf,
159        0x6d, 0x25, 0xe8, 0x16, 0x33, 0xde, 0xd4, 0xbf,
160    ], 64);
161
162    #[rustfmt::skip]
163    const TAKE_IV: Midstate = Midstate::new([
164        0x50, 0x5f, 0xc0, 0x81, 0xb5, 0xba, 0x2a, 0xcd,
165        0x09, 0x50, 0x67, 0xc3, 0xdf, 0xb8, 0xea, 0x12,
166        0x6f, 0xa1, 0x5d, 0x55, 0xcb, 0x21, 0x1e, 0x6a,
167        0xed, 0x34, 0xe8, 0xd1, 0xe3, 0x7a, 0xf0, 0xfa,
168    ], 64);
169
170    #[rustfmt::skip]
171    const DROP_IV: Midstate = Midstate::new([
172        0x8a, 0x30, 0x8d, 0x38, 0xa1, 0x13, 0xa2, 0x60,
173        0xb4, 0xc7, 0x14, 0x5a, 0xbd, 0xc5, 0x22, 0x4d,
174        0xeb, 0x70, 0x13, 0x79, 0x59, 0x0e, 0x0c, 0x8c,
175        0x38, 0x86, 0x0b, 0xab, 0x12, 0x71, 0xa8, 0xa8,
176    ], 64);
177
178    #[rustfmt::skip]
179    const COMP_IV: Midstate = Midstate::new([
180        0x57, 0xec, 0x23, 0xa2, 0xa4, 0x77, 0x8e, 0x01,
181        0x58, 0xa6, 0x21, 0x7a, 0xea, 0x3e, 0xf7, 0x42,
182        0x8b, 0xa0, 0x90, 0x92, 0x73, 0xb9, 0x73, 0xfa,
183        0x14, 0x32, 0xa9, 0x27, 0x84, 0x3e, 0x92, 0x7a,
184    ], 64);
185
186    #[rustfmt::skip]
187    const CASE_IV: Midstate = Midstate::new([
188        0x29, 0x5e, 0x2a, 0x6d, 0xc8, 0xc5, 0xce, 0x59,
189        0xe4, 0xed, 0xcf, 0xe9, 0xb4, 0xd8, 0xf7, 0x64,
190        0x13, 0x3a, 0xa5, 0x51, 0x4b, 0xd3, 0xee, 0x8b,
191        0x4b, 0x75, 0xec, 0x8f, 0x4d, 0xeb, 0x08, 0xbe,
192    ], 64);
193
194    #[rustfmt::skip]
195    const PAIR_IV: Midstate = Midstate::new([
196        0x7d, 0x5e, 0x6d, 0xac, 0x15, 0xb1, 0x42, 0x8a,
197        0x0d, 0x26, 0x0c, 0x94, 0x29, 0xdb, 0xe8, 0x89,
198        0x65, 0x93, 0xf3, 0x1f, 0x70, 0x86, 0x27, 0xee,
199        0x75, 0xb2, 0x7e, 0xee, 0xfd, 0xd0, 0x50, 0x05,
200    ], 64);
201
202    #[rustfmt::skip]
203    const DISCONNECT_IV: Midstate = Midstate::new([
204        0x4e, 0xb7, 0x99, 0x5f, 0xb5, 0xdd, 0xe5, 0xd0,
205        0x85, 0xf4, 0x70, 0x85, 0xcd, 0x95, 0x3d, 0x16,
206        0x84, 0x54, 0x11, 0xed, 0xc6, 0x89, 0xe2, 0x7a,
207        0xf9, 0xc3, 0xde, 0xa2, 0xfb, 0x12, 0x25, 0xd5,
208    ], 64);
209
210    #[rustfmt::skip]
211    const WITNESS_IV: Midstate = Midstate::new([
212        0xcb, 0x37, 0xff, 0x70, 0x01, 0xc6, 0x2d, 0x94,
213        0x42, 0x4f, 0x98, 0x7f, 0x30, 0x23, 0xb3, 0x5e,
214        0x30, 0xd2, 0x17, 0x23, 0x96, 0x27, 0x6f, 0x89,
215        0xd0, 0x9f, 0x07, 0xaa, 0x67, 0xb6, 0x21, 0x96,
216    ], 64);
217
218    #[rustfmt::skip]
219    const FAIL_IV: Midstate = Midstate::new([
220        0x22, 0x83, 0xc1, 0x81, 0x9e, 0x69, 0x2f, 0x96,
221        0x85, 0xfe, 0x95, 0x40, 0x76, 0xc5, 0x16, 0x7c,
222        0x03, 0xbd, 0xe7, 0xcc, 0xda, 0xab, 0x00, 0x5e,
223        0x55, 0x36, 0x12, 0x2e, 0x18, 0xf7, 0x23, 0x7a,
224    ], 64);
225}
226
227impl Ihr {
228    /// Construct an IHR from its components: an IMR and the source and target types.
229    pub fn from_imr(imr: Imr, ty: &FinalArrow) -> Ihr {
230        bip340_iv(b"Simplicity\x1fIdentity")
231            .update_0_then_32(imr)
232            .zz_update_2x32(ty.source.tmr(), ty.target.tmr())
233            .into_merkle_root()
234    }
235}
236
237#[cfg(test)]
238mod tests {
239    use super::*;
240
241    #[test]
242    #[rustfmt::skip] // wants to split up the check_iv lines below
243    fn ivs() {
244        fn check_iv(target: Midstate, s: &'static str) {
245            let name = s
246                .trim_start_matches("Simplicity\x1f")
247                .trim_start_matches("Commitment\x1f")
248                .trim_start_matches("Identity\x1f");
249            // Uncomment this if the IVs ever change
250            /*
251            let target = Imr(bip340_iv(s.as_bytes()));
252            println!("    #[rustfmt::skip]");
253            println!("    const {}_IV: Midstate = Midstate::new([", name.to_ascii_uppercase());
254            print!("       "); for ch in &target.0[0..8] { print!(" 0x{:02x},", ch); }; println!();
255            print!("       "); for ch in &target.0[8..16] { print!(" 0x{:02x},", ch); }; println!();
256            print!("       "); for ch in &target.0[16..24] { print!(" 0x{:02x},", ch); }; println!();
257            print!("       "); for ch in &target.0[24..32] { print!(" 0x{:02x},", ch); }; println!();
258            println!("    ], 64);");
259            println!();
260            */
261            assert_eq!(target, bip340_iv(s.as_bytes()), "mismatch on IV for {}", name);
262        }
263
264        // Note that these are the same as those for CMRs **except** for disconnect and witness.
265        check_iv(Imr::IDEN_IV, "Simplicity\x1fCommitment\x1fiden");
266        check_iv(Imr::UNIT_IV, "Simplicity\x1fCommitment\x1funit");
267        check_iv(Imr::INJL_IV, "Simplicity\x1fCommitment\x1finjl");
268        check_iv(Imr::INJR_IV, "Simplicity\x1fCommitment\x1finjr");
269        check_iv(Imr::TAKE_IV, "Simplicity\x1fCommitment\x1ftake");
270        check_iv(Imr::DROP_IV, "Simplicity\x1fCommitment\x1fdrop");
271        check_iv(Imr::COMP_IV, "Simplicity\x1fCommitment\x1fcomp");
272        check_iv(Imr::CASE_IV, "Simplicity\x1fCommitment\x1fcase");
273        check_iv(Imr::PAIR_IV, "Simplicity\x1fCommitment\x1fpair");
274        check_iv(Imr::DISCONNECT_IV, "Simplicity\x1fIdentity\x1fdisconnect");
275        check_iv(Imr::WITNESS_IV, "Simplicity\x1fIdentity\x1fwitness");
276        check_iv(Imr::FAIL_IV, "Simplicity\x1fCommitment\x1ffail");
277    }
278}