1use 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 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
18 pub struct Imr([u8; 32]);
19}
20
21impl_mr_type! {
22 #[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 pub const fn iden() -> Self {
53 Self::from_byte_array(Self::IDEN_IV.to_parts().0)
54 }
55
56 pub const fn unit() -> Self {
58 Self::from_byte_array(Self::UNIT_IV.to_parts().0)
59 }
60
61 pub fn injl(child: Self) -> Self {
63 Self::INJL_IV.update_0_then_32(child).into_merkle_root()
64 }
65
66 pub fn injr(child: Self) -> Self {
68 Self::INJR_IV.update_0_then_32(child).into_merkle_root()
69 }
70
71 pub fn take(child: Self) -> Self {
73 Self::TAKE_IV.update_0_then_32(child).into_merkle_root()
74 }
75
76 pub fn drop(child: Self) -> Self {
78 Self::DROP_IV.update_0_then_32(child).into_merkle_root()
79 }
80
81 pub fn comp(left: Self, right: Self) -> Self {
83 Self::COMP_IV.zz_update_2x32(left, right).into_merkle_root()
84 }
85
86 pub fn case(left: Self, right: Self) -> Self {
88 Self::CASE_IV.zz_update_2x32(left, right).into_merkle_root()
89 }
90
91 pub fn pair(left: Self, right: Self) -> Self {
93 Self::PAIR_IV.zz_update_2x32(left, right).into_merkle_root()
94 }
95
96 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 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 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 pub fn jet(jet: &dyn Jet) -> Self {
119 Cmr::jet(jet).into()
120 }
121
122 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 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] 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 assert_eq!(target, bip340_iv(s.as_bytes()), "mismatch on IV for {}", name);
262 }
263
264 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}