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, DisplayAsGraph, DisplayExpr, GraphFormat, SharingLevel};
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 fn compute_sharing_id(cmr: Cmr, cached_data: &Self::CachedData) -> Option<Self::SharingId>;
119}
120
121#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
123pub struct NoWitness;
124
125impl From<NoWitness> for Option<Value> {
126 fn from(_: NoWitness) -> Self {
127 None
128 }
129}
130
131pub trait Constructible<'brand, X, W>:
132 JetConstructible<'brand>
133 + DisconnectConstructible<'brand, X>
134 + WitnessConstructible<'brand, W>
135 + CoreConstructible<'brand>
136 + Sized
137{
138 fn from_inner(
139 inference_context: &types::Context<'brand>,
140 inner: Inner<&Self, &X, W>,
141 ) -> Result<Self, types::Error> {
142 match inner {
143 Inner::Iden => Ok(Self::iden(inference_context)),
144 Inner::Unit => Ok(Self::unit(inference_context)),
145 Inner::InjL(child) => Ok(Self::injl(child)),
146 Inner::InjR(child) => Ok(Self::injr(child)),
147 Inner::Take(child) => Ok(Self::take(child)),
148 Inner::Drop(child) => Ok(Self::drop_(child)),
149 Inner::Comp(left, right) => Self::comp(left, right),
150 Inner::Case(left, right) => Self::case(left, right),
151 Inner::AssertL(left, r_cmr) => Self::assertl(left, r_cmr),
152 Inner::AssertR(l_cmr, right) => Self::assertr(l_cmr, right),
153 Inner::Pair(left, right) => Self::pair(left, right),
154 Inner::Disconnect(left, right) => Self::disconnect(left, right),
155 Inner::Fail(entropy) => Ok(Self::fail(inference_context, entropy)),
156 Inner::Word(ref w) => Ok(Self::const_word(inference_context, w.shallow_clone())),
157 Inner::Jet(j) => Ok(Self::jet(inference_context, j.as_ref())),
158 Inner::Witness(w) => Ok(Self::witness(inference_context, w)),
159 }
160 }
161}
162
163impl<'brand, X, W, T> Constructible<'brand, X, W> for T where
164 T: DisconnectConstructible<'brand, X>
165 + JetConstructible<'brand>
166 + WitnessConstructible<'brand, W>
167 + CoreConstructible<'brand>
168 + Sized
169{
170}
171
172pub trait CoreConstructible<'brand>: Sized {
173 fn iden(inference_context: &types::Context<'brand>) -> Self;
174 fn unit(inference_context: &types::Context<'brand>) -> Self;
175 fn injl(child: &Self) -> Self;
176 fn injr(child: &Self) -> Self;
177 fn take(child: &Self) -> Self;
178 fn drop_(child: &Self) -> Self;
179 fn comp(left: &Self, right: &Self) -> Result<Self, types::Error>;
180 fn case(left: &Self, right: &Self) -> Result<Self, types::Error>;
181 fn assertl(left: &Self, right: Cmr) -> Result<Self, types::Error>;
182 fn assertr(left: Cmr, right: &Self) -> Result<Self, types::Error>;
183 fn pair(left: &Self, right: &Self) -> Result<Self, types::Error>;
184 fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self;
185 fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self;
186
187 fn inference_context(&self) -> &types::Context<'brand>;
189
190 fn scribe(ctx: &types::Context<'brand>, value: &Value) -> Self {
194 use crate::value::ValueRef;
195
196 #[derive(Debug, Clone)]
197 enum Task<'v> {
198 Process(ValueRef<'v>),
199 MakeLeft,
200 MakeRight,
201 MakeProduct,
202 }
203
204 let mut input = vec![Task::Process(value.as_ref())];
205 let mut output = vec![];
206 while let Some(top) = input.pop() {
207 match top {
208 Task::Process(value) => {
209 if value.is_unit() {
210 output.push(Self::unit(ctx));
211 } else if let Some(word) = value.to_word() {
212 output.push(Self::const_word(ctx, word));
213 } else if let Some(left) = value.as_left() {
214 input.push(Task::MakeLeft);
215 input.push(Task::Process(left));
216 } else if let Some(right) = value.as_right() {
217 input.push(Task::MakeRight);
218 input.push(Task::Process(right));
219 } else if let Some((left, right)) = value.as_product() {
220 input.push(Task::MakeProduct);
221 input.push(Task::Process(right));
222 input.push(Task::Process(left));
223 }
224 }
225 Task::MakeLeft => {
226 let inner = output.pop().unwrap();
227 output.push(Self::injl(&inner));
228 }
229 Task::MakeRight => {
230 let inner = output.pop().unwrap();
231 output.push(Self::injr(&inner));
232 }
233 Task::MakeProduct => {
234 let right = output.pop().unwrap();
235 let left = output.pop().unwrap();
236 output.push(
238 Self::pair(&left, &right).expect(
239 "`pair` should always succeed because input type is unrestricted",
240 ),
241 );
242 }
243 }
244 }
245 debug_assert_eq!(output.len(), 1);
246 output.pop().unwrap()
247 }
248
249 fn bit_false(inference_context: &types::Context<'brand>) -> Self {
253 let unit = Self::unit(inference_context);
254 Self::injl(&unit)
255 }
256
257 fn bit_true(inference_context: &types::Context<'brand>) -> Self {
261 let unit = Self::unit(inference_context);
262 Self::injr(&unit)
263 }
264
265 fn cond(left: &Self, right: &Self) -> Result<Self, types::Error> {
273 let drop_left = Self::drop_(left);
274 let drop_right = Self::drop_(right);
275 Self::case(&drop_right, &drop_left)
276 }
277
278 fn assert(child: &Self, hash: Cmr) -> Result<Self, types::Error> {
285 let unit = Self::unit(child.inference_context());
286 let pair_child_unit = Self::pair(child, &unit)?;
287 let assertr_hidden_unit = Self::assertr(hash, &unit)?;
288
289 Self::comp(&pair_child_unit, &assertr_hidden_unit)
290 }
291
292 #[allow(clippy::should_implement_trait)]
298 fn not(child: &Self) -> Result<Self, types::Error> {
299 let unit = Self::unit(child.inference_context());
300 let pair_child_unit = Self::pair(child, &unit)?;
301 let bit_true = Self::bit_true(child.inference_context());
302 let bit_false = Self::bit_false(child.inference_context());
303 let case_true_false = Self::case(&bit_true, &bit_false)?;
304
305 Self::comp(&pair_child_unit, &case_true_false)
306 }
307
308 fn and(left: &Self, right: &Self) -> Result<Self, types::Error> {
314 left.inference_context()
315 .check_eq(right.inference_context())?;
316 let iden = Self::iden(left.inference_context());
317 let pair_left_iden = Self::pair(left, &iden)?;
318 let bit_false = Self::bit_false(left.inference_context());
319 let drop_right = Self::drop_(right);
320 let case_false_right = Self::case(&bit_false, &drop_right)?;
321
322 Self::comp(&pair_left_iden, &case_false_right)
323 }
324
325 fn or(left: &Self, right: &Self) -> Result<Self, types::Error> {
331 left.inference_context()
332 .check_eq(right.inference_context())?;
333 let iden = Self::iden(left.inference_context());
334 let pair_left_iden = Self::pair(left, &iden)?;
335 let drop_right = Self::drop_(right);
336 let bit_true = Self::bit_true(left.inference_context());
337 let case_right_true = Self::case(&drop_right, &bit_true)?;
338
339 Self::comp(&pair_left_iden, &case_right_true)
340 }
341}
342
343pub trait DisconnectConstructible<'brand, X>: Sized {
344 fn disconnect(left: &Self, right: &X) -> Result<Self, types::Error>;
345}
346
347pub trait JetConstructible<'brand>: Sized {
348 fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self;
349}
350
351pub trait WitnessConstructible<'brand, W>: Sized {
352 fn witness(inference_context: &types::Context<'brand>, witness: W) -> Self;
353}
354
355pub struct Node<N: Marker> {
369 inner: Inner<Arc<Node<N>>, N::Disconnect, N::Witness>,
370 cmr: Cmr,
371 data: N::CachedData,
372}
373
374impl<N: Marker> PartialEq for Node<N>
375where
376 N::CachedData: PartialEq,
377{
378 fn eq(&self, other: &Self) -> bool {
379 self.cmr == other.cmr && self.data == other.data
380 }
381}
382impl<N: Marker> Eq for Node<N> where N::CachedData: Eq {}
383
384impl<N: Marker> hash::Hash for Node<N>
385where
386 N::CachedData: hash::Hash,
387{
388 fn hash<H: hash::Hasher>(&self, h: &mut H) {
389 self.cmr.hash(h);
390 self.data.hash(h);
391 }
392}
393
394impl<N: Marker> fmt::Debug for Node<N>
395where
396 for<'a> &'a Node<N>: DagLike,
397{
398 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
399 self.post_order_iter::<MaxSharing<N>>().into_display(
400 f,
401 |node, f| fmt::Display::fmt(&node.inner, f),
402 |_, _| Ok(()),
403 )
404 }
405}
406
407#[cfg(feature = "base64")]
408impl<N: Marker> fmt::Display for Node<N> {
409 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
413 use crate::base64::display::Base64Display;
414 use crate::base64::engine::general_purpose;
415
416 let v = self.to_vec_without_witness();
417 Base64Display::new(&v, &general_purpose::STANDARD).fmt(f)
418 }
419}
420
421impl<N: Marker> HasCmr for Node<N> {
422 fn cmr(&self) -> Cmr {
423 self.cmr
424 }
425}
426
427impl<N: Marker> HasCmr for Arc<Node<N>> {
428 fn cmr(&self) -> Cmr {
429 self.cmr
430 }
431}
432
433impl<'brand, N> CoreConstructible<'brand> for Arc<Node<N>>
434where
435 N: Marker,
436 N::CachedData: CoreConstructible<'brand>,
437{
438 fn iden(inference_context: &types::Context<'brand>) -> Self {
439 Arc::new(Node {
440 cmr: Cmr::iden(),
441 data: N::CachedData::iden(inference_context),
442 inner: Inner::Iden,
443 })
444 }
445
446 fn unit(inference_context: &types::Context<'brand>) -> Self {
447 Arc::new(Node {
448 cmr: Cmr::unit(),
449 data: N::CachedData::unit(inference_context),
450 inner: Inner::Unit,
451 })
452 }
453
454 fn injl(child: &Self) -> Self {
455 Arc::new(Node {
456 cmr: Cmr::injl(child.cmr()),
457 data: N::CachedData::injl(&child.data),
458 inner: Inner::InjL(Arc::clone(child)),
459 })
460 }
461
462 fn injr(child: &Self) -> Self {
463 Arc::new(Node {
464 cmr: Cmr::injr(child.cmr()),
465 data: N::CachedData::injr(&child.data),
466 inner: Inner::InjR(Arc::clone(child)),
467 })
468 }
469
470 fn take(child: &Self) -> Self {
471 Arc::new(Node {
472 cmr: Cmr::take(child.cmr()),
473 data: N::CachedData::take(&child.data),
474 inner: Inner::Take(Arc::clone(child)),
475 })
476 }
477
478 fn drop_(child: &Self) -> Self {
479 Arc::new(Node {
480 cmr: Cmr::drop(child.cmr()),
481 data: N::CachedData::drop_(&child.data),
482 inner: Inner::Drop(Arc::clone(child)),
483 })
484 }
485
486 fn comp(left: &Self, right: &Self) -> Result<Self, types::Error> {
487 Ok(Arc::new(Node {
488 cmr: Cmr::comp(left.cmr(), right.cmr()),
489 data: N::CachedData::comp(&left.data, &right.data)?,
490 inner: Inner::Comp(Arc::clone(left), Arc::clone(right)),
491 }))
492 }
493
494 fn case(left: &Self, right: &Self) -> Result<Self, types::Error> {
495 Ok(Arc::new(Node {
496 cmr: Cmr::case(left.cmr(), right.cmr()),
497 data: N::CachedData::case(&left.data, &right.data)?,
498 inner: Inner::Case(Arc::clone(left), Arc::clone(right)),
499 }))
500 }
501
502 fn assertl(left: &Self, r_cmr: Cmr) -> Result<Self, types::Error> {
503 Ok(Arc::new(Node {
504 cmr: Cmr::case(left.cmr(), r_cmr),
505 data: N::CachedData::assertl(&left.data, r_cmr)?,
506 inner: Inner::AssertL(Arc::clone(left), r_cmr),
507 }))
508 }
509
510 fn assertr(l_cmr: Cmr, right: &Self) -> Result<Self, types::Error> {
511 Ok(Arc::new(Node {
512 cmr: Cmr::case(l_cmr, right.cmr()),
513 data: N::CachedData::assertr(l_cmr, &right.data)?,
514 inner: Inner::AssertR(l_cmr, Arc::clone(right)),
515 }))
516 }
517
518 fn pair(left: &Self, right: &Self) -> Result<Self, types::Error> {
519 Ok(Arc::new(Node {
520 cmr: Cmr::pair(left.cmr(), right.cmr()),
521 data: N::CachedData::pair(&left.data, &right.data)?,
522 inner: Inner::Pair(Arc::clone(left), Arc::clone(right)),
523 }))
524 }
525
526 fn fail(inference_context: &types::Context<'brand>, entropy: FailEntropy) -> Self {
527 Arc::new(Node {
528 cmr: Cmr::fail(entropy),
529 data: N::CachedData::fail(inference_context, entropy),
530 inner: Inner::Fail(entropy),
531 })
532 }
533
534 fn const_word(inference_context: &types::Context<'brand>, word: Word) -> Self {
535 Arc::new(Node {
536 cmr: Cmr::const_word(&word),
537 data: N::CachedData::const_word(inference_context, word.shallow_clone()),
538 inner: Inner::Word(word),
539 })
540 }
541
542 fn inference_context(&self) -> &types::Context<'brand> {
543 self.data.inference_context()
544 }
545}
546
547impl<'brand, N> DisconnectConstructible<'brand, N::Disconnect> for Arc<Node<N>>
548where
549 N: Marker,
550 N::CachedData: DisconnectConstructible<'brand, N::Disconnect>,
551{
552 fn disconnect(left: &Self, right: &N::Disconnect) -> Result<Self, types::Error> {
553 Ok(Arc::new(Node {
554 cmr: Cmr::disconnect(left.cmr()),
555 data: N::CachedData::disconnect(&left.data, right)?,
556 inner: Inner::Disconnect(Arc::clone(left), right.clone()),
557 }))
558 }
559}
560
561impl<'brand, N> WitnessConstructible<'brand, N::Witness> for Arc<Node<N>>
562where
563 N: Marker,
564 N::CachedData: WitnessConstructible<'brand, N::Witness>,
565{
566 fn witness(inference_context: &types::Context<'brand>, value: N::Witness) -> Self {
567 Arc::new(Node {
568 cmr: Cmr::witness(),
569 data: N::CachedData::witness(inference_context, value.clone()),
570 inner: Inner::Witness(value),
571 })
572 }
573}
574
575impl<'brand, N> JetConstructible<'brand> for Arc<Node<N>>
576where
577 N: Marker,
578 N::CachedData: JetConstructible<'brand>,
579{
580 fn jet(inference_context: &types::Context<'brand>, jet: &dyn Jet) -> Self {
581 Arc::new(Node {
582 cmr: Cmr::jet(jet),
583 data: N::CachedData::jet(inference_context, jet),
584 inner: Inner::Jet(jet.dyn_clone()),
585 })
586 }
587}
588
589impl<N: Marker> Node<N> {
590 pub fn inner(&self) -> &Inner<Arc<Node<N>>, N::Disconnect, N::Witness> {
592 &self.inner
593 }
594
595 pub fn cmr(&self) -> Cmr {
597 self.cmr
598 }
599
600 pub fn sharing_id(&self) -> Option<N::SharingId> {
602 N::compute_sharing_id(self.cmr, &self.data)
603 }
604
605 pub fn cached_data(&self) -> &N::CachedData {
607 &self.data
608 }
609
610 pub fn from_parts(
619 inner: Inner<Arc<Self>, N::Disconnect, N::Witness>,
620 data: N::CachedData,
621 ) -> Self {
622 let cmr = match &inner {
623 Inner::Unit => Cmr::unit(),
624 Inner::Iden => Cmr::iden(),
625 Inner::InjL(ref c) => Cmr::injl(c.cmr()),
626 Inner::InjR(ref c) => Cmr::injr(c.cmr()),
627 Inner::Take(ref c) => Cmr::take(c.cmr()),
628 Inner::Drop(ref c) => Cmr::drop(c.cmr()),
629 Inner::Comp(ref cl, ref cr) => Cmr::comp(cl.cmr(), cr.cmr()),
630 Inner::Case(ref cl, ref cr) => Cmr::case(cl.cmr(), cr.cmr()),
631 Inner::AssertL(ref c, cmr) => Cmr::case(c.cmr(), *cmr),
632 Inner::AssertR(cmr, ref c) => Cmr::case(*cmr, c.cmr()),
633 Inner::Pair(ref cl, ref cr) => Cmr::pair(cl.cmr(), cr.cmr()),
634 Inner::Disconnect(ref cl, _) => Cmr::disconnect(cl.cmr()),
635 Inner::Witness(_) => Cmr::witness(),
636 Inner::Fail(entropy) => Cmr::fail(*entropy),
637 Inner::Jet(j) => Cmr::jet(j.as_ref()),
638 Inner::Word(ref w) => Cmr::const_word(w),
639 };
640
641 Node { cmr, inner, data }
642 }
643
644 pub fn convert<S, M, C>(&self, converter: &mut C) -> Result<Arc<Node<M>>, C::Error>
652 where
653 S: for<'a> SharingTracker<&'a Self> + Default,
654 M: Marker,
655 C: Converter<N, M>,
656 {
657 let mut converted: Vec<Arc<Node<M>>> = vec![];
658 for data in self.post_order_iter::<S>() {
659 converter.visit_node(&data);
661
662 let indexed_inner: Inner<usize, &N::Disconnect, &N::Witness> = data
666 .node
667 .inner
668 .as_ref()
669 .map_left_right(|_| data.left_index.unwrap(), |_| data.right_index.unwrap());
670
671 let witness_inner: Inner<&usize, &&N::Disconnect, M::Witness> = indexed_inner
673 .as_ref()
674 .map_witness_result(|wit| converter.convert_witness(&data, wit))?;
675
676 let maybe_converted = data.right_index.map(|idx| &converted[idx]);
678 let witness_inner: Inner<&usize, M::Disconnect, M::Witness> = witness_inner
679 .map_disconnect_result(|disc| {
680 converter.convert_disconnect(&data, maybe_converted, disc)
681 })?;
682
683 let converted_inner: Inner<Arc<Node<M>>, M::Disconnect, M::Witness> =
686 witness_inner.map(|idx| Arc::clone(&converted[*idx]));
687
688 let pruned_inner = if let Inner::Case(left, right) = converted_inner {
690 let hide = converter.prune_case(&data, &left, &right)?;
691
692 match hide {
693 Hide::Neither => Inner::Case(left, right),
694 Hide::Left => Inner::AssertR(left.cmr(), right),
695 Hide::Right => Inner::AssertL(left, right.cmr()),
696 }
697 } else {
698 converted_inner
699 };
700
701 converted.push(Arc::new(Node {
703 data: converter.convert_data(&data, pruned_inner.as_ref())?,
704 cmr: data.node.cmr,
705 inner: pruned_inner,
706 }));
707 }
708 Ok(converted.pop().unwrap())
709 }
710
711 pub fn display(&self) -> Display<'_, N> {
712 Display::from(self)
713 }
714
715 pub fn display_expr(&self) -> DisplayExpr<'_, N> {
720 DisplayExpr::from(self)
721 }
722
723 pub fn display_as_graph(
734 &self,
735 format: GraphFormat,
736 sharing_level: SharingLevel,
737 ) -> DisplayAsGraph<'_, N> {
738 DisplayAsGraph::new(self, format, sharing_level)
739 }
740
741 pub fn display_as_dot(&self) -> DisplayAsGraph<'_, N> {
746 DisplayAsGraph::new(self, GraphFormat::Dot, SharingLevel::None)
747 }
748
749 pub fn display_as_mermaid(&self) -> DisplayAsGraph<'_, N> {
754 DisplayAsGraph::new(self, GraphFormat::Mermaid, SharingLevel::None)
755 }
756
757 pub fn encode_without_witness(&self, prog: &mut dyn io::Write) -> io::Result<usize> {
759 let mut w = BitWriter::new(prog);
760 let program_bits = encode::encode_program(self, &mut w)?;
761 w.flush_all()?;
762 Ok(program_bits)
763 }
764
765 pub fn to_vec_without_witness(&self) -> Vec<u8> {
767 let mut program = Vec::<u8>::new();
768 self.encode_without_witness(&mut program)
769 .expect("Vec::write is infallible");
770 debug_assert!(!program.is_empty());
771 program
772 }
773}
774
775impl<N: Marker<Witness = Value>> Node<N> {
776 pub fn encode_with_witness(
780 &self,
781 prog: &mut dyn io::Write,
782 witness: &mut dyn io::Write,
783 ) -> io::Result<(usize, usize)> {
784 let mut prog = BitWriter::new(prog);
785 let mut witness = BitWriter::new(witness);
786
787 let sharing_iter = self.post_order_iter::<MaxSharing<N>>();
788 let program_bits = encode::encode_program(self, &mut prog)?;
789 prog.flush_all()?;
790 let witness_bits = encode::encode_witness(sharing_iter.into_witnesses(), &mut witness)?;
791 witness.flush_all()?;
792 Ok((program_bits, witness_bits))
793 }
794
795 pub fn to_vec_with_witness(&self) -> (Vec<u8>, Vec<u8>) {
797 let mut ret_1 = vec![];
798 let mut ret_2 = vec![];
799 self.encode_with_witness(&mut ret_1, &mut ret_2)
800 .expect("Vec::write is infallible");
801 (ret_1, ret_2)
802 }
803}
804
805#[cfg(test)]
806#[cfg(all(feature = "test-utils", feature = "elements"))]
807mod tests {
808 use ffi::tests::TestData;
809
810 use crate::analysis::Cost;
811 use crate::ffi;
812 use crate::jet::Elements;
813 use crate::BitIter;
814 use crate::RedeemNode;
815
816 fn check_merkle_roots(test: &TestData) {
817 let prog = BitIter::from(test.prog.as_slice());
818 let witness = BitIter::from(test.witness.as_slice());
819 ffi::tests::run_program(
820 &test.prog,
821 &test.witness,
822 ffi::tests::TestUpTo::CheckOneOne,
823 None,
824 None,
825 )
826 .unwrap();
827 let prog = RedeemNode::decode::<_, _, Elements>(prog, witness).unwrap();
828 assert_eq!(prog.cmr().to_byte_array(), test.cmr);
829 assert_eq!(prog.amr().to_byte_array(), test.amr);
830 assert_eq!(prog.ihr().to_byte_array(), test.ihr);
831 assert_eq!(prog.bounds().cost, Cost::from_milliweight(test.cost))
832 }
833
834 #[test]
835 fn progs_cmr() {
836 let schnorr0 = ffi::tests::schnorr0_test_data();
837 let schnorr6 = ffi::tests::schnorr6_test_data();
838 let ctx8_unpruned = ffi::tests::ctx8_unpruned_test_data();
839 let ctx8_pruned = ffi::tests::ctx8_pruned_test_data();
840 check_merkle_roots(&schnorr0);
842 check_merkle_roots(&schnorr6);
843 check_merkle_roots(&ctx8_unpruned);
844 check_merkle_roots(&ctx8_pruned);
845 }
846}