1use crate::impl_midstate_wrapper;
4use crate::jet::Jet;
5use crate::node::{
6 CoreConstructible, DisconnectConstructible, JetConstructible, WitnessConstructible,
7};
8use crate::types::{self, Error};
9use crate::value::Word;
10use crate::{FailEntropy, Tmr};
11use hashes::sha256::Midstate;
12
13use super::bip340_iv;
14
15#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
24pub struct Cmr(pub(crate) Midstate);
25
26impl_midstate_wrapper!(Cmr);
27
28impl From<Tmr> for Cmr {
29 fn from(tmr: Tmr) -> Self {
30 Cmr::from_byte_array(tmr.to_byte_array())
31 }
32}
33
34impl Cmr {
35 pub const fn iden() -> Self {
37 Self::IDEN_IV
38 }
39
40 pub const fn unit() -> Self {
42 Self::UNIT_IV
43 }
44
45 pub fn injl(child: Cmr) -> Self {
47 Self::INJL_IV.update_1(child)
48 }
49
50 pub fn injr(child: Cmr) -> Self {
52 Self::INJR_IV.update_1(child)
53 }
54
55 pub fn take(child: Cmr) -> Self {
57 Self::TAKE_IV.update_1(child)
58 }
59
60 pub fn drop(child: Cmr) -> Self {
62 Self::DROP_IV.update_1(child)
63 }
64
65 pub fn comp(left: Cmr, right: Cmr) -> Self {
67 Self::COMP_IV.update(left, right)
68 }
69
70 pub fn case(left: Cmr, right: Cmr) -> Self {
72 Self::CASE_IV.update(left, right)
73 }
74
75 pub fn pair(left: Cmr, right: Cmr) -> Self {
77 Self::PAIR_IV.update(left, right)
78 }
79
80 pub fn disconnect(left: Cmr) -> Self {
82 Self::DISCONNECT_IV.update_1(left)
83 }
84
85 pub fn witness() -> Self {
87 Self::WITNESS_IV
88 }
89
90 pub fn fail(entropy: FailEntropy) -> Self {
92 Self::FAIL_IV.update_fail_entropy(entropy)
93 }
94
95 pub fn jet<J: Jet>(jet: J) -> Self {
97 jet.cmr()
98 }
99
100 pub fn const_word(word: &Word) -> Self {
105 let w = 1 + word.n() as usize;
106
107 let mut cmr_stack = Vec::with_capacity(33);
108 for (bit_idx, bit) in word.iter().enumerate() {
110 cmr_stack.push(Cmr::BITS[usize::from(bit)]);
111 let mut j = bit_idx;
112 while j & 1 == 1 {
113 let right_cmr = cmr_stack.pop().unwrap();
114 let left_cmr = cmr_stack.pop().unwrap();
115 cmr_stack.push(Cmr::PAIR_IV.update(left_cmr, right_cmr));
116 j >>= 1;
117 }
118 }
119 assert_eq!(cmr_stack.len(), 1);
120
121 let ihr_iv = Self::CONST_WORD_IV;
122 let ihr_pass1 = ihr_iv.update_1(cmr_stack[0]);
123 let ihr_pass2 = ihr_pass1.update(Tmr::unit().into(), Tmr::TWO_TWO_N[w - 1].into());
125 Cmr(bip340_iv(b"Simplicity\x1fJet")).update_with_weight(word.len() as u64, ihr_pass2)
127 }
128
129 #[rustfmt::skip]
130 const UNIT_IV: Cmr = Cmr(Midstate([
131 0xc4, 0x0a, 0x10, 0x26, 0x3f, 0x74, 0x36, 0xb4,
132 0x16, 0x0a, 0xcb, 0xef, 0x1c, 0x36, 0xfb, 0xa4,
133 0xbe, 0x4d, 0x95, 0xdf, 0x18, 0x1a, 0x96, 0x8a,
134 0xfe, 0xab, 0x5e, 0xac, 0x24, 0x7a, 0xdf, 0xf7,
135 ]));
136
137 #[rustfmt::skip]
138 const IDEN_IV: Cmr = Cmr(Midstate([
139 0x54, 0x1a, 0x1a, 0x69, 0xbd, 0x4b, 0xcb, 0xda,
140 0x7f, 0x34, 0x31, 0x0e, 0x30, 0x78, 0xf7, 0x26,
141 0x44, 0x31, 0x22, 0xfb, 0xcc, 0x1c, 0xb5, 0x36,
142 0x0c, 0x78, 0x64, 0xec, 0x0d, 0x32, 0x3a, 0xc0,
143 ]));
144
145 #[rustfmt::skip]
146 const INJL_IV: Cmr = Cmr(Midstate([
147 0x54, 0xe9, 0x1d, 0x18, 0xd8, 0xf8, 0x1f, 0x6d,
148 0x29, 0x86, 0xbb, 0x58, 0x47, 0x9a, 0x54, 0xeb,
149 0x63, 0x0e, 0x95, 0x23, 0xb6, 0x9e, 0xe8, 0x53,
150 0x29, 0x80, 0xd0, 0x55, 0x58, 0x19, 0x4f, 0x15,
151 ]));
152
153 #[rustfmt::skip]
154 const INJR_IV: Cmr = Cmr(Midstate([
155 0xd7, 0x0f, 0xfd, 0xce, 0x97, 0x77, 0x7b, 0x4d,
156 0xfe, 0x31, 0xfd, 0x9f, 0xf5, 0xd0, 0x17, 0xa6,
157 0x30, 0x5d, 0x7e, 0xc6, 0x0d, 0xf3, 0xb1, 0xbf,
158 0x6d, 0x25, 0xe8, 0x16, 0x33, 0xde, 0xd4, 0xbf,
159 ]));
160
161 #[rustfmt::skip]
162 const TAKE_IV: Cmr = Cmr(Midstate([
163 0x50, 0x5f, 0xc0, 0x81, 0xb5, 0xba, 0x2a, 0xcd,
164 0x09, 0x50, 0x67, 0xc3, 0xdf, 0xb8, 0xea, 0x12,
165 0x6f, 0xa1, 0x5d, 0x55, 0xcb, 0x21, 0x1e, 0x6a,
166 0xed, 0x34, 0xe8, 0xd1, 0xe3, 0x7a, 0xf0, 0xfa,
167 ]));
168
169 #[rustfmt::skip]
170 const DROP_IV: Cmr = Cmr(Midstate([
171 0x8a, 0x30, 0x8d, 0x38, 0xa1, 0x13, 0xa2, 0x60,
172 0xb4, 0xc7, 0x14, 0x5a, 0xbd, 0xc5, 0x22, 0x4d,
173 0xeb, 0x70, 0x13, 0x79, 0x59, 0x0e, 0x0c, 0x8c,
174 0x38, 0x86, 0x0b, 0xab, 0x12, 0x71, 0xa8, 0xa8,
175 ]));
176
177 #[rustfmt::skip]
178 const COMP_IV: Cmr = Cmr(Midstate([
179 0x57, 0xec, 0x23, 0xa2, 0xa4, 0x77, 0x8e, 0x01,
180 0x58, 0xa6, 0x21, 0x7a, 0xea, 0x3e, 0xf7, 0x42,
181 0x8b, 0xa0, 0x90, 0x92, 0x73, 0xb9, 0x73, 0xfa,
182 0x14, 0x32, 0xa9, 0x27, 0x84, 0x3e, 0x92, 0x7a,
183 ]));
184
185 #[rustfmt::skip]
186 const CASE_IV: Cmr = Cmr(Midstate([
187 0x29, 0x5e, 0x2a, 0x6d, 0xc8, 0xc5, 0xce, 0x59,
188 0xe4, 0xed, 0xcf, 0xe9, 0xb4, 0xd8, 0xf7, 0x64,
189 0x13, 0x3a, 0xa5, 0x51, 0x4b, 0xd3, 0xee, 0x8b,
190 0x4b, 0x75, 0xec, 0x8f, 0x4d, 0xeb, 0x08, 0xbe,
191 ]));
192
193 #[rustfmt::skip]
194 const PAIR_IV: Cmr = Cmr(Midstate([
195 0x7d, 0x5e, 0x6d, 0xac, 0x15, 0xb1, 0x42, 0x8a,
196 0x0d, 0x26, 0x0c, 0x94, 0x29, 0xdb, 0xe8, 0x89,
197 0x65, 0x93, 0xf3, 0x1f, 0x70, 0x86, 0x27, 0xee,
198 0x75, 0xb2, 0x7e, 0xee, 0xfd, 0xd0, 0x50, 0x05,
199 ]));
200
201 #[rustfmt::skip]
202 const DISCONNECT_IV: Cmr = Cmr(Midstate([
203 0x35, 0x33, 0x8b, 0x5b, 0x81, 0x74, 0x0c, 0x6d,
204 0x67, 0xdc, 0x1e, 0xa3, 0xc8, 0x31, 0xe4, 0xc0,
205 0xaf, 0xd8, 0x64, 0x09, 0xbc, 0x04, 0xd0, 0xdd,
206 0x43, 0x24, 0xb7, 0xd9, 0xd5, 0x83, 0xf4, 0xeb,
207 ]));
208
209 #[rustfmt::skip]
210 const WITNESS_IV: Cmr = Cmr(Midstate([
211 0xa0, 0xfc, 0x8d, 0xeb, 0xd6, 0x79, 0x69, 0x17,
212 0xc8, 0x6b, 0x77, 0xad, 0xed, 0x82, 0xe6, 0xc6,
213 0x16, 0x49, 0x88, 0x9a, 0xe8, 0xf2, 0xed, 0x65,
214 0xb5, 0x7b, 0x41, 0xaa, 0x9d, 0x90, 0xe3, 0x75,
215 ]));
216
217 #[rustfmt::skip]
218 const FAIL_IV: Cmr = Cmr(Midstate([
219 0x22, 0x83, 0xc1, 0x81, 0x9e, 0x69, 0x2f, 0x96,
220 0x85, 0xfe, 0x95, 0x40, 0x76, 0xc5, 0x16, 0x7c,
221 0x03, 0xbd, 0xe7, 0xcc, 0xda, 0xab, 0x00, 0x5e,
222 0x55, 0x36, 0x12, 0x2e, 0x18, 0xf7, 0x23, 0x7a,
223 ]));
224
225 #[rustfmt::skip]
226 const CONST_WORD_IV: Cmr = Cmr(Midstate([
227 0x0c, 0x5b, 0xc1, 0xce, 0xc8, 0xf1, 0x41, 0x85,
228 0x0e, 0x33, 0x3e, 0x28, 0xea, 0x01, 0xc0, 0x5a,
229 0xc6, 0x42, 0xeb, 0x30, 0xb4, 0x9e, 0x69, 0x2c,
230 0x56, 0xb1, 0x22, 0xbb, 0x69, 0x49, 0xc5, 0xcd,
231 ]));
232
233 #[rustfmt::skip]
235 const BITS: [Cmr; 2] = [
236 Cmr(Midstate([
237 0x88, 0x81, 0xaf, 0xf5, 0x16, 0x0c, 0xc0, 0xc9,
238 0xf8, 0xec, 0xea, 0xd8, 0xb4, 0x01, 0xfa, 0x97,
239 0xee, 0xf5, 0xfc, 0x60, 0x75, 0x2e, 0x98, 0xd2,
240 0x47, 0x56, 0x1a, 0x4d, 0xa6, 0xce, 0x96, 0x5e,
241 ])),
242 Cmr(Midstate([
243 0xa0, 0x43, 0x8b, 0x72, 0x36, 0x48, 0x72, 0x7b,
244 0x3f, 0x2d, 0x18, 0x5f, 0xcd, 0x95, 0x69, 0xe0,
245 0x22, 0xa4, 0x47, 0x8e, 0xb2, 0x5f, 0xdf, 0xa5,
246 0x38, 0xea, 0xc5, 0x9d, 0x81, 0x7c, 0x31, 0x1c,
247 ])),
248 ];
249}
250
251pub struct ConstructibleCmr<'brand> {
255 pub cmr: Cmr,
256 pub inference_context: types::Context<'brand>,
257}
258
259impl<'brand> CoreConstructible<'brand> for ConstructibleCmr<'brand> {
260 fn iden(inference_context: &types::Context<'brand>) -> Self {
261 ConstructibleCmr {
262 cmr: Cmr::iden(),
263 inference_context: inference_context.shallow_clone(),
264 }
265 }
266
267 fn unit(inference_context: &types::Context<'brand>) -> Self {
268 ConstructibleCmr {
269 cmr: Cmr::unit(),
270 inference_context: inference_context.shallow_clone(),
271 }
272 }
273
274 fn injl(child: &Self) -> Self {
275 ConstructibleCmr {
276 cmr: Cmr::injl(child.cmr),
277 inference_context: child.inference_context.shallow_clone(),
278 }
279 }
280
281 fn injr(child: &Self) -> Self {
282 ConstructibleCmr {
283 cmr: Cmr::injl(child.cmr),
284 inference_context: child.inference_context.shallow_clone(),
285 }
286 }
287
288 fn take(child: &Self) -> Self {
289 ConstructibleCmr {
290 cmr: Cmr::take(child.cmr),
291 inference_context: child.inference_context.shallow_clone(),
292 }
293 }
294
295 fn drop_(child: &Self) -> Self {
296 ConstructibleCmr {
297 cmr: Cmr::drop(child.cmr),
298 inference_context: child.inference_context.shallow_clone(),
299 }
300 }
301
302 fn comp(left: &Self, right: &Self) -> Result<Self, Error> {
303 left.inference_context.check_eq(&right.inference_context)?;
304 Ok(ConstructibleCmr {
305 cmr: Cmr::comp(left.cmr, right.cmr),
306 inference_context: left.inference_context.shallow_clone(),
307 })
308 }
309
310 fn case(left: &Self, right: &Self) -> Result<Self, Error> {
311 left.inference_context.check_eq(&right.inference_context)?;
312 Ok(ConstructibleCmr {
313 cmr: Cmr::case(left.cmr, right.cmr),
314 inference_context: left.inference_context.shallow_clone(),
315 })
316 }
317
318 fn assertl(left: &Self, right: Cmr) -> Result<Self, Error> {
319 Ok(ConstructibleCmr {
320 cmr: Cmr::case(left.cmr, right),
321 inference_context: left.inference_context.shallow_clone(),
322 })
323 }
324
325 fn assertr(left: Cmr, right: &Self) -> Result<Self, Error> {
326 Ok(ConstructibleCmr {
327 cmr: Cmr::case(left, right.cmr),
328 inference_context: right.inference_context.shallow_clone(),
329 })
330 }
331
332 fn pair(left: &Self, right: &Self) -> Result<Self, Error> {
333 left.inference_context.check_eq(&right.inference_context)?;
334 Ok(ConstructibleCmr {
335 cmr: Cmr::pair(left.cmr, right.cmr),
336 inference_context: left.inference_context.shallow_clone(),
337 })
338 }
339
340 fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self {
341 ConstructibleCmr {
342 cmr: Cmr::fail(entropy),
343 inference_context: inference_context.shallow_clone(),
344 }
345 }
346
347 fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self {
348 ConstructibleCmr {
349 cmr: Cmr::const_word(&word),
350 inference_context: inference_context.shallow_clone(),
351 }
352 }
353
354 fn inference_context(&self) -> &types::Context<'brand> {
355 &self.inference_context
356 }
357}
358
359impl<'brand, X> DisconnectConstructible<'brand, X> for ConstructibleCmr<'brand> {
360 fn disconnect(left: &Self, _right: &X) -> Result<Self, Error> {
365 Ok(ConstructibleCmr {
366 cmr: Cmr::disconnect(left.cmr),
367 inference_context: left.inference_context.shallow_clone(),
368 })
369 }
370}
371
372impl<'brand, W> WitnessConstructible<'brand, W> for ConstructibleCmr<'brand> {
373 fn witness(inference_context: &types::Context<'brand>, _witness: W) -> Self {
374 ConstructibleCmr {
375 cmr: Cmr::witness(),
376 inference_context: inference_context.shallow_clone(),
377 }
378 }
379}
380
381impl<'brand, J: Jet> JetConstructible<'brand, J> for ConstructibleCmr<'brand> {
382 fn jet(inference_context: &types::Context<'brand>, jet: J) -> Self {
383 ConstructibleCmr {
384 cmr: jet.cmr(),
385 inference_context: inference_context.shallow_clone(),
386 }
387 }
388}
389
390#[cfg(test)]
391mod tests {
392 use super::*;
393
394 use crate::jet::Core;
395 use crate::node::{ConstructNode, CoreConstructible};
396
397 use std::str::FromStr;
398 use std::sync::Arc;
399
400 #[test]
401 fn cmr_display_unit() {
402 types::Context::with_context(|ctx| {
403 let c = Arc::<ConstructNode<Core>>::unit(&ctx);
404
405 assert_eq!(
406 c.cmr().to_string(),
407 "c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7"
408 );
409 assert_eq!(format!("{:.8}", c.cmr()), "c40a1026");
410
411 assert_eq!(
412 Cmr::from_str("c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7"),
413 Ok(c.cmr()),
414 );
415 });
416 }
417
418 #[test]
419 fn fixed_const_word_cmr() {
420 let bit0 = Word::u1(0);
422 #[rustfmt::skip]
423 assert_eq!(
424 Cmr::const_word(&bit0),
425 Cmr::from_str("a51cfd799d0bc368f48208032fc3881953f35aa7fd2b985cb237cbad143e30d2").unwrap(),
426 );
427 }
428
429 #[test]
430 fn bit_cmr() {
431 types::Context::with_context(|ctx| {
432 let unit = Arc::<ConstructNode<Core>>::unit(&ctx);
433 let bit0 = Arc::<ConstructNode<Core>>::injl(&unit);
434 assert_eq!(bit0.cmr(), Cmr::BITS[0]);
435
436 let bit1 = Arc::<ConstructNode<_>>::injr(&unit);
437 assert_eq!(bit1.cmr(), Cmr::BITS[1]);
438 });
439 }
440
441 #[test]
442 fn ivs() {
443 fn check_iv(target: Cmr, s: &'static str) {
444 let name = s
445 .trim_start_matches("Simplicity\x1f")
446 .strip_prefix("Commitment\x1f")
447 .unwrap_or("const_word");
448 assert_eq!(
461 target,
462 Cmr(bip340_iv(s.as_bytes())),
463 "mismatch on IV for {}",
464 name
465 );
466 }
467
468 check_iv(Cmr::UNIT_IV, "Simplicity\x1fCommitment\x1funit");
469 check_iv(Cmr::IDEN_IV, "Simplicity\x1fCommitment\x1fiden");
470 check_iv(Cmr::INJL_IV, "Simplicity\x1fCommitment\x1finjl");
471 check_iv(Cmr::INJR_IV, "Simplicity\x1fCommitment\x1finjr");
472 check_iv(Cmr::TAKE_IV, "Simplicity\x1fCommitment\x1ftake");
473 check_iv(Cmr::DROP_IV, "Simplicity\x1fCommitment\x1fdrop");
474 check_iv(Cmr::COMP_IV, "Simplicity\x1fCommitment\x1fcomp");
475 check_iv(Cmr::CASE_IV, "Simplicity\x1fCommitment\x1fcase");
476 check_iv(Cmr::PAIR_IV, "Simplicity\x1fCommitment\x1fpair");
477 check_iv(Cmr::DISCONNECT_IV, "Simplicity\x1fCommitment\x1fdisconnect");
478 check_iv(Cmr::WITNESS_IV, "Simplicity\x1fCommitment\x1fwitness");
479 check_iv(Cmr::FAIL_IV, "Simplicity\x1fCommitment\x1ffail");
480 check_iv(Cmr::CONST_WORD_IV, "Simplicity\x1fIdentity");
481 }
482
483 #[test]
484 fn const_bits() {
485 fn scribe<'brand>(
487 ctx: &types::Context<'brand>,
488 bit: u8,
489 ) -> Arc<ConstructNode<'brand, Core>> {
490 match bit {
491 0 => Arc::<ConstructNode<Core>>::injl(&Arc::<ConstructNode<Core>>::unit(ctx)),
492 1 => Arc::<ConstructNode<Core>>::injr(&Arc::<ConstructNode<Core>>::unit(ctx)),
493 _ => panic!("Unexpected bit {bit}"),
494 }
495 }
496
497 fn check_bit(target: Cmr, index: u8) {
498 types::Context::with_context(|ctx| {
509 assert_eq!(
510 target,
511 scribe(&ctx, index).cmr(),
512 "mismatch on CMR for bit {index}",
513 );
514 });
515 }
516
517 for index in 0..2u8 {
518 check_bit(Cmr::BITS[usize::from(index)], index)
519 }
520 }
521}