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