1use crate::jet::Jet;
4use crate::merkle::compact_value;
5use crate::types::FinalArrow;
6use crate::value::Word;
7use crate::{Cmr, Tmr, Value};
8use hashes::sha256::Midstate;
9
10use super::{impl_mr_type, FailEntropy, MidstateExt as _};
11
12impl_mr_type! {
13 #[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
20 pub struct Amr([u8; 32]);
21}
22
23impl From<Cmr> for Amr {
24 fn from(cmr: Cmr) -> Self {
25 Amr::from_byte_array(cmr.to_byte_array())
26 }
27}
28
29impl From<Tmr> for Amr {
30 fn from(tmr: Tmr) -> Self {
31 Amr::from_byte_array(tmr.to_byte_array())
32 }
33}
34
35impl Amr {
36 pub fn iden(ty: &FinalArrow) -> Self {
38 let a = &ty.source;
39 Self::IDEN_IV.update_0_then_32(a.tmr()).into_merkle_root()
40 }
41
42 pub fn unit(ty: &FinalArrow) -> Self {
44 let a = &ty.source;
45 Self::UNIT_IV.update_0_then_32(a.tmr()).into_merkle_root()
46 }
47
48 pub fn injl(ty: &FinalArrow, child: Amr) -> Self {
50 let a = &ty.source;
51 let (b, c) = ty.target.as_sum().unwrap();
52 Self::INJL_IV
53 .zz_update_2x32(a.tmr(), b.tmr())
54 .zz_update_2x32(c.tmr(), child)
55 .into_merkle_root()
56 }
57
58 pub fn injr(ty: &FinalArrow, child: Amr) -> Self {
60 let a = &ty.source;
61 let (b, c) = ty.target.as_sum().unwrap();
62 Self::INJR_IV
63 .zz_update_2x32(a.tmr(), b.tmr())
64 .zz_update_2x32(c.tmr(), child)
65 .into_merkle_root()
66 }
67
68 pub fn take(ty: &FinalArrow, child: Amr) -> Self {
70 let (a, b) = ty.source.as_product().unwrap();
71 let c = &ty.target;
72 Self::TAKE_IV
73 .zz_update_2x32(a.tmr(), b.tmr())
74 .zz_update_2x32(c.tmr(), child)
75 .into_merkle_root()
76 }
77
78 pub fn drop(ty: &FinalArrow, child: Amr) -> Self {
80 let (a, b) = ty.source.as_product().unwrap();
81 let c = &ty.target;
82 Self::DROP_IV
83 .zz_update_2x32(a.tmr(), b.tmr())
84 .zz_update_2x32(c.tmr(), child)
85 .into_merkle_root()
86 }
87
88 pub fn comp(ty: &FinalArrow, left_arrow: &FinalArrow, left: Amr, right: Amr) -> Self {
90 let a = &ty.source;
91 let b = &left_arrow.target;
92 let c = &ty.target;
93 Self::COMP_IV
94 .update_0_then_32(a.tmr())
95 .zz_update_2x32(b.tmr(), c.tmr())
96 .zz_update_2x32(left, right)
97 .into_merkle_root()
98 }
99
100 fn case_helper(iv: Midstate, ty: &FinalArrow, left: Amr, right: Amr) -> Self {
101 let (sum_a_b, c) = ty.source.as_product().unwrap();
102 let (a, b) = sum_a_b.as_sum().unwrap();
103 let d = &ty.target;
104 iv.zz_update_2x32(a.tmr(), b.tmr())
105 .zz_update_2x32(c.tmr(), d.tmr())
106 .zz_update_2x32(left, right)
107 .into_merkle_root()
108 }
109
110 pub fn case(ty: &FinalArrow, left: Amr, right: Amr) -> Self {
112 Self::case_helper(Self::CASE_IV, ty, left, right)
113 }
114
115 pub fn assertl(ty: &FinalArrow, left: Amr, right: Amr) -> Self {
117 Self::case_helper(Self::ASSERTL_IV, ty, left, right)
118 }
119
120 pub fn assertr(ty: &FinalArrow, left: Amr, right: Amr) -> Self {
122 Self::case_helper(Self::ASSERTR_IV, ty, left, right)
123 }
124
125 pub fn pair(
127 ty: &FinalArrow,
128 left_arrow: &FinalArrow,
129 right_arrow: &FinalArrow,
130 left: Amr,
131 right: Amr,
132 ) -> Self {
133 let a = &ty.source;
134 let b = &left_arrow.target;
135 let c = &right_arrow.target;
136 Self::PAIR_IV
137 .update_0_then_32(a.tmr())
138 .zz_update_2x32(b.tmr(), c.tmr())
139 .zz_update_2x32(left, right)
140 .into_merkle_root()
141 }
142
143 pub fn disconnect(ty: &FinalArrow, right_arrow: &FinalArrow, left: Amr, right: Amr) -> Self {
145 let a = &ty.source;
146 let (b, d) = ty.target.as_product().unwrap();
147 let c = &right_arrow.source;
148 Self::DISCONNECT_IV
149 .zz_update_2x32(a.tmr(), b.tmr())
150 .zz_update_2x32(c.tmr(), d.tmr())
151 .zz_update_2x32(left, right)
152 .into_merkle_root()
153 }
154
155 pub fn witness(ty: &FinalArrow, value: &Value) -> Self {
157 let a = &ty.source;
158 let b = &ty.target;
159 Self::WITNESS_IV
160 .update_0_then_32(a.tmr())
161 .zz_update_2x32(b.tmr(), compact_value(value))
162 .into_merkle_root()
163 }
164
165 pub fn fail(entropy: FailEntropy) -> Self {
167 Self::FAIL_IV
168 .zz_update_64(entropy.to_byte_array())
169 .into_merkle_root()
170 }
171
172 pub fn jet(jet: &dyn Jet) -> Self {
174 Cmr::jet(jet).into()
175 }
176
177 pub fn const_word(word: &Word) -> Self {
182 Cmr::const_word(word).into()
183 }
184
185 #[rustfmt::skip]
186 const IDEN_IV: Midstate = Midstate::new([
187 0x45, 0x1f, 0x68, 0x8c, 0x41, 0x50, 0x99, 0x68,
188 0x3a, 0x8d, 0x36, 0xa7, 0x09, 0xba, 0x42, 0x49,
189 0xe6, 0xde, 0xf7, 0x1b, 0x35, 0x29, 0xb4, 0xc1,
190 0xf2, 0xe4, 0xd5, 0x63, 0x85, 0x54, 0x91, 0xaf,
191 ], 64);
192
193 #[rustfmt::skip]
194 const UNIT_IV: Midstate = Midstate::new([
195 0xdb, 0xfe, 0xe7, 0x84, 0x3b, 0x59, 0x1e, 0x8f,
196 0x7c, 0xe4, 0x85, 0xdc, 0xb5, 0xd6, 0x6b, 0xcc,
197 0x23, 0x98, 0x48, 0x10, 0xbd, 0x6b, 0xe5, 0x2a,
198 0xa7, 0x6e, 0xaf, 0x2b, 0x25, 0xcb, 0x44, 0x23,
199 ], 64);
200
201 #[rustfmt::skip]
202 const INJL_IV: Midstate = Midstate::new([
203 0xba, 0xcb, 0x63, 0x56, 0x69, 0x80, 0xdc, 0xac,
204 0x45, 0x59, 0x1f, 0x5a, 0xef, 0x0d, 0x91, 0xd4,
205 0x9e, 0xa4, 0xc1, 0xe0, 0x07, 0x2b, 0x1c, 0xe3,
206 0xdd, 0x20, 0x75, 0x21, 0xc9, 0xea, 0xd8, 0x08,
207 ], 64);
208
209 #[rustfmt::skip]
210 const INJR_IV: Midstate = Midstate::new([
211 0x7b, 0x11, 0x6e, 0xbc, 0x3f, 0x90, 0x9e, 0xef,
212 0x13, 0x87, 0x98, 0x71, 0x99, 0x84, 0x4b, 0x91,
213 0xbc, 0xc7, 0x40, 0x2c, 0x24, 0x30, 0xc4, 0x85,
214 0x29, 0x75, 0xd4, 0x8f, 0x49, 0x0c, 0x54, 0x7a,
215 ], 64);
216
217 #[rustfmt::skip]
218 const TAKE_IV: Midstate = Midstate::new([
219 0x41, 0x75, 0xa1, 0x34, 0xe6, 0xb4, 0xd1, 0x5b,
220 0xb4, 0x8a, 0xc5, 0x82, 0xd9, 0xbc, 0x83, 0xa2,
221 0x94, 0x84, 0xc7, 0xec, 0x27, 0x00, 0x4d, 0xff,
222 0x94, 0xaa, 0xe4, 0xcb, 0x5d, 0x87, 0x6f, 0xb6,
223 ], 64);
224
225 #[rustfmt::skip]
226 const DROP_IV: Midstate = Midstate::new([
227 0x3b, 0x32, 0x93, 0xab, 0xbc, 0xc9, 0xb9, 0xdb,
228 0xe1, 0xbd, 0x70, 0xa3, 0x31, 0x5f, 0x38, 0xff,
229 0x26, 0x05, 0xfb, 0x30, 0xe3, 0x1f, 0x3c, 0xee,
230 0x7b, 0x25, 0x1a, 0x88, 0x31, 0xc1, 0x56, 0x89,
231 ], 64);
232
233 #[rustfmt::skip]
234 const COMP_IV: Midstate = Midstate::new([
235 0x73, 0x7f, 0xd0, 0x53, 0x08, 0xd6, 0x05, 0x00,
236 0x3b, 0xde, 0x8e, 0xb2, 0x0a, 0x3b, 0x93, 0x97,
237 0xc1, 0xda, 0xaa, 0xe5, 0x43, 0xd8, 0xa4, 0xe4,
238 0xfe, 0xef, 0x48, 0x38, 0x76, 0x85, 0x93, 0x84,
239 ], 64);
240
241 #[rustfmt::skip]
242 const CASE_IV: Midstate = Midstate::new([
243 0x59, 0x58, 0x14, 0xf9, 0xe0, 0xc8, 0x89, 0xb4,
244 0x84, 0x7a, 0xba, 0x1d, 0x51, 0xe1, 0x4e, 0x04,
245 0x8f, 0x95, 0x34, 0x4b, 0x2a, 0x43, 0x20, 0x91,
246 0xf8, 0x1b, 0xd3, 0xb8, 0x36, 0xec, 0x35, 0x04,
247 ], 64);
248
249 #[rustfmt::skip]
250 const ASSERTL_IV: Midstate = Midstate::new([
251 0xd5, 0xdd, 0xd7, 0x41, 0xd7, 0x27, 0xe2, 0x20,
252 0x35, 0x56, 0xb0, 0xf8, 0xba, 0x4f, 0x7f, 0xd0,
253 0xb4, 0x8f, 0x8d, 0xbf, 0x7a, 0x85, 0x84, 0x87,
254 0x9b, 0xab, 0xa8, 0xd6, 0xec, 0xaa, 0x43, 0xef,
255 ], 64);
256
257 #[rustfmt::skip]
258 const ASSERTR_IV: Midstate = Midstate::new([
259 0xc5, 0xfe, 0xcd, 0x9c, 0xad, 0xc1, 0x6a, 0x7a,
260 0x08, 0xcf, 0x21, 0x5a, 0xe7, 0x58, 0x40, 0xf6,
261 0xd2, 0x05, 0xe7, 0xaa, 0x27, 0xf6, 0xff, 0xf2,
262 0x6b, 0xfa, 0x1e, 0x6b, 0x3a, 0x0f, 0x76, 0xfa,
263 ], 64);
264
265 #[rustfmt::skip]
266 const PAIR_IV: Midstate = Midstate::new([
267 0x79, 0x96, 0xb3, 0xbf, 0xa6, 0x03, 0x36, 0x73,
268 0x25, 0x15, 0xa1, 0x24, 0x3f, 0x6b, 0x3c, 0x23,
269 0x6b, 0xff, 0x0e, 0xb0, 0x66, 0x2f, 0x8a, 0xdd,
270 0x54, 0xaf, 0x0c, 0x98, 0xd1, 0xfd, 0xdd, 0xa7,
271 ], 64);
272
273 #[rustfmt::skip]
274 const DISCONNECT_IV: Midstate = Midstate::new([
275 0x27, 0xeb, 0xbc, 0xaa, 0x5a, 0x53, 0x7c, 0x25,
276 0xd8, 0xbb, 0x43, 0x40, 0x37, 0xbb, 0x2f, 0xff,
277 0x6b, 0x88, 0x15, 0x35, 0x43, 0x5e, 0x6d, 0x60,
278 0xa5, 0xf8, 0x5c, 0xd0, 0xf0, 0x5a, 0x61, 0x47,
279 ], 64);
280
281 #[rustfmt::skip]
282 const WITNESS_IV: Midstate = Midstate::new([
283 0x6b, 0xc6, 0x20, 0xcb, 0x52, 0xf9, 0x0c, 0x63,
284 0x0e, 0xf8, 0xc8, 0x0d, 0x5f, 0x69, 0x0d, 0xb4,
285 0xe9, 0x93, 0x0a, 0xd0, 0xfa, 0x70, 0x71, 0x36,
286 0x5b, 0x5c, 0x93, 0xe0, 0x39, 0x1b, 0xd7, 0x96,
287 ], 64);
288
289 #[rustfmt::skip]
290 const FAIL_IV: Midstate = Midstate::new([
291 0x36, 0x9c, 0xdd, 0x29, 0x3f, 0xd5, 0x8a, 0x85,
292 0xa5, 0x90, 0x38, 0x0f, 0x12, 0x20, 0x7e, 0x18,
293 0x10, 0x02, 0x0d, 0x39, 0x1c, 0x46, 0xd1, 0xab,
294 0xbe, 0xb2, 0x12, 0x2e, 0xa2, 0xfd, 0x55, 0xec,
295 ], 64);
296}
297
298#[cfg(test)]
299mod tests {
300 use super::super::bip340_iv;
301 use super::*;
302
303 use crate::jet::Core;
304 use crate::node::{ConstructNode, CoreConstructible as _};
305 use crate::types;
306 use std::sync::Arc;
307
308 #[test]
309 fn fixed_amr() {
310 types::Context::with_context(|ctx| {
311 let node = Arc::<ConstructNode>::jet(&ctx, &Core::Verify)
312 .finalize_types_non_program()
313 .unwrap();
314 #[rustfmt::skip]
316 assert_eq!(
317 &node.amr().unwrap().to_string(),
318 "cdca2a05e52cefa59dc7a5b0dae22098fb896e3913bfdd446b594e1f9250783e"
319 );
320 });
321 }
322
323 #[test]
324 fn ivs() {
325 fn check_iv(target: Midstate, s: &'static str) {
326 let name = s.trim_start_matches("Simplicity\x1fAnnotated\x1f");
327 assert_eq!(
340 target,
341 bip340_iv(s.as_bytes()),
342 "mismatch on IV for {}",
343 name
344 );
345 }
346
347 check_iv(Amr::IDEN_IV, "Simplicity\x1fAnnotated\x1fiden");
348 check_iv(Amr::UNIT_IV, "Simplicity\x1fAnnotated\x1funit");
349 check_iv(Amr::INJL_IV, "Simplicity\x1fAnnotated\x1finjl");
350 check_iv(Amr::INJR_IV, "Simplicity\x1fAnnotated\x1finjr");
351 check_iv(Amr::TAKE_IV, "Simplicity\x1fAnnotated\x1ftake");
352 check_iv(Amr::DROP_IV, "Simplicity\x1fAnnotated\x1fdrop");
353 check_iv(Amr::COMP_IV, "Simplicity\x1fAnnotated\x1fcomp");
354 check_iv(Amr::CASE_IV, "Simplicity\x1fAnnotated\x1fcase");
355 check_iv(Amr::ASSERTL_IV, "Simplicity\x1fAnnotated\x1fassertl");
356 check_iv(Amr::ASSERTR_IV, "Simplicity\x1fAnnotated\x1fassertr");
357 check_iv(Amr::PAIR_IV, "Simplicity\x1fAnnotated\x1fpair");
358 check_iv(Amr::DISCONNECT_IV, "Simplicity\x1fAnnotated\x1fdisconnect");
359 check_iv(Amr::WITNESS_IV, "Simplicity\x1fAnnotated\x1fwitness");
360 check_iv(Amr::FAIL_IV, "Simplicity\x1fAnnotated\x1ffail");
361 }
362}