1use crate::impl_midstate_wrapper;
4use crate::jet::Jet;
5use crate::types::arrow::FinalArrow;
6use crate::value::Word;
7use crate::{Cmr, Tmr, Value};
8use hashes::sha256::Midstate;
9
10use super::{bip340_iv, compact_value, FailEntropy};
11
12#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
18pub struct Imr(Midstate);
19
20impl_midstate_wrapper!(Imr);
21
22#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
29pub struct Ihr(Midstate);
30
31impl_midstate_wrapper!(Ihr);
32
33impl From<Cmr> for Imr {
34 fn from(cmr: Cmr) -> Self {
35 Imr::from_byte_array(cmr.to_byte_array())
36 }
37}
38
39impl From<Cmr> for Ihr {
40 fn from(cmr: Cmr) -> Self {
41 Ihr::from_byte_array(cmr.to_byte_array())
42 }
43}
44
45impl From<Tmr> for Ihr {
46 fn from(tmr: Tmr) -> Self {
47 Ihr::from_byte_array(tmr.to_byte_array())
48 }
49}
50
51impl Imr {
52 pub const fn iden() -> Self {
54 Self::IDEN_IV
55 }
56
57 pub const fn unit() -> Self {
59 Self::UNIT_IV
60 }
61
62 pub fn injl(child: Self) -> Self {
64 Self::INJL_IV.update_1(child)
65 }
66
67 pub fn injr(child: Self) -> Self {
69 Self::INJR_IV.update_1(child)
70 }
71
72 pub fn take(child: Self) -> Self {
74 Self::TAKE_IV.update_1(child)
75 }
76
77 pub fn drop(child: Self) -> Self {
79 Self::DROP_IV.update_1(child)
80 }
81
82 pub fn comp(left: Self, right: Self) -> Self {
84 Self::COMP_IV.update(left, right)
85 }
86
87 pub fn case(left: Self, right: Self) -> Self {
89 Self::CASE_IV.update(left, right)
90 }
91
92 pub fn pair(left: Self, right: Self) -> Self {
94 Self::PAIR_IV.update(left, right)
95 }
96
97 pub fn disconnect(left: Self, right: Self) -> Self {
99 Self::DISCONNECT_IV.update(left, right)
100 }
101
102 pub fn witness(ty: &FinalArrow, value: &Value) -> Self {
104 use hashes::{sha256, HashEngine};
105
106 let value_hash = compact_value(value);
108 let mut engine = sha256::HashEngine::from_midstate(Self::WITNESS_IV.0, 0);
110 engine.input(&value_hash[..]);
111 engine.input(ty.target.tmr().as_ref());
112 Self(engine.midstate())
113 }
114
115 pub fn fail(entropy: FailEntropy) -> Self {
117 Self::FAIL_IV.update_fail_entropy(entropy)
118 }
119
120 pub fn jet<J: Jet>(jet: J) -> Self {
122 Cmr::jet(jet).into()
123 }
124
125 pub fn const_word(word: &Word) -> Self {
130 Cmr::const_word(word).into()
131 }
132
133 #[rustfmt::skip]
134 const IDEN_IV: Self = Self(Midstate([
135 0x54, 0x1a, 0x1a, 0x69, 0xbd, 0x4b, 0xcb, 0xda,
136 0x7f, 0x34, 0x31, 0x0e, 0x30, 0x78, 0xf7, 0x26,
137 0x44, 0x31, 0x22, 0xfb, 0xcc, 0x1c, 0xb5, 0x36,
138 0x0c, 0x78, 0x64, 0xec, 0x0d, 0x32, 0x3a, 0xc0,
139 ]));
140
141 #[rustfmt::skip]
142 const UNIT_IV: Self = Self(Midstate([
143 0xc4, 0x0a, 0x10, 0x26, 0x3f, 0x74, 0x36, 0xb4,
144 0x16, 0x0a, 0xcb, 0xef, 0x1c, 0x36, 0xfb, 0xa4,
145 0xbe, 0x4d, 0x95, 0xdf, 0x18, 0x1a, 0x96, 0x8a,
146 0xfe, 0xab, 0x5e, 0xac, 0x24, 0x7a, 0xdf, 0xf7,
147 ]));
148
149 #[rustfmt::skip]
150 const INJL_IV: Self = Self(Midstate([
151 0x54, 0xe9, 0x1d, 0x18, 0xd8, 0xf8, 0x1f, 0x6d,
152 0x29, 0x86, 0xbb, 0x58, 0x47, 0x9a, 0x54, 0xeb,
153 0x63, 0x0e, 0x95, 0x23, 0xb6, 0x9e, 0xe8, 0x53,
154 0x29, 0x80, 0xd0, 0x55, 0x58, 0x19, 0x4f, 0x15,
155 ]));
156
157 #[rustfmt::skip]
158 const INJR_IV: Self = Self(Midstate([
159 0xd7, 0x0f, 0xfd, 0xce, 0x97, 0x77, 0x7b, 0x4d,
160 0xfe, 0x31, 0xfd, 0x9f, 0xf5, 0xd0, 0x17, 0xa6,
161 0x30, 0x5d, 0x7e, 0xc6, 0x0d, 0xf3, 0xb1, 0xbf,
162 0x6d, 0x25, 0xe8, 0x16, 0x33, 0xde, 0xd4, 0xbf,
163 ]));
164
165 #[rustfmt::skip]
166 const TAKE_IV: Self = Self(Midstate([
167 0x50, 0x5f, 0xc0, 0x81, 0xb5, 0xba, 0x2a, 0xcd,
168 0x09, 0x50, 0x67, 0xc3, 0xdf, 0xb8, 0xea, 0x12,
169 0x6f, 0xa1, 0x5d, 0x55, 0xcb, 0x21, 0x1e, 0x6a,
170 0xed, 0x34, 0xe8, 0xd1, 0xe3, 0x7a, 0xf0, 0xfa,
171 ]));
172
173 #[rustfmt::skip]
174 const DROP_IV: Self = Self(Midstate([
175 0x8a, 0x30, 0x8d, 0x38, 0xa1, 0x13, 0xa2, 0x60,
176 0xb4, 0xc7, 0x14, 0x5a, 0xbd, 0xc5, 0x22, 0x4d,
177 0xeb, 0x70, 0x13, 0x79, 0x59, 0x0e, 0x0c, 0x8c,
178 0x38, 0x86, 0x0b, 0xab, 0x12, 0x71, 0xa8, 0xa8,
179 ]));
180
181 #[rustfmt::skip]
182 const COMP_IV: Self = Self(Midstate([
183 0x57, 0xec, 0x23, 0xa2, 0xa4, 0x77, 0x8e, 0x01,
184 0x58, 0xa6, 0x21, 0x7a, 0xea, 0x3e, 0xf7, 0x42,
185 0x8b, 0xa0, 0x90, 0x92, 0x73, 0xb9, 0x73, 0xfa,
186 0x14, 0x32, 0xa9, 0x27, 0x84, 0x3e, 0x92, 0x7a,
187 ]));
188
189 #[rustfmt::skip]
190 const CASE_IV: Self = Self(Midstate([
191 0x29, 0x5e, 0x2a, 0x6d, 0xc8, 0xc5, 0xce, 0x59,
192 0xe4, 0xed, 0xcf, 0xe9, 0xb4, 0xd8, 0xf7, 0x64,
193 0x13, 0x3a, 0xa5, 0x51, 0x4b, 0xd3, 0xee, 0x8b,
194 0x4b, 0x75, 0xec, 0x8f, 0x4d, 0xeb, 0x08, 0xbe,
195 ]));
196
197 #[rustfmt::skip]
198 const PAIR_IV: Self = Self(Midstate([
199 0x7d, 0x5e, 0x6d, 0xac, 0x15, 0xb1, 0x42, 0x8a,
200 0x0d, 0x26, 0x0c, 0x94, 0x29, 0xdb, 0xe8, 0x89,
201 0x65, 0x93, 0xf3, 0x1f, 0x70, 0x86, 0x27, 0xee,
202 0x75, 0xb2, 0x7e, 0xee, 0xfd, 0xd0, 0x50, 0x05,
203 ]));
204
205 #[rustfmt::skip]
206 const DISCONNECT_IV: Self = Self(Midstate([
207 0x4e, 0xb7, 0x99, 0x5f, 0xb5, 0xdd, 0xe5, 0xd0,
208 0x85, 0xf4, 0x70, 0x85, 0xcd, 0x95, 0x3d, 0x16,
209 0x84, 0x54, 0x11, 0xed, 0xc6, 0x89, 0xe2, 0x7a,
210 0xf9, 0xc3, 0xde, 0xa2, 0xfb, 0x12, 0x25, 0xd5,
211 ]));
212
213 #[rustfmt::skip]
214 const WITNESS_IV: Self = Self(Midstate([
215 0xcb, 0x37, 0xff, 0x70, 0x01, 0xc6, 0x2d, 0x94,
216 0x42, 0x4f, 0x98, 0x7f, 0x30, 0x23, 0xb3, 0x5e,
217 0x30, 0xd2, 0x17, 0x23, 0x96, 0x27, 0x6f, 0x89,
218 0xd0, 0x9f, 0x07, 0xaa, 0x67, 0xb6, 0x21, 0x96,
219 ]));
220
221 #[rustfmt::skip]
222 const FAIL_IV: Self = Self(Midstate([
223 0x22, 0x83, 0xc1, 0x81, 0x9e, 0x69, 0x2f, 0x96,
224 0x85, 0xfe, 0x95, 0x40, 0x76, 0xc5, 0x16, 0x7c,
225 0x03, 0xbd, 0xe7, 0xcc, 0xda, 0xab, 0x00, 0x5e,
226 0x55, 0x36, 0x12, 0x2e, 0x18, 0xf7, 0x23, 0x7a,
227 ]));
228}
229
230impl Ihr {
231 pub fn from_imr(imr: Imr, ty: &FinalArrow) -> Ihr {
233 let iv = Ihr(bip340_iv(b"Simplicity\x1fIdentity"));
234 iv.update_1(Ihr(imr.0))
235 .update(ty.source.tmr().into(), ty.target.tmr().into())
236 }
237}
238
239#[cfg(test)]
240mod tests {
241 use super::*;
242
243 #[test]
244 #[rustfmt::skip] fn ivs() {
246 fn check_iv(target: Imr, s: &'static str) {
247 let name = s
248 .trim_start_matches("Simplicity\x1f")
249 .trim_start_matches("Commitment\x1f")
250 .trim_start_matches("Identity\x1f");
251 assert_eq!(target, Imr(bip340_iv(s.as_bytes())), "mismatch on IV for {}", name);
264 }
265
266 check_iv(Imr::IDEN_IV, "Simplicity\x1fCommitment\x1fiden");
268 check_iv(Imr::UNIT_IV, "Simplicity\x1fCommitment\x1funit");
269 check_iv(Imr::INJL_IV, "Simplicity\x1fCommitment\x1finjl");
270 check_iv(Imr::INJR_IV, "Simplicity\x1fCommitment\x1finjr");
271 check_iv(Imr::TAKE_IV, "Simplicity\x1fCommitment\x1ftake");
272 check_iv(Imr::DROP_IV, "Simplicity\x1fCommitment\x1fdrop");
273 check_iv(Imr::COMP_IV, "Simplicity\x1fCommitment\x1fcomp");
274 check_iv(Imr::CASE_IV, "Simplicity\x1fCommitment\x1fcase");
275 check_iv(Imr::PAIR_IV, "Simplicity\x1fCommitment\x1fpair");
276 check_iv(Imr::DISCONNECT_IV, "Simplicity\x1fIdentity\x1fdisconnect");
277 check_iv(Imr::WITNESS_IV, "Simplicity\x1fIdentity\x1fwitness");
278 check_iv(Imr::FAIL_IV, "Simplicity\x1fCommitment\x1ffail");
279 }
280}