1use crate::dag::{DagLike, MaxSharing, SharingTracker};
67use crate::encode;
68use crate::jet::Jet;
69use crate::{types, BitWriter, Cmr, FailEntropy, HasCmr, Value};
70
71use std::sync::Arc;
72use std::{fmt, hash, io};
73
74mod commit;
75mod construct;
76mod convert;
77mod disconnect;
78mod display;
79mod hiding;
80mod inner;
81mod redeem;
82
83use crate::value::Word;
84pub use commit::{Commit, CommitData, CommitNode};
85pub use construct::{Construct, ConstructData, ConstructNode};
86pub use convert::{Converter, Hide, SimpleFinalizer};
87pub use disconnect::{Disconnectable, NoDisconnect};
88pub use display::{Display, DisplayExpr};
89pub use hiding::Hiding;
90pub use inner::Inner;
91pub use redeem::{Redeem, RedeemData, RedeemNode};
92
93pub trait Marker:
97 Copy + Clone + PartialEq + Eq + PartialOrd + Ord + fmt::Debug + hash::Hash
98{
99 type CachedData: Clone;
101
102 type Witness: Clone;
105
106 type Disconnect: Disconnectable<Node<Self>> + Clone;
108
109 type SharingId: hash::Hash + Clone + Eq;
112
113 type Jet: Jet;
115
116 fn compute_sharing_id(cmr: Cmr, cached_data: &Self::CachedData) -> Option<Self::SharingId>;
122}
123
124#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
126pub struct NoWitness;
127
128impl From<NoWitness> for Option<Value> {
129 fn from(_: NoWitness) -> Self {
130 None
131 }
132}
133
134pub trait Constructible<'brand, J, X, W>:
135 JetConstructible<'brand, J>
136 + DisconnectConstructible<'brand, X>
137 + WitnessConstructible<'brand, W>
138 + CoreConstructible<'brand>
139 + Sized
140{
141 fn from_inner(
142 inference_context: &types::Context<'brand>,
143 inner: Inner<&Self, J, &X, W>,
144 ) -> Result<Self, types::Error> {
145 match inner {
146 Inner::Iden => Ok(Self::iden(inference_context)),
147 Inner::Unit => Ok(Self::unit(inference_context)),
148 Inner::InjL(child) => Ok(Self::injl(child)),
149 Inner::InjR(child) => Ok(Self::injr(child)),
150 Inner::Take(child) => Ok(Self::take(child)),
151 Inner::Drop(child) => Ok(Self::drop_(child)),
152 Inner::Comp(left, right) => Self::comp(left, right),
153 Inner::Case(left, right) => Self::case(left, right),
154 Inner::AssertL(left, r_cmr) => Self::assertl(left, r_cmr),
155 Inner::AssertR(l_cmr, right) => Self::assertr(l_cmr, right),
156 Inner::Pair(left, right) => Self::pair(left, right),
157 Inner::Disconnect(left, right) => Self::disconnect(left, right),
158 Inner::Fail(entropy) => Ok(Self::fail(inference_context, entropy)),
159 Inner::Word(ref w) => Ok(Self::const_word(inference_context, w.shallow_clone())),
160 Inner::Jet(j) => Ok(Self::jet(inference_context, j)),
161 Inner::Witness(w) => Ok(Self::witness(inference_context, w)),
162 }
163 }
164}
165
166impl<'brand, J, X, W, T> Constructible<'brand, J, X, W> for T where
167 T: DisconnectConstructible<'brand, X>
168 + JetConstructible<'brand, J>
169 + WitnessConstructible<'brand, W>
170 + CoreConstructible<'brand>
171 + Sized
172{
173}
174
175pub trait CoreConstructible<'brand>: Sized {
176 fn iden(inference_context: &types::Context<'brand>) -> Self;
177 fn unit(inference_context: &types::Context<'brand>) -> Self;
178 fn injl(child: &Self) -> Self;
179 fn injr(child: &Self) -> Self;
180 fn take(child: &Self) -> Self;
181 fn drop_(child: &Self) -> Self;
182 fn comp(left: &Self, right: &Self) -> Result<Self, types::Error>;
183 fn case(left: &Self, right: &Self) -> Result<Self, types::Error>;
184 fn assertl(left: &Self, right: Cmr) -> Result<Self, types::Error>;
185 fn assertr(left: Cmr, right: &Self) -> Result<Self, types::Error>;
186 fn pair(left: &Self, right: &Self) -> Result<Self, types::Error>;
187 fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self;
188 fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self;
189
190 fn inference_context(&self) -> &types::Context<'brand>;
192
193 fn scribe(ctx: &types::Context<'brand>, value: &Value) -> Self {
197 use crate::value::ValueRef;
198
199 #[derive(Debug, Clone)]
200 enum Task<'v> {
201 Process(ValueRef<'v>),
202 MakeLeft,
203 MakeRight,
204 MakeProduct,
205 }
206
207 let mut input = vec![Task::Process(value.as_ref())];
208 let mut output = vec![];
209 while let Some(top) = input.pop() {
210 match top {
211 Task::Process(value) => {
212 if value.is_unit() {
213 output.push(Self::unit(ctx));
214 } else if let Some(word) = value.to_word() {
215 output.push(Self::const_word(ctx, word));
216 } else if let Some(left) = value.as_left() {
217 input.push(Task::MakeLeft);
218 input.push(Task::Process(left));
219 } else if let Some(right) = value.as_right() {
220 input.push(Task::MakeRight);
221 input.push(Task::Process(right));
222 } else if let Some((left, right)) = value.as_product() {
223 input.push(Task::MakeProduct);
224 input.push(Task::Process(right));
225 input.push(Task::Process(left));
226 }
227 }
228 Task::MakeLeft => {
229 let inner = output.pop().unwrap();
230 output.push(Self::injl(&inner));
231 }
232 Task::MakeRight => {
233 let inner = output.pop().unwrap();
234 output.push(Self::injr(&inner));
235 }
236 Task::MakeProduct => {
237 let right = output.pop().unwrap();
238 let left = output.pop().unwrap();
239 output.push(
241 Self::pair(&left, &right).expect(
242 "`pair` should always succeed because input type is unrestricted",
243 ),
244 );
245 }
246 }
247 }
248 debug_assert_eq!(output.len(), 1);
249 output.pop().unwrap()
250 }
251
252 fn bit_false(inference_context: &types::Context<'brand>) -> Self {
256 let unit = Self::unit(inference_context);
257 Self::injl(&unit)
258 }
259
260 fn bit_true(inference_context: &types::Context<'brand>) -> Self {
264 let unit = Self::unit(inference_context);
265 Self::injr(&unit)
266 }
267
268 fn cond(left: &Self, right: &Self) -> Result<Self, types::Error> {
276 let drop_left = Self::drop_(left);
277 let drop_right = Self::drop_(right);
278 Self::case(&drop_right, &drop_left)
279 }
280
281 fn assert(child: &Self, hash: Cmr) -> Result<Self, types::Error> {
288 let unit = Self::unit(child.inference_context());
289 let pair_child_unit = Self::pair(child, &unit)?;
290 let assertr_hidden_unit = Self::assertr(hash, &unit)?;
291
292 Self::comp(&pair_child_unit, &assertr_hidden_unit)
293 }
294
295 #[allow(clippy::should_implement_trait)]
301 fn not(child: &Self) -> Result<Self, types::Error> {
302 let unit = Self::unit(child.inference_context());
303 let pair_child_unit = Self::pair(child, &unit)?;
304 let bit_true = Self::bit_true(child.inference_context());
305 let bit_false = Self::bit_false(child.inference_context());
306 let case_true_false = Self::case(&bit_true, &bit_false)?;
307
308 Self::comp(&pair_child_unit, &case_true_false)
309 }
310
311 fn and(left: &Self, right: &Self) -> Result<Self, types::Error> {
317 left.inference_context()
318 .check_eq(right.inference_context())?;
319 let iden = Self::iden(left.inference_context());
320 let pair_left_iden = Self::pair(left, &iden)?;
321 let bit_false = Self::bit_false(left.inference_context());
322 let drop_right = Self::drop_(right);
323 let case_false_right = Self::case(&bit_false, &drop_right)?;
324
325 Self::comp(&pair_left_iden, &case_false_right)
326 }
327
328 fn or(left: &Self, right: &Self) -> Result<Self, types::Error> {
334 left.inference_context()
335 .check_eq(right.inference_context())?;
336 let iden = Self::iden(left.inference_context());
337 let pair_left_iden = Self::pair(left, &iden)?;
338 let drop_right = Self::drop_(right);
339 let bit_true = Self::bit_true(left.inference_context());
340 let case_right_true = Self::case(&drop_right, &bit_true)?;
341
342 Self::comp(&pair_left_iden, &case_right_true)
343 }
344}
345
346pub trait DisconnectConstructible<'brand, X>: Sized {
347 fn disconnect(left: &Self, right: &X) -> Result<Self, types::Error>;
348}
349
350pub trait JetConstructible<'brand, J>: Sized {
351 fn jet(inference_context: &types::Context<'brand>, jet: J) -> Self;
352}
353
354pub trait WitnessConstructible<'brand, W>: Sized {
355 fn witness(inference_context: &types::Context<'brand>, witness: W) -> Self;
356}
357
358pub struct Node<N: Marker> {
372 inner: Inner<Arc<Node<N>>, N::Jet, N::Disconnect, N::Witness>,
373 cmr: Cmr,
374 data: N::CachedData,
375}
376
377impl<N: Marker> PartialEq for Node<N>
378where
379 N::CachedData: PartialEq,
380{
381 fn eq(&self, other: &Self) -> bool {
382 self.cmr == other.cmr && self.data == other.data
383 }
384}
385impl<N: Marker> Eq for Node<N> where N::CachedData: Eq {}
386
387impl<N: Marker> hash::Hash for Node<N>
388where
389 N::CachedData: hash::Hash,
390{
391 fn hash<H: hash::Hasher>(&self, h: &mut H) {
392 self.cmr.hash(h);
393 self.data.hash(h);
394 }
395}
396
397impl<N: Marker> fmt::Debug for Node<N>
398where
399 for<'a> &'a Node<N>: DagLike,
400{
401 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
402 self.post_order_iter::<MaxSharing<N>>().into_display(
403 f,
404 |node, f| fmt::Display::fmt(&node.inner, f),
405 |_, _| Ok(()),
406 )
407 }
408}
409
410#[cfg(feature = "base64")]
411impl<N: Marker> fmt::Display for Node<N> {
412 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
416 use crate::base64::display::Base64Display;
417 use crate::base64::engine::general_purpose;
418
419 let v = self.to_vec_without_witness();
420 Base64Display::new(&v, &general_purpose::STANDARD).fmt(f)
421 }
422}
423
424impl<N: Marker> HasCmr for Node<N> {
425 fn cmr(&self) -> Cmr {
426 self.cmr
427 }
428}
429
430impl<N: Marker> HasCmr for Arc<Node<N>> {
431 fn cmr(&self) -> Cmr {
432 self.cmr
433 }
434}
435
436impl<'brand, N> CoreConstructible<'brand> for Arc<Node<N>>
437where
438 N: Marker,
439 N::CachedData: CoreConstructible<'brand>,
440{
441 fn iden(inference_context: &types::Context<'brand>) -> Self {
442 Arc::new(Node {
443 cmr: Cmr::iden(),
444 data: N::CachedData::iden(inference_context),
445 inner: Inner::Iden,
446 })
447 }
448
449 fn unit(inference_context: &types::Context<'brand>) -> Self {
450 Arc::new(Node {
451 cmr: Cmr::unit(),
452 data: N::CachedData::unit(inference_context),
453 inner: Inner::Unit,
454 })
455 }
456
457 fn injl(child: &Self) -> Self {
458 Arc::new(Node {
459 cmr: Cmr::injl(child.cmr()),
460 data: N::CachedData::injl(&child.data),
461 inner: Inner::InjL(Arc::clone(child)),
462 })
463 }
464
465 fn injr(child: &Self) -> Self {
466 Arc::new(Node {
467 cmr: Cmr::injr(child.cmr()),
468 data: N::CachedData::injr(&child.data),
469 inner: Inner::InjR(Arc::clone(child)),
470 })
471 }
472
473 fn take(child: &Self) -> Self {
474 Arc::new(Node {
475 cmr: Cmr::take(child.cmr()),
476 data: N::CachedData::take(&child.data),
477 inner: Inner::Take(Arc::clone(child)),
478 })
479 }
480
481 fn drop_(child: &Self) -> Self {
482 Arc::new(Node {
483 cmr: Cmr::drop(child.cmr()),
484 data: N::CachedData::drop_(&child.data),
485 inner: Inner::Drop(Arc::clone(child)),
486 })
487 }
488
489 fn comp(left: &Self, right: &Self) -> Result<Self, types::Error> {
490 Ok(Arc::new(Node {
491 cmr: Cmr::comp(left.cmr(), right.cmr()),
492 data: N::CachedData::comp(&left.data, &right.data)?,
493 inner: Inner::Comp(Arc::clone(left), Arc::clone(right)),
494 }))
495 }
496
497 fn case(left: &Self, right: &Self) -> Result<Self, types::Error> {
498 Ok(Arc::new(Node {
499 cmr: Cmr::case(left.cmr(), right.cmr()),
500 data: N::CachedData::case(&left.data, &right.data)?,
501 inner: Inner::Case(Arc::clone(left), Arc::clone(right)),
502 }))
503 }
504
505 fn assertl(left: &Self, r_cmr: Cmr) -> Result<Self, types::Error> {
506 Ok(Arc::new(Node {
507 cmr: Cmr::case(left.cmr(), r_cmr),
508 data: N::CachedData::assertl(&left.data, r_cmr)?,
509 inner: Inner::AssertL(Arc::clone(left), r_cmr),
510 }))
511 }
512
513 fn assertr(l_cmr: Cmr, right: &Self) -> Result<Self, types::Error> {
514 Ok(Arc::new(Node {
515 cmr: Cmr::case(l_cmr, right.cmr()),
516 data: N::CachedData::assertr(l_cmr, &right.data)?,
517 inner: Inner::AssertR(l_cmr, Arc::clone(right)),
518 }))
519 }
520
521 fn pair(left: &Self, right: &Self) -> Result<Self, types::Error> {
522 Ok(Arc::new(Node {
523 cmr: Cmr::pair(left.cmr(), right.cmr()),
524 data: N::CachedData::pair(&left.data, &right.data)?,
525 inner: Inner::Pair(Arc::clone(left), Arc::clone(right)),
526 }))
527 }
528
529 fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self {
530 Arc::new(Node {
531 cmr: Cmr::fail(entropy),
532 data: N::CachedData::fail(inference_context, entropy),
533 inner: Inner::Fail(entropy),
534 })
535 }
536
537 fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self {
538 Arc::new(Node {
539 cmr: Cmr::const_word(&word),
540 data: N::CachedData::const_word(inference_context, word.shallow_clone()),
541 inner: Inner::Word(word),
542 })
543 }
544
545 fn inference_context(&self) -> &types::Context<'brand> {
546 self.data.inference_context()
547 }
548}
549
550impl<'brand, N> DisconnectConstructible<'brand, N::Disconnect> for Arc<Node<N>>
551where
552 N: Marker,
553 N::CachedData: DisconnectConstructible<'brand, N::Disconnect>,
554{
555 fn disconnect(left: &Self, right: &N::Disconnect) -> Result<Self, types::Error> {
556 Ok(Arc::new(Node {
557 cmr: Cmr::disconnect(left.cmr()),
558 data: N::CachedData::disconnect(&left.data, right)?,
559 inner: Inner::Disconnect(Arc::clone(left), right.clone()),
560 }))
561 }
562}
563
564impl<'brand, N> WitnessConstructible<'brand, N::Witness> for Arc<Node<N>>
565where
566 N: Marker,
567 N::CachedData: WitnessConstructible<'brand, N::Witness>,
568{
569 fn witness(inference_context: &types::Context<'brand>, value: N::Witness) -> Self {
570 Arc::new(Node {
571 cmr: Cmr::witness(),
572 data: N::CachedData::witness(inference_context, value.clone()),
573 inner: Inner::Witness(value),
574 })
575 }
576}
577
578impl<'brand, N> JetConstructible<'brand, N::Jet> for Arc<Node<N>>
579where
580 N: Marker,
581 N::CachedData: JetConstructible<'brand, N::Jet>,
582{
583 fn jet(inference_context: &types::Context<'brand>, jet: N::Jet) -> Self {
584 Arc::new(Node {
585 cmr: Cmr::jet(jet),
586 data: N::CachedData::jet(inference_context, jet),
587 inner: Inner::Jet(jet),
588 })
589 }
590}
591
592impl<N: Marker> Node<N> {
593 pub fn inner(&self) -> &Inner<Arc<Node<N>>, N::Jet, N::Disconnect, N::Witness> {
595 &self.inner
596 }
597
598 pub fn cmr(&self) -> Cmr {
600 self.cmr
601 }
602
603 pub fn sharing_id(&self) -> Option<N::SharingId> {
605 N::compute_sharing_id(self.cmr, &self.data)
606 }
607
608 pub fn cached_data(&self) -> &N::CachedData {
610 &self.data
611 }
612
613 pub fn from_parts(
622 inner: Inner<Arc<Self>, N::Jet, N::Disconnect, N::Witness>,
623 data: N::CachedData,
624 ) -> Self {
625 let cmr = match inner {
626 Inner::Unit => Cmr::unit(),
627 Inner::Iden => Cmr::iden(),
628 Inner::InjL(ref c) => Cmr::injl(c.cmr()),
629 Inner::InjR(ref c) => Cmr::injr(c.cmr()),
630 Inner::Take(ref c) => Cmr::take(c.cmr()),
631 Inner::Drop(ref c) => Cmr::drop(c.cmr()),
632 Inner::Comp(ref cl, ref cr) => Cmr::comp(cl.cmr(), cr.cmr()),
633 Inner::Case(ref cl, ref cr) => Cmr::case(cl.cmr(), cr.cmr()),
634 Inner::AssertL(ref c, cmr) => Cmr::case(c.cmr(), cmr),
635 Inner::AssertR(cmr, ref c) => Cmr::case(cmr, c.cmr()),
636 Inner::Pair(ref cl, ref cr) => Cmr::pair(cl.cmr(), cr.cmr()),
637 Inner::Disconnect(ref cl, _) => Cmr::disconnect(cl.cmr()),
638 Inner::Witness(_) => Cmr::witness(),
639 Inner::Fail(entropy) => Cmr::fail(entropy),
640 Inner::Jet(j) => Cmr::jet(j),
641 Inner::Word(ref w) => Cmr::const_word(w),
642 };
643
644 Node { cmr, inner, data }
645 }
646
647 pub fn convert<S, M, C>(&self, converter: &mut C) -> Result<Arc<Node<M>>, C::Error>
655 where
656 S: for<'a> SharingTracker<&'a Self> + Default,
657 M: Marker<Jet = <N as Marker>::Jet>,
658 C: Converter<N, M>,
659 {
660 let mut converted: Vec<Arc<Node<M>>> = vec![];
661 for data in self.post_order_iter::<S>() {
662 converter.visit_node(&data);
664
665 let indexed_inner: Inner<usize, N::Jet, &N::Disconnect, &N::Witness> = data
669 .node
670 .inner
671 .as_ref()
672 .map_left_right(|_| data.left_index.unwrap(), |_| data.right_index.unwrap());
673
674 let witness_inner: Inner<&usize, M::Jet, &&N::Disconnect, M::Witness> = indexed_inner
676 .as_ref()
677 .map_witness_result(|wit| converter.convert_witness(&data, wit))?;
678
679 let maybe_converted = data.right_index.map(|idx| &converted[idx]);
681 let witness_inner: Inner<&usize, N::Jet, M::Disconnect, M::Witness> = witness_inner
682 .map_disconnect_result(|disc| {
683 converter.convert_disconnect(&data, maybe_converted, disc)
684 })?;
685
686 let converted_inner: Inner<Arc<Node<M>>, M::Jet, M::Disconnect, M::Witness> =
689 witness_inner.map(|idx| Arc::clone(&converted[*idx]));
690
691 let pruned_inner = if let Inner::Case(left, right) = converted_inner {
693 let hide = converter.prune_case(&data, &left, &right)?;
694
695 match hide {
696 Hide::Neither => Inner::Case(left, right),
697 Hide::Left => Inner::AssertR(left.cmr(), right),
698 Hide::Right => Inner::AssertL(left, right.cmr()),
699 }
700 } else {
701 converted_inner
702 };
703
704 converted.push(Arc::new(Node {
706 data: converter.convert_data(&data, pruned_inner.as_ref())?,
707 cmr: data.node.cmr,
708 inner: pruned_inner,
709 }));
710 }
711 Ok(converted.pop().unwrap())
712 }
713
714 pub fn display(&self) -> Display<'_, N> {
715 Display::from(self)
716 }
717
718 pub fn display_expr(&self) -> DisplayExpr<'_, N> {
723 DisplayExpr::from(self)
724 }
725
726 pub fn encode_without_witness<W: io::Write>(&self, prog: W) -> io::Result<usize> {
728 let mut w = BitWriter::new(prog);
729 let program_bits = encode::encode_program(self, &mut w)?;
730 w.flush_all()?;
731 Ok(program_bits)
732 }
733
734 pub fn to_vec_without_witness(&self) -> Vec<u8> {
736 let mut program = Vec::<u8>::new();
737 self.encode_without_witness(&mut program)
738 .expect("Vec::write is infallible");
739 debug_assert!(!program.is_empty());
740 program
741 }
742}
743
744impl<N: Marker<Witness = Value>> Node<N> {
745 pub fn encode_with_witness<W1: io::Write, W2: io::Write>(
749 &self,
750 prog: W1,
751 witness: W2,
752 ) -> io::Result<(usize, usize)> {
753 let mut prog = BitWriter::new(prog);
754 let mut witness = BitWriter::new(witness);
755
756 let sharing_iter = self.post_order_iter::<MaxSharing<N>>();
757 let program_bits = encode::encode_program(self, &mut prog)?;
758 prog.flush_all()?;
759 let witness_bits = encode::encode_witness(sharing_iter.into_witnesses(), &mut witness)?;
760 witness.flush_all()?;
761 Ok((program_bits, witness_bits))
762 }
763
764 pub fn to_vec_with_witness(&self) -> (Vec<u8>, Vec<u8>) {
766 let mut ret_1 = vec![];
767 let mut ret_2 = vec![];
768 self.encode_with_witness(&mut ret_1, &mut ret_2)
769 .expect("Vec::write is infallible");
770 (ret_1, ret_2)
771 }
772}
773
774#[cfg(test)]
775#[cfg(all(feature = "test-utils", feature = "elements"))]
776mod tests {
777 use ffi::tests::TestData;
778
779 use crate::analysis::Cost;
780 use crate::ffi;
781 use crate::jet::Elements;
782 use crate::BitIter;
783 use crate::RedeemNode;
784
785 fn check_merkle_roots(test: &TestData) {
786 let prog = BitIter::from(test.prog.as_slice());
787 let witness = BitIter::from(test.witness.as_slice());
788 ffi::tests::run_program(
789 &test.prog,
790 &test.witness,
791 ffi::tests::TestUpTo::CheckOneOne,
792 None,
793 None,
794 )
795 .unwrap();
796 let prog = RedeemNode::<Elements>::decode(prog, witness).unwrap();
797 assert_eq!(prog.cmr().to_byte_array(), test.cmr);
798 assert_eq!(prog.amr().to_byte_array(), test.amr);
799 assert_eq!(prog.ihr().to_byte_array(), test.ihr);
800 assert_eq!(prog.bounds().cost, Cost::from_milliweight(test.cost))
801 }
802
803 #[test]
804 fn progs_cmr() {
805 let schnorr0 = ffi::tests::schnorr0_test_data();
806 let schnorr6 = ffi::tests::schnorr6_test_data();
807 let ctx8_unpruned = ffi::tests::ctx8_unpruned_test_data();
808 let ctx8_pruned = ffi::tests::ctx8_pruned_test_data();
809 check_merkle_roots(&schnorr0);
811 check_merkle_roots(&schnorr6);
812 check_merkle_roots(&ctx8_unpruned);
813 check_merkle_roots(&ctx8_pruned);
814 }
815}