1use crate::dag::{DagLike, MaxSharing, SharingTracker};
67use crate::jet::Jet;
68use crate::{types, Cmr, FailEntropy, HasCmr, Value};
69
70use std::sync::Arc;
71use std::{fmt, hash};
72
73mod commit;
74mod construct;
75mod convert;
76mod disconnect;
77mod display;
78mod hiding;
79mod inner;
80mod redeem;
81
82use crate::value::Word;
83pub use commit::{Commit, CommitData, CommitNode};
84pub use construct::{Construct, ConstructData, ConstructNode};
85pub use convert::{Converter, Hide, SimpleFinalizer};
86pub use disconnect::{Disconnectable, NoDisconnect};
87use display::DisplayExpr;
88pub use hiding::Hiding;
89pub use inner::Inner;
90pub use redeem::{Redeem, RedeemData, RedeemNode};
91
92pub trait Marker:
96 Copy + Clone + PartialEq + Eq + PartialOrd + Ord + fmt::Debug + hash::Hash
97{
98 type CachedData: Clone;
100
101 type Witness: Clone;
104
105 type Disconnect: Disconnectable<Node<Self>> + Clone;
107
108 type SharingId: hash::Hash + Clone + Eq;
111
112 type Jet: Jet;
114
115 fn compute_sharing_id(cmr: Cmr, cached_data: &Self::CachedData) -> Option<Self::SharingId>;
121}
122
123#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
125pub struct NoWitness;
126
127pub trait Constructible<J, X, W>:
128 JetConstructible<J>
129 + DisconnectConstructible<X>
130 + WitnessConstructible<W>
131 + CoreConstructible
132 + Sized
133{
134 fn from_inner(
135 inference_context: &types::Context,
136 inner: Inner<&Self, J, &X, W>,
137 ) -> Result<Self, types::Error> {
138 match inner {
139 Inner::Iden => Ok(Self::iden(inference_context)),
140 Inner::Unit => Ok(Self::unit(inference_context)),
141 Inner::InjL(child) => Ok(Self::injl(child)),
142 Inner::InjR(child) => Ok(Self::injr(child)),
143 Inner::Take(child) => Ok(Self::take(child)),
144 Inner::Drop(child) => Ok(Self::drop_(child)),
145 Inner::Comp(left, right) => Self::comp(left, right),
146 Inner::Case(left, right) => Self::case(left, right),
147 Inner::AssertL(left, r_cmr) => Self::assertl(left, r_cmr),
148 Inner::AssertR(l_cmr, right) => Self::assertr(l_cmr, right),
149 Inner::Pair(left, right) => Self::pair(left, right),
150 Inner::Disconnect(left, right) => Self::disconnect(left, right),
151 Inner::Fail(entropy) => Ok(Self::fail(inference_context, entropy)),
152 Inner::Word(ref w) => Ok(Self::const_word(inference_context, w.shallow_clone())),
153 Inner::Jet(j) => Ok(Self::jet(inference_context, j)),
154 Inner::Witness(w) => Ok(Self::witness(inference_context, w)),
155 }
156 }
157}
158
159impl<J, X, W, T> Constructible<J, X, W> for T where
160 T: DisconnectConstructible<X>
161 + JetConstructible<J>
162 + WitnessConstructible<W>
163 + CoreConstructible
164 + Sized
165{
166}
167
168pub trait CoreConstructible: Sized {
169 fn iden(inference_context: &types::Context) -> Self;
170 fn unit(inference_context: &types::Context) -> Self;
171 fn injl(child: &Self) -> Self;
172 fn injr(child: &Self) -> Self;
173 fn take(child: &Self) -> Self;
174 fn drop_(child: &Self) -> Self;
175 fn comp(left: &Self, right: &Self) -> Result<Self, types::Error>;
176 fn case(left: &Self, right: &Self) -> Result<Self, types::Error>;
177 fn assertl(left: &Self, right: Cmr) -> Result<Self, types::Error>;
178 fn assertr(left: Cmr, right: &Self) -> Result<Self, types::Error>;
179 fn pair(left: &Self, right: &Self) -> Result<Self, types::Error>;
180 fn fail(inference_context: &types::Context, entropy: FailEntropy) -> Self;
181 fn const_word(inference_context: &types::Context, word: Word) -> Self;
182
183 fn inference_context(&self) -> &types::Context;
185
186 fn scribe(ctx: &types::Context, value: &Value) -> Self {
190 use crate::value::ValueRef;
191
192 #[derive(Debug, Clone)]
193 enum Task<'v> {
194 Process(ValueRef<'v>),
195 MakeLeft,
196 MakeRight,
197 MakeProduct,
198 }
199
200 let mut input = vec![Task::Process(value.as_ref())];
201 let mut output = vec![];
202 while let Some(top) = input.pop() {
203 match top {
204 Task::Process(value) => {
205 if value.is_unit() {
206 output.push(Self::unit(ctx));
207 } else if let Some(word) = value.to_word() {
208 output.push(Self::const_word(ctx, word));
209 } else if let Some(left) = value.as_left() {
210 input.push(Task::MakeLeft);
211 input.push(Task::Process(left));
212 } else if let Some(right) = value.as_right() {
213 input.push(Task::MakeRight);
214 input.push(Task::Process(right));
215 } else if let Some((left, right)) = value.as_product() {
216 input.push(Task::MakeProduct);
217 input.push(Task::Process(right));
218 input.push(Task::Process(left));
219 }
220 }
221 Task::MakeLeft => {
222 let inner = output.pop().unwrap();
223 output.push(Self::injl(&inner));
224 }
225 Task::MakeRight => {
226 let inner = output.pop().unwrap();
227 output.push(Self::injr(&inner));
228 }
229 Task::MakeProduct => {
230 let right = output.pop().unwrap();
231 let left = output.pop().unwrap();
232 output.push(
234 Self::pair(&left, &right).expect(
235 "`pair` should always succeed because input type is unrestricted",
236 ),
237 );
238 }
239 }
240 }
241 debug_assert_eq!(output.len(), 1);
242 output.pop().unwrap()
243 }
244
245 fn bit_false(inference_context: &types::Context) -> Self {
249 let unit = Self::unit(inference_context);
250 Self::injl(&unit)
251 }
252
253 fn bit_true(inference_context: &types::Context) -> Self {
257 let unit = Self::unit(inference_context);
258 Self::injr(&unit)
259 }
260
261 fn cond(left: &Self, right: &Self) -> Result<Self, types::Error> {
269 let drop_left = Self::drop_(left);
270 let drop_right = Self::drop_(right);
271 Self::case(&drop_right, &drop_left)
272 }
273
274 fn assert(child: &Self, hash: Cmr) -> Result<Self, types::Error> {
281 let unit = Self::unit(child.inference_context());
282 let pair_child_unit = Self::pair(child, &unit)?;
283 let assertr_hidden_unit = Self::assertr(hash, &unit)?;
284
285 Self::comp(&pair_child_unit, &assertr_hidden_unit)
286 }
287
288 #[allow(clippy::should_implement_trait)]
294 fn not(child: &Self) -> Result<Self, types::Error> {
295 let unit = Self::unit(child.inference_context());
296 let pair_child_unit = Self::pair(child, &unit)?;
297 let bit_true = Self::bit_true(child.inference_context());
298 let bit_false = Self::bit_false(child.inference_context());
299 let case_true_false = Self::case(&bit_true, &bit_false)?;
300
301 Self::comp(&pair_child_unit, &case_true_false)
302 }
303
304 fn and(left: &Self, right: &Self) -> Result<Self, types::Error> {
310 left.inference_context()
311 .check_eq(right.inference_context())?;
312 let iden = Self::iden(left.inference_context());
313 let pair_left_iden = Self::pair(left, &iden)?;
314 let bit_false = Self::bit_false(left.inference_context());
315 let drop_right = Self::drop_(right);
316 let case_false_right = Self::case(&bit_false, &drop_right)?;
317
318 Self::comp(&pair_left_iden, &case_false_right)
319 }
320
321 fn or(left: &Self, right: &Self) -> Result<Self, types::Error> {
327 left.inference_context()
328 .check_eq(right.inference_context())?;
329 let iden = Self::iden(left.inference_context());
330 let pair_left_iden = Self::pair(left, &iden)?;
331 let drop_right = Self::drop_(right);
332 let bit_true = Self::bit_true(left.inference_context());
333 let case_right_true = Self::case(&drop_right, &bit_true)?;
334
335 Self::comp(&pair_left_iden, &case_right_true)
336 }
337}
338
339pub trait DisconnectConstructible<X>: Sized {
340 fn disconnect(left: &Self, right: &X) -> Result<Self, types::Error>;
341}
342
343pub trait JetConstructible<J>: Sized {
344 fn jet(inference_context: &types::Context, jet: J) -> Self;
345}
346
347pub trait WitnessConstructible<W>: Sized {
348 fn witness(inference_context: &types::Context, witness: W) -> Self;
349}
350
351pub struct Node<N: Marker> {
365 inner: Inner<Arc<Node<N>>, N::Jet, N::Disconnect, N::Witness>,
366 cmr: Cmr,
367 data: N::CachedData,
368}
369
370impl<N: Marker> PartialEq for Node<N>
371where
372 N::CachedData: PartialEq,
373{
374 fn eq(&self, other: &Self) -> bool {
375 self.cmr == other.cmr && self.data == other.data
376 }
377}
378impl<N: Marker> Eq for Node<N> where N::CachedData: Eq {}
379
380impl<N: Marker> hash::Hash for Node<N>
381where
382 N::CachedData: hash::Hash,
383{
384 fn hash<H: hash::Hasher>(&self, h: &mut H) {
385 self.cmr.hash(h);
386 self.data.hash(h);
387 }
388}
389
390impl<N: Marker> fmt::Debug for Node<N>
391where
392 for<'a> &'a Node<N>: DagLike,
393{
394 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
395 fmt::Display::fmt(self, f)
396 }
397}
398
399impl<N: Marker> fmt::Display for Node<N>
400where
401 for<'a> &'a Node<N>: DagLike,
402{
403 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
404 self.post_order_iter::<MaxSharing<N>>().into_display(
405 f,
406 |node, f| fmt::Display::fmt(&node.inner, f),
407 |_, _| Ok(()),
408 )
409 }
410}
411
412impl<N: Marker> HasCmr for Node<N> {
413 fn cmr(&self) -> Cmr {
414 self.cmr
415 }
416}
417
418impl<N: Marker> HasCmr for Arc<Node<N>> {
419 fn cmr(&self) -> Cmr {
420 self.cmr
421 }
422}
423
424impl<N> CoreConstructible for Arc<Node<N>>
425where
426 N: Marker,
427 N::CachedData: CoreConstructible,
428{
429 fn iden(inference_context: &types::Context) -> Self {
430 Arc::new(Node {
431 cmr: Cmr::iden(),
432 data: N::CachedData::iden(inference_context),
433 inner: Inner::Iden,
434 })
435 }
436
437 fn unit(inference_context: &types::Context) -> Self {
438 Arc::new(Node {
439 cmr: Cmr::unit(),
440 data: N::CachedData::unit(inference_context),
441 inner: Inner::Unit,
442 })
443 }
444
445 fn injl(child: &Self) -> Self {
446 Arc::new(Node {
447 cmr: Cmr::injl(child.cmr()),
448 data: N::CachedData::injl(&child.data),
449 inner: Inner::InjL(Arc::clone(child)),
450 })
451 }
452
453 fn injr(child: &Self) -> Self {
454 Arc::new(Node {
455 cmr: Cmr::injr(child.cmr()),
456 data: N::CachedData::injr(&child.data),
457 inner: Inner::InjR(Arc::clone(child)),
458 })
459 }
460
461 fn take(child: &Self) -> Self {
462 Arc::new(Node {
463 cmr: Cmr::take(child.cmr()),
464 data: N::CachedData::take(&child.data),
465 inner: Inner::Take(Arc::clone(child)),
466 })
467 }
468
469 fn drop_(child: &Self) -> Self {
470 Arc::new(Node {
471 cmr: Cmr::drop(child.cmr()),
472 data: N::CachedData::drop_(&child.data),
473 inner: Inner::Drop(Arc::clone(child)),
474 })
475 }
476
477 fn comp(left: &Self, right: &Self) -> Result<Self, types::Error> {
478 Ok(Arc::new(Node {
479 cmr: Cmr::comp(left.cmr(), right.cmr()),
480 data: N::CachedData::comp(&left.data, &right.data)?,
481 inner: Inner::Comp(Arc::clone(left), Arc::clone(right)),
482 }))
483 }
484
485 fn case(left: &Self, right: &Self) -> Result<Self, types::Error> {
486 Ok(Arc::new(Node {
487 cmr: Cmr::case(left.cmr(), right.cmr()),
488 data: N::CachedData::case(&left.data, &right.data)?,
489 inner: Inner::Case(Arc::clone(left), Arc::clone(right)),
490 }))
491 }
492
493 fn assertl(left: &Self, r_cmr: Cmr) -> Result<Self, types::Error> {
494 Ok(Arc::new(Node {
495 cmr: Cmr::case(left.cmr(), r_cmr),
496 data: N::CachedData::assertl(&left.data, r_cmr)?,
497 inner: Inner::AssertL(Arc::clone(left), r_cmr),
498 }))
499 }
500
501 fn assertr(l_cmr: Cmr, right: &Self) -> Result<Self, types::Error> {
502 Ok(Arc::new(Node {
503 cmr: Cmr::case(l_cmr, right.cmr()),
504 data: N::CachedData::assertr(l_cmr, &right.data)?,
505 inner: Inner::AssertR(l_cmr, Arc::clone(right)),
506 }))
507 }
508
509 fn pair(left: &Self, right: &Self) -> Result<Self, types::Error> {
510 Ok(Arc::new(Node {
511 cmr: Cmr::pair(left.cmr(), right.cmr()),
512 data: N::CachedData::pair(&left.data, &right.data)?,
513 inner: Inner::Pair(Arc::clone(left), Arc::clone(right)),
514 }))
515 }
516
517 fn fail(inference_context: &types::Context, entropy: FailEntropy) -> Self {
518 Arc::new(Node {
519 cmr: Cmr::fail(entropy),
520 data: N::CachedData::fail(inference_context, entropy),
521 inner: Inner::Fail(entropy),
522 })
523 }
524
525 fn const_word(inference_context: &types::Context, word: Word) -> Self {
526 Arc::new(Node {
527 cmr: Cmr::const_word(&word),
528 data: N::CachedData::const_word(inference_context, word.shallow_clone()),
529 inner: Inner::Word(word),
530 })
531 }
532
533 fn inference_context(&self) -> &types::Context {
534 self.data.inference_context()
535 }
536}
537
538impl<N> DisconnectConstructible<N::Disconnect> for Arc<Node<N>>
539where
540 N: Marker,
541 N::CachedData: DisconnectConstructible<N::Disconnect>,
542{
543 fn disconnect(left: &Self, right: &N::Disconnect) -> Result<Self, types::Error> {
544 Ok(Arc::new(Node {
545 cmr: Cmr::disconnect(left.cmr()),
546 data: N::CachedData::disconnect(&left.data, right)?,
547 inner: Inner::Disconnect(Arc::clone(left), right.clone()),
548 }))
549 }
550}
551
552impl<N> WitnessConstructible<N::Witness> for Arc<Node<N>>
553where
554 N: Marker,
555 N::CachedData: WitnessConstructible<N::Witness>,
556{
557 fn witness(inference_context: &types::Context, value: N::Witness) -> Self {
558 Arc::new(Node {
559 cmr: Cmr::witness(),
560 data: N::CachedData::witness(inference_context, value.clone()),
561 inner: Inner::Witness(value),
562 })
563 }
564}
565
566impl<N> JetConstructible<N::Jet> for Arc<Node<N>>
567where
568 N: Marker,
569 N::CachedData: JetConstructible<N::Jet>,
570{
571 fn jet(inference_context: &types::Context, jet: N::Jet) -> Self {
572 Arc::new(Node {
573 cmr: Cmr::jet(jet),
574 data: N::CachedData::jet(inference_context, jet),
575 inner: Inner::Jet(jet),
576 })
577 }
578}
579
580impl<N: Marker> Node<N> {
581 pub fn inner(&self) -> &Inner<Arc<Node<N>>, N::Jet, N::Disconnect, N::Witness> {
583 &self.inner
584 }
585
586 pub fn cmr(&self) -> Cmr {
588 self.cmr
589 }
590
591 pub fn sharing_id(&self) -> Option<N::SharingId> {
593 N::compute_sharing_id(self.cmr, &self.data)
594 }
595
596 pub fn cached_data(&self) -> &N::CachedData {
598 &self.data
599 }
600
601 pub fn from_parts(
610 inner: Inner<Arc<Self>, N::Jet, N::Disconnect, N::Witness>,
611 data: N::CachedData,
612 ) -> Self {
613 let cmr = match inner {
614 Inner::Unit => Cmr::unit(),
615 Inner::Iden => Cmr::iden(),
616 Inner::InjL(ref c) => Cmr::injl(c.cmr()),
617 Inner::InjR(ref c) => Cmr::injr(c.cmr()),
618 Inner::Take(ref c) => Cmr::take(c.cmr()),
619 Inner::Drop(ref c) => Cmr::drop(c.cmr()),
620 Inner::Comp(ref cl, ref cr) => Cmr::comp(cl.cmr(), cr.cmr()),
621 Inner::Case(ref cl, ref cr) => Cmr::case(cl.cmr(), cr.cmr()),
622 Inner::AssertL(ref c, cmr) => Cmr::case(c.cmr(), cmr),
623 Inner::AssertR(cmr, ref c) => Cmr::case(cmr, c.cmr()),
624 Inner::Pair(ref cl, ref cr) => Cmr::pair(cl.cmr(), cr.cmr()),
625 Inner::Disconnect(ref cl, _) => Cmr::disconnect(cl.cmr()),
626 Inner::Witness(_) => Cmr::witness(),
627 Inner::Fail(entropy) => Cmr::fail(entropy),
628 Inner::Jet(j) => Cmr::jet(j),
629 Inner::Word(ref w) => Cmr::const_word(w),
630 };
631
632 Node { cmr, inner, data }
633 }
634
635 pub fn convert<S, M, C>(&self, converter: &mut C) -> Result<Arc<Node<M>>, C::Error>
643 where
644 S: for<'a> SharingTracker<&'a Self> + Default,
645 M: Marker<Jet = <N as Marker>::Jet>,
646 C: Converter<N, M>,
647 {
648 let mut converted: Vec<Arc<Node<M>>> = vec![];
649 for data in self.post_order_iter::<S>() {
650 converter.visit_node(&data);
652
653 let indexed_inner: Inner<usize, N::Jet, &N::Disconnect, &N::Witness> = data
657 .node
658 .inner
659 .as_ref()
660 .map_left_right(|_| data.left_index.unwrap(), |_| data.right_index.unwrap());
661
662 let witness_inner: Inner<&usize, M::Jet, &&N::Disconnect, M::Witness> = indexed_inner
664 .as_ref()
665 .map_witness_result(|wit| converter.convert_witness(&data, wit))?;
666
667 let maybe_converted = data.right_index.map(|idx| &converted[idx]);
669 let witness_inner: Inner<&usize, N::Jet, M::Disconnect, M::Witness> = witness_inner
670 .map_disconnect_result(|disc| {
671 converter.convert_disconnect(&data, maybe_converted, disc)
672 })?;
673
674 let converted_inner: Inner<Arc<Node<M>>, M::Jet, M::Disconnect, M::Witness> =
677 witness_inner.map(|idx| Arc::clone(&converted[*idx]));
678
679 let pruned_inner = if let Inner::Case(left, right) = converted_inner {
681 let hide = converter.prune_case(&data, &left, &right)?;
682
683 match hide {
684 Hide::Neither => Inner::Case(left, right),
685 Hide::Left => Inner::AssertR(left.cmr(), right),
686 Hide::Right => Inner::AssertL(left, right.cmr()),
687 }
688 } else {
689 converted_inner
690 };
691
692 converted.push(Arc::new(Node {
694 data: converter.convert_data(&data, pruned_inner.as_ref())?,
695 cmr: data.node.cmr,
696 inner: pruned_inner,
697 }));
698 }
699 Ok(converted.pop().unwrap())
700 }
701
702 pub fn display_expr(&self) -> DisplayExpr<N> {
707 DisplayExpr::from(self)
708 }
709}
710
711#[cfg(test)]
712#[cfg(all(feature = "test-utils", feature = "elements"))]
713mod tests {
714
715 use ffi::tests::TestData;
716
717 use crate::analysis::Cost;
718 use crate::ffi;
719 use crate::jet::Elements;
720 use crate::BitIter;
721 use crate::RedeemNode;
722
723 fn check_merkle_roots(test: &TestData) {
724 let prog = BitIter::from(test.prog.as_slice());
725 let witness = BitIter::from(test.witness.as_slice());
726 ffi::tests::run_program(&test.prog, &test.witness, ffi::tests::TestUpTo::CheckOneOne)
727 .unwrap();
728 let prog = RedeemNode::<Elements>::decode(prog, witness).unwrap();
729 assert_eq!(prog.cmr().to_byte_array(), test.cmr);
730 assert_eq!(prog.amr().to_byte_array(), test.amr);
731 assert_eq!(prog.ihr().to_byte_array(), test.ihr);
732 assert_eq!(prog.bounds().cost, Cost::from_milliweight(test.cost))
733 }
734
735 #[test]
736 fn progs_cmr() {
737 let schnorr0 = ffi::tests::schnorr0_test_data();
738 let schnorr6 = ffi::tests::schnorr6_test_data();
739 let ctx8_unpruned = ffi::tests::ctx8_unpruned_test_data();
740 let ctx8_pruned = ffi::tests::ctx8_pruned_test_data();
741 check_merkle_roots(&schnorr0);
743 check_merkle_roots(&schnorr6);
744 check_merkle_roots(&ctx8_unpruned);
745 check_merkle_roots(&ctx8_pruned);
746 }
747}