1use crate::dag::{DagLike, MaxSharing, NoSharing, PostOrderIterItem};
4use crate::jet::Jet;
5use crate::types::arrow::{Arrow, FinalArrow};
6use crate::{encode, types, Value};
7use crate::{Amr, BitIter, BitWriter, Cmr, Error, Ihr, Imr};
8
9use super::{
10 Construct, ConstructData, ConstructNode, Constructible, Converter, Inner, Marker, NoDisconnect,
11 NoWitness, Node, Redeem, RedeemNode,
12};
13
14use std::io;
15use std::marker::PhantomData;
16use std::sync::Arc;
17
18#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
19pub struct Commit<J> {
20 never: std::convert::Infallible,
22 phantom: std::marker::PhantomData<J>,
24}
25
26impl<J: Jet> Marker for Commit<J> {
27 type CachedData = Arc<CommitData<J>>;
28 type Witness = NoWitness;
29 type Disconnect = NoDisconnect;
30 type SharingId = Ihr;
31 type Jet = J;
32
33 fn compute_sharing_id(_: Cmr, cached_data: &Arc<CommitData<J>>) -> Option<Ihr> {
34 cached_data.ihr
35 }
36}
37
38#[derive(Clone, Debug, PartialEq, Eq, Hash)]
39pub struct CommitData<J> {
40 arrow: FinalArrow,
42 imr: Option<Imr>,
45 amr: Option<Amr>,
48 ihr: Option<Ihr>,
51 phantom: PhantomData<J>,
55}
56
57impl<J: Jet> CommitData<J> {
58 pub fn arrow(&self) -> &FinalArrow {
60 &self.arrow
61 }
62
63 pub fn ihr(&self) -> Option<Ihr> {
65 self.ihr
66 }
67
68 fn incomplete_amr(
70 inner: Inner<&Arc<Self>, J, &NoDisconnect, &NoWitness>,
71 arrow: &FinalArrow,
72 ) -> Option<Amr> {
73 match inner {
74 Inner::Iden => Some(Amr::iden(arrow)),
75 Inner::Unit => Some(Amr::unit(arrow)),
76 Inner::InjL(child) => child.amr.map(|amr| Amr::injl(arrow, amr)),
77 Inner::InjR(child) => child.amr.map(|amr| Amr::injr(arrow, amr)),
78 Inner::Take(child) => child.amr.map(|amr| Amr::take(arrow, amr)),
79 Inner::Drop(child) => child.amr.map(|amr| Amr::drop(arrow, amr)),
80 Inner::Comp(left, right) => left
81 .amr
82 .zip(right.amr)
83 .map(|(a, b)| Amr::comp(arrow, &left.arrow, a, b)),
84 Inner::Case(left, right) => {
85 left.amr.zip(right.amr).map(|(a, b)| Amr::case(arrow, a, b))
86 }
87 Inner::AssertL(left, r_cmr) => left
88 .amr
89 .map(|l_amr| Amr::assertl(arrow, l_amr, r_cmr.into())),
90 Inner::AssertR(l_cmr, right) => right
91 .amr
92 .map(|r_amr| Amr::assertr(arrow, l_cmr.into(), r_amr)),
93 Inner::Pair(left, right) => left
94 .amr
95 .zip(right.amr)
96 .map(|(a, b)| Amr::pair(arrow, &left.arrow, &right.arrow, a, b)),
97 Inner::Disconnect(..) => None,
98 Inner::Witness(..) => None,
99 Inner::Fail(entropy) => Some(Amr::fail(entropy)),
100 Inner::Jet(jet) => Some(Amr::jet(jet)),
101 Inner::Word(ref val) => Some(Amr::const_word(val)),
102 }
103 }
104
105 fn imr(inner: Inner<&Arc<Self>, J, &NoDisconnect, &NoWitness>) -> Option<Imr> {
107 match inner {
108 Inner::Iden => Some(Imr::iden()),
109 Inner::Unit => Some(Imr::unit()),
110 Inner::InjL(child) => child.imr.map(Imr::injl),
111 Inner::InjR(child) => child.imr.map(Imr::injr),
112 Inner::Take(child) => child.imr.map(Imr::take),
113 Inner::Drop(child) => child.imr.map(Imr::drop),
114 Inner::Comp(left, right) => left.imr.zip(right.imr).map(|(a, b)| Imr::comp(a, b)),
115 Inner::Case(left, right) => left.imr.zip(right.imr).map(|(a, b)| Imr::case(a, b)),
116 Inner::AssertL(left, r_cmr) => left.imr.map(|l_ihr| Imr::case(l_ihr, r_cmr.into())),
117 Inner::AssertR(l_cmr, right) => right.imr.map(|r_ihr| Imr::case(l_cmr.into(), r_ihr)),
118 Inner::Pair(left, right) => left.imr.zip(right.imr).map(|(a, b)| Imr::pair(a, b)),
119 Inner::Disconnect(..) => None,
120 Inner::Witness(..) => None,
121 Inner::Fail(entropy) => Some(Imr::fail(entropy)),
122 Inner::Jet(jet) => Some(Imr::jet(jet)),
123 Inner::Word(ref val) => Some(Imr::const_word(val)),
124 }
125 }
126
127 pub fn new(
128 arrow: &Arrow,
129 inner: Inner<&Arc<Self>, J, &NoDisconnect, &NoWitness>,
130 ) -> Result<Self, types::Error> {
131 let final_arrow = arrow.finalize()?;
132 let imr = Self::imr(inner.clone());
133 let amr = Self::incomplete_amr(inner, &final_arrow);
134 Ok(CommitData {
135 imr,
136 amr,
137 ihr: imr.map(|ihr| Ihr::from_imr(ihr, &final_arrow)),
138 arrow: final_arrow,
139 phantom: PhantomData,
140 })
141 }
142
143 pub fn from_final(
144 arrow: FinalArrow,
145 inner: Inner<&Arc<Self>, J, &NoDisconnect, &NoWitness>,
146 ) -> Self {
147 let imr = Self::imr(inner.clone());
148 let amr = Self::incomplete_amr(inner, &arrow);
149 CommitData {
150 imr,
151 amr,
152 ihr: imr.map(|ihr| Ihr::from_imr(ihr, &arrow)),
153 arrow,
154 phantom: PhantomData,
155 }
156 }
157}
158
159pub type CommitNode<J> = Node<Commit<J>>;
160
161impl<J: Jet> CommitNode<J> {
162 pub fn arrow(&self) -> &FinalArrow {
164 &self.data.arrow
165 }
166
167 pub fn amr(&self) -> Option<Amr> {
169 self.data.amr
170 }
171
172 pub fn ihr(&self) -> Option<Ihr> {
174 self.data.ihr
175 }
176
177 pub fn finalize<C: Converter<Commit<J>, Redeem<J>>>(
183 &self,
184 converter: &mut C,
185 ) -> Result<Arc<RedeemNode<J>>, C::Error> {
186 self.convert::<NoSharing, Redeem<J>, _>(converter)
187 }
188
189 pub fn unfinalize_types(&self) -> Result<Arc<ConstructNode<J>>, types::Error> {
191 struct UnfinalizeTypes<J: Jet> {
192 inference_context: types::Context,
193 phantom: PhantomData<J>,
194 }
195
196 impl<J: Jet> Converter<Commit<J>, Construct<J>> for UnfinalizeTypes<J> {
197 type Error = types::Error;
198 fn convert_witness(
199 &mut self,
200 _: &PostOrderIterItem<&CommitNode<J>>,
201 _: &NoWitness,
202 ) -> Result<Option<Value>, Self::Error> {
203 Ok(None)
204 }
205
206 fn convert_disconnect(
207 &mut self,
208 _: &PostOrderIterItem<&CommitNode<J>>,
209 _: Option<&Arc<ConstructNode<J>>>,
210 _: &NoDisconnect,
211 ) -> Result<Option<Arc<ConstructNode<J>>>, Self::Error> {
212 Ok(None)
213 }
214
215 fn convert_data(
216 &mut self,
217 _: &PostOrderIterItem<&CommitNode<J>>,
218 inner: Inner<
219 &Arc<ConstructNode<J>>,
220 J,
221 &Option<Arc<ConstructNode<J>>>,
222 &Option<Value>,
223 >,
224 ) -> Result<ConstructData<J>, Self::Error> {
225 let inner = inner
226 .map(|node| node.arrow())
227 .map_disconnect(|maybe_node| maybe_node.as_ref().map(|node| node.arrow()));
228 let inner = inner.disconnect_as_ref(); Ok(ConstructData::new(Arrow::from_inner(
230 &self.inference_context,
231 inner,
232 )?))
233 }
234 }
235
236 self.convert::<MaxSharing<Commit<J>>, _, _>(&mut UnfinalizeTypes {
237 inference_context: types::Context::new(),
238 phantom: PhantomData,
239 })
240 }
241
242 pub fn decode<I: Iterator<Item = u8>>(mut bits: BitIter<I>) -> Result<Arc<Self>, Error> {
252 let construct = crate::decode::decode_expression(&mut bits)?;
254 bits.close()
255 .map_err(crate::decode::Error::BitIter)
256 .map_err(Error::Decode)?;
257 let program = construct.finalize_types()?;
258 if program.as_ref().is_shared_as::<MaxSharing<Commit<J>>>() {
260 Ok(program)
261 } else {
262 Err(Error::Decode(crate::decode::Error::SharingNotMaximal))
263 }
264 }
265
266 pub fn encode<W: io::Write>(&self, w: &mut BitWriter<W>) -> io::Result<usize> {
268 let program_bits = encode::encode_program(self, w)?;
269 w.flush_all()?;
270 Ok(program_bits)
271 }
272
273 pub fn encode_to_vec(&self) -> Vec<u8> {
275 let mut program = Vec::<u8>::new();
276 let mut writer = BitWriter::new(&mut program);
277 self.encode(&mut writer)
278 .expect("write to vector never fails");
279 debug_assert!(!program.is_empty());
280
281 program
282 }
283}
284
285#[cfg(test)]
286mod tests {
287 use super::*;
288
289 use hex::DisplayHex;
290 use std::fmt;
291
292 use crate::decode::Error;
293 use crate::human_encoding::Forest;
294 use crate::jet::Core;
295 use crate::node::SimpleFinalizer;
296 use crate::{BitMachine, Value};
297
298 fn assert_program_deserializable<J: Jet>(
299 prog_str: &str,
300 prog_bytes: &[u8],
301 cmr_str: &str,
302 ) -> Arc<CommitNode<J>> {
303 let forest = match Forest::<J>::parse(prog_str) {
304 Ok(forest) => forest,
305 Err(e) => panic!("Failed to parse program `{}`: {}", prog_str, e),
306 };
307 assert_eq!(
308 forest.roots().len(),
309 1,
310 "program `{}` has multiple roots",
311 prog_str
312 );
313 let main = match forest.roots().get("main") {
314 Some(root) => root,
315 None => panic!("Program `{}` has no main", prog_str),
316 };
317
318 let prog_hex = prog_bytes.as_hex();
319 let main_bytes = main.encode_to_vec();
320 assert_eq!(
321 prog_bytes,
322 main_bytes,
323 "Program string `{}` encoded to {} (expected {})",
324 prog_str,
325 main_bytes.as_hex(),
326 prog_hex,
327 );
328
329 let iter = BitIter::from(prog_bytes);
330 let prog = match CommitNode::<J>::decode(iter) {
331 Ok(prog) => prog,
332 Err(e) => panic!("program {} failed: {}", prog_hex, e),
333 };
334
335 assert_eq!(
336 prog.cmr().to_string(),
337 cmr_str,
338 "CMR mismatch (got {} expected {}) for program {}",
339 prog.cmr(),
340 cmr_str,
341 prog_hex,
342 );
343
344 let reser_sink = prog.encode_to_vec();
345 assert_eq!(
346 prog_bytes,
347 &reser_sink[..],
348 "program {} reserialized as {}",
349 prog_hex,
350 reser_sink.as_hex(),
351 );
352
353 prog
354 }
355
356 fn assert_program_not_deserializable<J: Jet>(prog: &[u8], err: &dyn fmt::Display) {
357 let prog_hex = prog.as_hex();
358 let err_str = err.to_string();
359
360 let iter = BitIter::from(prog);
361 match CommitNode::<J>::decode(iter) {
362 Ok(prog) => panic!(
363 "Program {} succeded (expected error {}). Program parsed as:\n{}",
364 prog_hex, err, prog
365 ),
366 Err(e) if e.to_string() == err_str => {} Err(e) => panic!(
368 "Program {} failed with error {} (expected error {})",
369 prog_hex, e, err
370 ),
371 };
372 }
373
374 #[test]
375 fn canonical_order() {
376 assert_program_not_deserializable::<Core>(&[0xa8, 0x48, 0x10], &Error::NotInCanonicalOrder);
380
381 assert_program_not_deserializable::<Core>(
383 &[0xc1, 0x00, 0x06, 0x20],
384 &Error::NotInCanonicalOrder,
385 );
386 }
387
388 #[test]
389 fn hidden_node() {
390 #[rustfmt::skip]
392 let hidden = [
393 0x36, 0xf5, 0x6d, 0xf7, 0x7e, 0xf5, 0x6d, 0xf7,
394 0x7e, 0xf5, 0x6d, 0xf7, 0x7e, 0xf5, 0x6d, 0xf7,
395 0x7e, 0xf5, 0x6d, 0xf7, 0x7e, 0xf5, 0x6d, 0xf7,
396 0x7e, 0xf5, 0x6d, 0xf7, 0x7e, 0xf5, 0x6d, 0xf7,
397 78,
398 ];
399 assert_program_not_deserializable::<Core>(&hidden, &Error::HiddenNode);
400
401 let hidden = [
403 0xae, 0xdb, 0xd5, 0xb7, 0xdd, 0xfb, 0xd5, 0xb7, 0xdd, 0xfb, 0xd5, 0xb7, 0xdd, 0xfb,
404 0xd5, 0xb7, 0xdd, 0xfb, 0xd5, 0xb7, 0xdd, 0xfb, 0xd5, 0xb7, 0xdd, 0xfb, 0xd5, 0xb7,
405 0xdd, 0xfb, 0xd5, 0xb7, 0xdd, 0xe0, 0x80,
406 ];
407 assert_program_not_deserializable::<Core>(&hidden, &Error::HiddenNode);
408 }
409
410 #[test]
411 fn case_both_children_hidden() {
412 #[rustfmt::skip]
415 let hidden = [
416 0x8d, 0xbd, 0x5b, 0x7d, 0xdf, 0xbd, 0x5b, 0x7d,
417 0xdf, 0xbd, 0x5b, 0x7d, 0xdf, 0xbd, 0x5b, 0x7d,
418 0xdf, 0xbd, 0x5b, 0x7d, 0xdf, 0xbd, 0x5b, 0x7d,
419 0xdf, 0xbd, 0x5b, 0x7d, 0xdf, 0xbd, 0x5b, 0x7d,
420 0xde, 0x10,
421 ];
422 assert_program_not_deserializable::<Core>(&hidden, &Error::BothChildrenHidden);
423 }
424
425 #[test]
426 fn unshared_hidden() {
427 #[rustfmt::skip]
430 let hidden = [
431 0xd6, 0xe9, 0x62, 0x56, 0x62, 0xc9, 0x38, 0x8a,
432 0x44, 0x31, 0x85, 0xee, 0xc2, 0x2b, 0x91, 0x48,
433 0x87, 0xe1, 0xfd, 0x18, 0x57, 0xc2, 0x8c, 0x4a,
434 0x28, 0x44, 0x2f, 0xa8, 0x61, 0x5c, 0xa7, 0x6e,
435 0x8c, 0xf9, 0x80, 0xc2, 0x18, 0x95, 0x98, 0xb2,
436 0x4e, 0x22, 0x91, 0x0c, 0x61, 0x7b, 0xb0, 0x8a,
437 0xe4, 0x52, 0x21, 0xf8, 0x7f, 0x46, 0x15, 0xf0,
438 0xa3, 0x12, 0x8a, 0x11, 0x0b, 0xea, 0x18, 0x57,
439 0x29, 0xdb, 0xa3, 0x3e, 0x60, 0x30, 0x2c, 0x00,
440 0xd0, 0x48, 0x20,
441 ];
442 assert_program_not_deserializable::<Core>(&hidden, &Error::SharingNotMaximal);
443 }
444
445 #[test]
446 fn shared_witnesses() {
447 assert_program_deserializable::<Core>(
448 "main := witness",
449 &[0x38],
450 "a0fc8debd6796917c86b77aded82e6c61649889ae8f2ed65b57b41aa9d90e375",
451 );
452
453 #[rustfmt::skip]
454 let bad_diff1s = vec![
455 vec![
458 0xda, 0xe2, 0x39, 0xa3, 0x10, 0x42, 0x0e, 0x05,
459 0x71, 0x88, 0xa3, 0x6d, 0xc4, 0x11, 0x80, 0x80
460 ],
461 vec![
465 0xde, 0x87, 0x04, 0x08, 0xe6, 0x8c, 0x41, 0x08,
466 0x38, 0x15, 0xc6, 0x22, 0x8d, 0xb7, 0x10, 0x46,
467 0x02, 0x00,
468 ],
469 ];
470 for bad_diff1 in bad_diff1s {
471 assert_program_not_deserializable::<Core>(&bad_diff1, &Error::SharingNotMaximal);
472 }
473
474 #[rustfmt::skip]
475 let diff1s = vec![
476 (
477 "
479 -- Program which demands two 32-bit witnesses, the first one == the second + 1
480 wit1 := witness : 1 -> 2^32
481 wit2 := witness : 1 -> 2^32
482
483 wit_diff := comp (comp (pair wit1 wit2) jet_subtract_32) (drop iden) : 1 -> 2^32
484 diff_is_one := comp (pair wit_diff jet_one_32) jet_eq_32 : 1 -> 2
485 main := comp diff_is_one jet_verify : 1 -> 1
486 ",
487 vec![
488 0xdc, 0xee, 0x28, 0xe6, 0x8c, 0x41, 0x08, 0x38,
489 0x15, 0xc6, 0x22, 0x8d, 0xb7, 0x10, 0x46, 0x02,
490 0x00,
491 ],
492 "e9339a0d715c721bff752aedc02710cdf3399f3f8d86e64456e85a1bc06ecb7c",
494 ),
495 (
497 "
498 -- Program which demands two 32-bit witnesses, the first one == the second + 1
499 wit1 := witness : 1 -> 2^32
500 wit2 := witness : 1 -> 2^32
501 compwit1 := comp iden wit1
502 compwit2 := comp iden wit2
503
504 wit_diff := comp (comp (pair compwit1 compwit2) jet_subtract_32) (drop iden)
505 diff_is_one := comp (pair wit_diff jet_one_32) jet_eq_32 : 1 -> 2
506 main := comp diff_is_one jet_verify : 1 -> 1
507 ",
508 vec![
509 0xe0, 0x28, 0x70, 0x43, 0x83, 0x00, 0xab, 0x9a,
510 0x31, 0x04, 0x20, 0xe0, 0x57, 0x18, 0x8a, 0x36,
511 0xdc, 0x41, 0x18, 0x08,
512 ],
513 "d03bf350f406aef3af0d48e6533b3325ff86f18a36e0e73895a5cd6d6692b860",
515 )
516 ];
517
518 for (prog_str, diff1, cmr) in diff1s {
519 let diff1_prog = crate::node::commit::tests::assert_program_deserializable::<Core>(
520 prog_str, &diff1, cmr,
521 );
522
523 let mut counter = 0..100;
526 let witness_iter = (&mut counter).rev().map(Value::u32);
527 let diff1_final = diff1_prog
528 .finalize(&mut SimpleFinalizer::new(witness_iter))
529 .unwrap();
530 assert_eq!(counter, 0..98);
531
532 let mut mac =
534 BitMachine::for_program(&diff1_final).expect("program has reasonable bounds");
535 mac.exec(&diff1_final, &()).unwrap();
536 }
537 }
538
539 #[test]
540 fn extra_nodes() {
541 assert_program_not_deserializable::<Core>(&[0xa9, 0x48, 0x00], &Error::NotInCanonicalOrder);
544 }
545
546 #[test]
547 fn regression_177() {
548 let bad_prog = "
556 id := iden
557 main := case (drop id) id
558 ";
559 match Forest::<Core>::parse(bad_prog) {
560 Ok(_) => panic!("program should have failed"),
561 Err(set) => {
562 let mut errs_happened = (false, false);
563 for err in set.iter() {
564 match err {
565 crate::human_encoding::Error::TypeCheck(e @ types::Error::Bind { .. }) => {
566 errs_happened.0 = true;
567 e.to_string();
568 }
569 crate::human_encoding::Error::TypeCheck(
570 e @ types::Error::OccursCheck { .. },
571 ) => {
572 errs_happened.1 = true;
573 e.to_string();
574 }
575 x => panic!("unexpected error {x:?}"),
576 }
577 }
578 assert_eq!(errs_happened, (true, true));
579 }
580 };
581 }
582}