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(jet: &dyn Jet) -> 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> JetConstructible<'brand> for ConstructibleCmr<'brand> {
382 fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> 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::node::{ConstructNode, CoreConstructible};
395
396 use std::str::FromStr;
397 use std::sync::Arc;
398
399 #[test]
400 fn cmr_display_unit() {
401 types::Context::with_context(|ctx| {
402 let c = Arc::<ConstructNode>::unit(&ctx);
403
404 assert_eq!(
405 c.cmr().to_string(),
406 "c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7"
407 );
408 assert_eq!(format!("{:.8}", c.cmr()), "c40a1026");
409
410 assert_eq!(
411 Cmr::from_str("c40a10263f7436b4160acbef1c36fba4be4d95df181a968afeab5eac247adff7"),
412 Ok(c.cmr()),
413 );
414 });
415 }
416
417 #[test]
418 fn fixed_const_word_cmr() {
419 let bit0 = Word::u1(0);
421 #[rustfmt::skip]
422 assert_eq!(
423 Cmr::const_word(&bit0),
424 Cmr::from_str("a51cfd799d0bc368f48208032fc3881953f35aa7fd2b985cb237cbad143e30d2").unwrap(),
425 );
426 }
427
428 #[test]
429 fn bit_cmr() {
430 types::Context::with_context(|ctx| {
431 let unit = Arc::<ConstructNode>::unit(&ctx);
432 let bit0 = Arc::<ConstructNode>::injl(&unit);
433 assert_eq!(bit0.cmr(), Cmr::BITS[0]);
434
435 let bit1 = Arc::<ConstructNode>::injr(&unit);
436 assert_eq!(bit1.cmr(), Cmr::BITS[1]);
437 });
438 }
439
440 #[test]
441 fn ivs() {
442 fn check_iv(target: Cmr, s: &'static str) {
443 let name = s
444 .trim_start_matches("Simplicity\x1f")
445 .strip_prefix("Commitment\x1f")
446 .unwrap_or("const_word");
447 assert_eq!(
460 target,
461 Cmr(bip340_iv(s.as_bytes())),
462 "mismatch on IV for {}",
463 name
464 );
465 }
466
467 check_iv(Cmr::UNIT_IV, "Simplicity\x1fCommitment\x1funit");
468 check_iv(Cmr::IDEN_IV, "Simplicity\x1fCommitment\x1fiden");
469 check_iv(Cmr::INJL_IV, "Simplicity\x1fCommitment\x1finjl");
470 check_iv(Cmr::INJR_IV, "Simplicity\x1fCommitment\x1finjr");
471 check_iv(Cmr::TAKE_IV, "Simplicity\x1fCommitment\x1ftake");
472 check_iv(Cmr::DROP_IV, "Simplicity\x1fCommitment\x1fdrop");
473 check_iv(Cmr::COMP_IV, "Simplicity\x1fCommitment\x1fcomp");
474 check_iv(Cmr::CASE_IV, "Simplicity\x1fCommitment\x1fcase");
475 check_iv(Cmr::PAIR_IV, "Simplicity\x1fCommitment\x1fpair");
476 check_iv(Cmr::DISCONNECT_IV, "Simplicity\x1fCommitment\x1fdisconnect");
477 check_iv(Cmr::WITNESS_IV, "Simplicity\x1fCommitment\x1fwitness");
478 check_iv(Cmr::FAIL_IV, "Simplicity\x1fCommitment\x1ffail");
479 check_iv(Cmr::CONST_WORD_IV, "Simplicity\x1fIdentity");
480 }
481
482 #[test]
483 fn const_bits() {
484 fn scribe<'brand>(ctx: &types::Context<'brand>, bit: u8) -> Arc<ConstructNode<'brand>> {
486 match bit {
487 0 => Arc::<ConstructNode>::injl(&Arc::<ConstructNode>::unit(ctx)),
488 1 => Arc::<ConstructNode>::injr(&Arc::<ConstructNode>::unit(ctx)),
489 _ => panic!("Unexpected bit {bit}"),
490 }
491 }
492
493 fn check_bit(target: Cmr, index: u8) {
494 types::Context::with_context(|ctx| {
505 assert_eq!(
506 target,
507 scribe(&ctx, index).cmr(),
508 "mismatch on CMR for bit {index}",
509 );
510 });
511 }
512
513 for index in 0..2u8 {
514 check_bit(Cmr::BITS[usize::from(index)], index)
515 }
516 }
517}