1use crate::analysis::Cost;
4use crate::node::{ConstructNode, Hiding, RedeemNode};
5use crate::policy::ToXOnlyPubkey;
6use crate::types;
7use crate::{Cmr, Policy, Value};
8
9use elements::bitcoin;
10use elements::locktime::Height;
11use elements::taproot::TapLeafHash;
12use hashes::Hash;
13
14use crate::jet::elements::ElementsEnv;
15use std::convert::TryFrom;
16use std::sync::Arc;
17
18pub type Preimage32 = [u8; 32];
20
21pub trait Satisfier<'brand, Pk: ToXOnlyPubkey> {
27 fn lookup_tap_leaf_script_sig(&self, _: &Pk, _: &TapLeafHash) -> Option<elements::SchnorrSig> {
29 None
30 }
31
32 fn lookup_sha256(&self, _: &Pk::Sha256) -> Option<Preimage32> {
34 None
35 }
36
37 fn check_older(&self, _: elements::Sequence) -> bool {
39 false
40 }
41
42 fn check_after(&self, _: elements::LockTime) -> bool {
44 false
45 }
46
47 fn inference_context(&self) -> &types::Context<'brand>;
62
63 fn lookup_asm_program(&self, _: Cmr) -> Option<Arc<ConstructNode<'brand>>> {
76 None
77 }
78}
79
80impl<'brand, Pk: ToXOnlyPubkey> Satisfier<'brand, Pk>
81 for (&types::Context<'brand>, elements::Sequence)
82{
83 fn inference_context(&self) -> &types::Context<'brand> {
84 self.0
85 }
86
87 fn check_older(&self, n: elements::Sequence) -> bool {
88 use elements::bitcoin::locktime::relative::LockTime::*;
89
90 let this = match bitcoin::Sequence(self.1 .0).to_relative_lock_time() {
91 Some(x) => x,
92 None => return false,
93 };
94 let n = match bitcoin::Sequence(n.0).to_relative_lock_time() {
95 Some(x) => x,
96 None => return false,
97 };
98
99 match (n, this) {
100 (Blocks(n), Blocks(lock_time)) => n <= lock_time,
101 (Time(n), Time(lock_time)) => n <= lock_time,
102 _ => false, }
104 }
105}
106
107impl<'brand, Pk: ToXOnlyPubkey> Satisfier<'brand, Pk>
108 for (&types::Context<'brand>, elements::LockTime)
109{
110 fn inference_context(&self) -> &types::Context<'brand> {
111 self.0
112 }
113
114 fn check_after(&self, n: elements::LockTime) -> bool {
115 use elements::LockTime::*;
116
117 match (n, self.1) {
118 (Blocks(n), Blocks(lock_time)) => n <= lock_time,
119 (Seconds(n), Seconds(lock_time)) => n <= lock_time,
120 _ => false, }
122 }
123}
124
125#[derive(Debug)]
126pub enum SatisfierError {
127 Unsatisfiable,
129 AssemblyFailed(crate::bit_machine::ExecutionError),
133}
134
135type SatResult<'brand> = Hiding<'brand, Arc<ConstructNode<'brand>>>;
136
137fn ok_if(condition: bool, expr: SatResult) -> SatResult {
138 match condition {
139 true => expr,
140 false => expr.hide(),
141 }
142}
143
144impl<Pk: ToXOnlyPubkey> Policy<Pk> {
145 fn satisfy_internal<'brand, S: Satisfier<'brand, Pk>>(
146 &self,
147 satisfier: &S,
148 ) -> Result<SatResult<'brand>, SatisfierError> {
149 let inference_context = satisfier.inference_context();
150 let node: SatResult = match *self {
151 Policy::Unsatisfiable(entropy) => {
152 super::serialize::unsatisfiable::<SatResult>(inference_context, entropy).hide()
153 }
154 Policy::Trivial => super::serialize::trivial(inference_context),
155 Policy::Key(ref key) => {
156 let signature = satisfier
157 .lookup_tap_leaf_script_sig(key, &TapLeafHash::all_zeros())
158 .map(|sig| sig.sig.serialize())
159 .map(Value::u512);
160 ok_if(
161 signature.is_some(),
162 super::serialize::key(inference_context, key, signature),
163 )
164 }
165 Policy::After(n) => {
166 let height = Height::from_consensus(n).expect("timelock is valid");
167 ok_if(
168 satisfier.check_after(elements::LockTime::Blocks(height)),
169 super::serialize::after(inference_context, n),
170 )
171 }
172 Policy::Older(n) => ok_if(
173 satisfier.check_older(elements::Sequence(n.into())),
174 super::serialize::older(inference_context, n),
175 ),
176 Policy::Sha256(ref hash) => {
177 let preimage = satisfier.lookup_sha256(hash).map(Value::u256);
178 ok_if(
179 preimage.is_some(),
180 super::serialize::sha256::<Pk, _, _>(inference_context, hash, preimage),
181 )
182 }
183 Policy::And {
184 ref left,
185 ref right,
186 } => {
187 let left_res = left.satisfy_internal(satisfier)?;
188 let right_res = right.satisfy_internal(satisfier)?;
189 super::serialize::and(&left_res, &right_res)
190 }
191 Policy::Or {
192 ref left,
193 ref right,
194 } => {
195 let left_res = left.satisfy_internal(satisfier)?;
196 let right_res = right.satisfy_internal(satisfier)?;
197 let take_right = match (left_res.as_node(), right_res.as_node()) {
198 (Some(left), Some(right)) => {
199 let left_cost = left
200 .finalize_unpruned()
201 .expect("serialization should be sound")
202 .bounds()
203 .cost;
204 let right_cost = right
205 .finalize_unpruned()
206 .expect("serialization should be sound")
207 .bounds()
208 .cost;
209 right_cost < left_cost
210 }
211 (None, Some(..)) => true,
212 (Some(..), None) => false,
213 (None, None) => false,
216 };
217
218 let ret = if take_right {
219 super::serialize::or(&left_res, &right_res, Some(Value::u1(1)))
220 } else {
221 super::serialize::or(&left_res, &right_res, Some(Value::u1(0)))
222 };
223 ok_if(
224 left_res.as_node().is_some() || right_res.as_node().is_some(),
225 ret,
226 )
227 }
228 Policy::Threshold(k, ref subs) => {
229 let subs_res: Vec<SatResult> = subs
230 .iter()
231 .map(|sub| sub.satisfy_internal(satisfier))
232 .collect::<Result<_, SatisfierError>>()?;
233 let costs: Vec<Cost> = subs_res
234 .iter()
235 .map(|result| match result.as_node() {
236 Some(node) => node
237 .finalize_unpruned()
238 .map(|redeem| redeem.bounds().cost)
239 .unwrap_or(Cost::CONSENSUS_MAX),
240 None => Cost::CONSENSUS_MAX,
241 })
242 .collect();
243 let selected_node_indices = {
244 let mut indices: Vec<usize> = (0..costs.len()).collect();
245 indices.sort_by_key(|&i| costs[i]);
246 indices.truncate(k);
247 indices
248 };
249 let all_selected_ok = selected_node_indices
250 .iter()
251 .all(|&i| subs_res[i].as_node().is_some());
252 let witness_bits: Vec<Option<Value>> = (0..subs_res.len())
253 .map(|i| Some(Value::u1(u8::from(selected_node_indices.contains(&i)))))
254 .collect();
255 let k = u32::try_from(k).expect("k should be less than 2^32");
256 ok_if(
257 all_selected_ok,
258 super::serialize::threshold(k, &subs_res, &witness_bits),
259 )
260 }
261 Policy::Assembly(cmr) => match satisfier.lookup_asm_program(cmr) {
262 Some(program) => Hiding::from(program),
263 None => Hiding::hidden(cmr, inference_context.shallow_clone()),
264 },
265 };
266 Ok(node)
267 }
268
269 pub fn satisfy<'brand, S: Satisfier<'brand, Pk>>(
274 &self,
275 satisfier: &S,
276 env: &ElementsEnv<Arc<elements::Transaction>>,
277 ) -> Result<Arc<RedeemNode>, SatisfierError> {
278 let result = self.satisfy_internal(satisfier)?;
279 match result.get_node() {
280 Some(program) => program
281 .finalize_unpruned()
282 .expect("serialization should be sound")
283 .prune(env)
284 .map_err(SatisfierError::AssemblyFailed), None => Err(SatisfierError::Unsatisfiable),
286 }
287 }
288}
289
290#[cfg(test)]
291mod tests {
292 use super::*;
293 use crate::bit_encoding::BitCollector;
294 use crate::dag::{DagLike, NoSharing};
295 use crate::jet::elements::ElementsEnv;
296 use crate::jet::Elements;
297 use crate::node::{CoreConstructible, JetConstructible, SimpleFinalizer, WitnessConstructible};
298 use crate::policy::serialize;
299 use crate::{BitMachine, FailEntropy, SimplicityKey};
300 use elements::bitcoin::key::{Keypair, XOnlyPublicKey};
301 use elements::secp256k1_zkp;
302 use hashes::{sha256, Hash};
303 use std::collections::HashMap;
304 use std::sync::Arc;
305
306 pub struct PolicySatisfier<'a, 'brand, Pk: SimplicityKey> {
307 pub context: types::Context<'brand>,
308 pub preimages: HashMap<Pk::Sha256, Preimage32>,
309 pub signatures: HashMap<Pk, elements::SchnorrSig>,
310 pub assembly: HashMap<Cmr, Arc<ConstructNode<'brand>>>,
311 pub tx: &'a elements::Transaction,
312 pub index: usize,
313 }
314
315 impl<'brand, Pk: ToXOnlyPubkey> Satisfier<'brand, Pk> for PolicySatisfier<'_, 'brand, Pk> {
316 fn inference_context(&self) -> &types::Context<'brand> {
317 &self.context
318 }
319
320 fn lookup_tap_leaf_script_sig(
321 &self,
322 pk: &Pk,
323 _: &TapLeafHash,
324 ) -> Option<elements::SchnorrSig> {
325 self.signatures.get(pk).copied()
326 }
327
328 fn lookup_sha256(&self, hash: &Pk::Sha256) -> Option<Preimage32> {
329 self.preimages.get(hash).copied()
330 }
331
332 fn check_older(&self, sequence: elements::Sequence) -> bool {
333 let self_sequence = self.tx.input[self.index].sequence;
334 Satisfier::<Pk>::check_older(&(&self.context, self_sequence), sequence)
335 }
336
337 fn check_after(&self, locktime: elements::LockTime) -> bool {
338 Satisfier::<Pk>::check_after(&(&self.context, self.tx.lock_time), locktime)
339 }
340
341 fn lookup_asm_program(&self, cmr: Cmr) -> Option<Arc<ConstructNode<'brand>>> {
342 self.assembly.get(&cmr).cloned()
343 }
344 }
345
346 fn get_satisfier<'tx, 'brand>(
347 context: types::Context<'brand>,
348
349 env: &'tx ElementsEnv<Arc<elements::Transaction>>,
350 ) -> PolicySatisfier<'tx, 'brand, XOnlyPublicKey> {
351 let mut preimages = HashMap::new();
352
353 for i in 0..3 {
354 let preimage = [i; 32];
355 preimages.insert(sha256::Hash::hash(&preimage), preimage);
356 }
357
358 let secp = secp256k1_zkp::Secp256k1::new();
359 let mut rng = secp256k1_zkp::rand::rngs::ThreadRng::default();
360 let mut signatures = HashMap::new();
361
362 for _ in 0..3 {
363 let keypair = Keypair::new(&secp, &mut rng);
364 let xonly = keypair.x_only_public_key().0;
365
366 let sighash = env.c_tx_env().sighash_all();
367 let msg = secp256k1_zkp::Message::from_digest(sighash.to_byte_array());
368 let sig = elements::SchnorrSig {
369 sig: keypair.sign_schnorr(msg),
370 hash_ty: elements::SchnorrSighashType::All,
371 };
372
373 signatures.insert(xonly, sig);
374 }
375
376 PolicySatisfier {
377 context,
378 preimages,
379 signatures,
380 assembly: HashMap::new(),
381 tx: env.tx(),
382 index: env.ix() as usize,
383 }
384 }
385
386 fn execute_successful(program: Arc<RedeemNode>, env: &ElementsEnv<Arc<elements::Transaction>>) {
387 let mut mac = BitMachine::for_program(&program).unwrap();
388 assert!(mac.exec(&program, env).is_ok());
389 }
390
391 fn execute_unsuccessful(
392 program: Arc<RedeemNode>,
393 env: &ElementsEnv<Arc<elements::Transaction>>,
394 ) {
395 let mut mac = BitMachine::for_program(&program).unwrap();
396 assert!(mac.exec(&program, env).is_err());
397 }
398
399 fn to_witness(program: &RedeemNode) -> Vec<&Value> {
400 program
401 .post_order_iter::<NoSharing>()
402 .into_witnesses()
403 .collect()
404 }
405
406 #[test]
407 fn satisfy_unsatisfiable() {
408 types::Context::with_context(|ctx| {
409 let env = ElementsEnv::dummy();
410 let satisfier = get_satisfier(ctx, &env);
411 let policy = Policy::Unsatisfiable(FailEntropy::ZERO);
412
413 assert!(policy.satisfy(&satisfier, &env).is_err());
414
415 let commit = policy.commit().expect("no asm");
416 let program = commit
417 .finalize(&mut SimpleFinalizer::new(std::iter::empty()))
418 .expect("finalize");
419
420 execute_unsuccessful(program, &env);
421 });
422 }
423
424 #[test]
425 fn satisfy_trivial() {
426 types::Context::with_context(|ctx| {
427 let env = ElementsEnv::dummy();
428 let satisfier = get_satisfier(ctx, &env);
429 let policy = Policy::Trivial;
430
431 let program = policy.satisfy(&satisfier, &env).expect("satisfiable");
432 let witness = to_witness(&program);
433 assert!(witness.is_empty());
434
435 execute_successful(program, &env);
436 });
437 }
438
439 #[test]
440 fn satisfy_pk() {
441 types::Context::with_context(|ctx| {
442 let env = ElementsEnv::dummy();
443 let satisfier = get_satisfier(ctx, &env);
444 let mut it = satisfier.signatures.keys();
445 let xonly = it.next().unwrap();
446 let policy = Policy::Key(*xonly);
447
448 let program = policy.satisfy(&satisfier, &env).expect("satisfiable");
449 let witness = to_witness(&program);
450 assert_eq!(1, witness.len());
451
452 let sighash = env.c_tx_env().sighash_all();
453 let message = secp256k1_zkp::Message::from_digest(sighash.to_byte_array());
454 let signature_bytes = witness[0]
455 .iter_padded()
456 .try_collect_bytes()
457 .expect("to bytes");
458 let signature = secp256k1_zkp::schnorr::Signature::from_slice(&signature_bytes)
459 .expect("to signature");
460 assert!(signature.verify(&message, xonly).is_ok());
461
462 execute_successful(program, &env);
463 });
464 }
465
466 #[test]
467 fn satisfy_sha256() {
468 types::Context::with_context(|ctx| {
469 let env = ElementsEnv::dummy();
470 let satisfier = get_satisfier(ctx, &env);
471 let mut it = satisfier.preimages.keys();
472 let image = *it.next().unwrap();
473 let policy = Policy::Sha256(image);
474
475 let program = policy.satisfy(&satisfier, &env).expect("satisfiable");
476 let witness = to_witness(&program);
477 assert_eq!(1, witness.len());
478
479 let witness_bytes = witness[0]
480 .iter_padded()
481 .try_collect_bytes()
482 .expect("to bytes");
483 let witness_preimage =
484 Preimage32::try_from(witness_bytes.as_slice()).expect("to array");
485 let preimage = *satisfier.preimages.get(&image).unwrap();
486 assert_eq!(preimage, witness_preimage);
487
488 execute_successful(program, &env);
489 });
490 }
491
492 #[test]
493 fn satisfy_after() {
494 types::Context::with_context(|ctx| {
495 let height = Height::from_consensus(42).unwrap();
496 let env = ElementsEnv::dummy_with(
497 elements::LockTime::Blocks(height),
498 elements::Sequence::ZERO,
499 );
500 let satisfier = get_satisfier(ctx, &env);
501
502 let policy0 = Policy::After(41);
503 let program = policy0.satisfy(&satisfier, &env).expect("satisfiable");
504 let witness = to_witness(&program);
505 assert!(witness.is_empty());
506 execute_successful(program, &env);
507
508 let policy1 = Policy::After(42);
509 let program = policy1.satisfy(&satisfier, &env).expect("satisfiable");
510 let witness = to_witness(&program);
511 assert!(witness.is_empty());
512 execute_successful(program, &env);
513
514 let policy2 = Policy::After(43);
515 assert!(policy2.satisfy(&satisfier, &env).is_err(), "unsatisfiable");
516 });
517 }
518
519 #[test]
520 fn satisfy_older() {
521 types::Context::with_context(|ctx| {
522 let env = ElementsEnv::dummy_with(
523 elements::LockTime::ZERO,
524 elements::Sequence::from_consensus(42),
525 );
526 let satisfier = get_satisfier(ctx, &env);
527
528 let policy0 = Policy::Older(41);
529 let program = policy0.satisfy(&satisfier, &env).expect("satisfiable");
530 let witness = to_witness(&program);
531 assert!(witness.is_empty());
532 execute_successful(program, &env);
533
534 let policy1 = Policy::Older(42);
535 let program = policy1.satisfy(&satisfier, &env).expect("satisfiable");
536 let witness = to_witness(&program);
537 assert!(witness.is_empty());
538 execute_successful(program, &env);
539
540 let policy2 = Policy::Older(43);
541 assert!(policy2.satisfy(&satisfier, &env).is_err(), "unsatisfiable");
542 });
543 }
544
545 #[test]
546 fn satisfy_and() {
547 types::Context::with_context(|ctx| {
548 let env = ElementsEnv::dummy();
549 let satisfier = get_satisfier(ctx, &env);
550 let images: Vec<_> = satisfier.preimages.keys().copied().collect();
551 let preimages: Vec<_> = images
552 .iter()
553 .map(|x| satisfier.preimages.get(x).unwrap())
554 .collect();
555
556 let policy0 = Policy::And {
559 left: Arc::new(Policy::Sha256(images[0])),
560 right: Arc::new(Policy::Sha256(images[1])),
561 };
562 let program = policy0.satisfy(&satisfier, &env).expect("satisfiable");
563 let witness = to_witness(&program);
564 assert_eq!(2, witness.len());
565
566 for i in 0..2 {
567 let preimage_bytes = witness[i]
568 .iter_padded()
569 .try_collect_bytes()
570 .expect("to bytes");
571 let witness_preimage =
572 Preimage32::try_from(preimage_bytes.as_slice()).expect("to array");
573 assert_eq!(preimages[i], &witness_preimage);
574 }
575
576 execute_successful(program, &env);
577
578 let policy1 = Policy::And {
581 left: Arc::new(Policy::Sha256(sha256::Hash::from_byte_array([0; 32]))),
582 right: Arc::new(Policy::Sha256(images[1])),
583 };
584 assert!(policy1.satisfy(&satisfier, &env).is_err());
585
586 let policy2 = Policy::And {
589 left: Arc::new(Policy::Sha256(images[0])),
590 right: Arc::new(Policy::Sha256(sha256::Hash::from_byte_array([0; 32]))),
591 };
592 assert!(policy2.satisfy(&satisfier, &env).is_err());
593 });
594 }
595
596 #[test]
597 fn satisfy_or() {
598 types::Context::with_context(|ctx| {
599 let env = ElementsEnv::dummy();
600 let satisfier = get_satisfier(ctx, &env);
601 let images: Vec<_> = satisfier.preimages.keys().copied().collect();
602 let preimages: Vec<_> = images.iter().map(|x| satisfier.preimages[x]).collect();
603
604 let assert_branch = |policy: &Policy<XOnlyPublicKey>, bit: bool| {
605 let program = policy.satisfy(&satisfier, &env).expect("satisfiable");
606 let witness = to_witness(&program);
607 assert_eq!(2, witness.len());
608
609 assert_eq!(Value::u1(u8::from(bit)), *witness[0]);
610 let preimage_bytes = witness[1]
611 .iter_padded()
612 .try_collect_bytes()
613 .expect("to bytes");
614 let witness_preimage =
615 Preimage32::try_from(preimage_bytes.as_slice()).expect("to array");
616 assert_eq!(preimages[usize::from(bit)], witness_preimage);
617
618 execute_successful(program, &env);
619 };
620
621 let policy0 = Policy::Or {
624 left: Arc::new(Policy::Sha256(images[0])),
625 right: Arc::new(Policy::Sha256(images[1])),
626 };
627 assert_branch(&policy0, false);
628
629 let policy1 = Policy::Or {
632 left: Arc::new(Policy::Sha256(images[0])),
633 right: Arc::new(Policy::Sha256(sha256::Hash::from_byte_array([1; 32]))),
634 };
635 assert_branch(&policy1, false);
636
637 let policy2 = Policy::Or {
640 left: Arc::new(Policy::Sha256(sha256::Hash::from_byte_array([0; 32]))),
641 right: Arc::new(Policy::Sha256(images[1])),
642 };
643 assert_branch(&policy2, true);
644
645 let policy3 = Policy::Or {
648 left: Arc::new(Policy::Sha256(sha256::Hash::from_byte_array([0; 32]))),
649 right: Arc::new(Policy::Sha256(sha256::Hash::from_byte_array([1; 32]))),
650 };
651 assert!(policy3.satisfy(&satisfier, &env).is_err());
652 });
653 }
654
655 #[test]
656 fn satisfy_thresh() {
657 types::Context::with_context(|ctx| {
658 let env = ElementsEnv::dummy();
659 let satisfier = get_satisfier(ctx, &env);
660 let images: Vec<_> = satisfier.preimages.keys().copied().collect();
661 let preimages: Vec<_> = images
662 .iter()
663 .map(|x| satisfier.preimages.get(x).unwrap())
664 .collect();
665
666 let assert_branches = |policy: &Policy<XOnlyPublicKey>, bits: &[bool]| {
667 let program = policy.satisfy(&satisfier, &env).expect("satisfiable");
668 let witness = to_witness(&program);
669 assert_eq!(
670 witness.len(),
671 bits.len() + bits.iter().filter(|b| **b).count(),
672 );
673
674 let mut witidx = 0;
675 for (bit_n, bit) in bits.iter().copied().enumerate() {
676 assert_eq!(*witness[witidx], Value::u1(bit.into()));
677 witidx += 1;
678 if bit {
679 let preimage_bytes = witness[witidx]
680 .iter_padded()
681 .try_collect_bytes()
682 .expect("to bytes");
683 let witness_preimage =
684 Preimage32::try_from(preimage_bytes.as_slice()).expect("to array");
685 assert_eq!(preimages[bit_n], &witness_preimage);
686 witidx += 1;
687 }
688 }
689
690 execute_successful(program, &env);
691 };
692
693 let image_from_bit = |bit: bool, j: u8| {
694 if bit {
695 images[j as usize]
696 } else {
697 sha256::Hash::from_byte_array([j; 32])
698 }
699 };
700
701 for &bit0 in &[true, false] {
702 let image0 = image_from_bit(bit0, 0);
703
704 for &bit1 in &[true, false] {
705 let image1 = image_from_bit(bit1, 1);
706
707 for &bit2 in &[true, false] {
708 let image2 = image_from_bit(bit2, 2);
709
710 let policy = Policy::Threshold(
711 2,
712 vec![
713 Policy::Sha256(image0),
714 Policy::Sha256(image1),
715 Policy::Sha256(image2),
716 ],
717 );
718
719 match u8::from(bit0) + u8::from(bit1) + u8::from(bit2) {
720 3 => assert_branches(&policy, &[bit0, bit1, false]),
721 2 => assert_branches(&policy, &[bit0, bit1, bit2]),
722 _ => assert!(policy.satisfy(&satisfier, &env).is_err()),
723 }
724 }
725 }
726 }
727 });
728 }
729
730 #[test]
731 fn satisfy_asm() {
732 types::Context::with_context(|ctx| {
733 let env = ElementsEnv::dummy();
734 let mut satisfier = get_satisfier(ctx, &env);
735
736 let mut assert_branch = |witness0: Value, witness1: Value| {
737 let ctx = &satisfier.context;
738 let asm_program = serialize::verify_bexp(
739 &Arc::<ConstructNode>::pair(
740 &Arc::<ConstructNode>::witness(ctx, Some(witness0.clone())),
741 &Arc::<ConstructNode>::witness(ctx, Some(witness1.clone())),
742 )
743 .expect("sound types"),
744 &Arc::<ConstructNode>::jet(ctx, &Elements::Eq8),
745 );
746 let cmr = asm_program.cmr();
747 satisfier.assembly.insert(cmr, asm_program);
748
749 let policy = Policy::Assembly(cmr);
750 let result = policy.satisfy(&satisfier, &env);
751
752 if witness0 == witness1 {
753 let program = result.expect("policy should be satisfiable");
754 let witness = to_witness(&program);
755
756 assert_eq!(2, witness.len());
757 assert_eq!(&witness0, witness[0]);
758 assert_eq!(&witness1, witness[1]);
759
760 execute_successful(program, &env);
761 } else {
762 assert!(matches!(result, Err(SatisfierError::AssemblyFailed(..))));
763 }
764 };
765
766 for a in 0..2 {
767 for b in 0..2 {
768 assert_branch(Value::u8(a), Value::u8(b))
769 }
770 }
771 });
772 }
773
774 #[test]
775 #[ignore]
776 fn satisfy_asm_and_older() {
777 types::Context::with_context(|ctx| {
778 let env = ElementsEnv::dummy_with(
779 elements::LockTime::ZERO,
780 elements::Sequence::from_consensus(42),
781 );
782 let mut satisfier = get_satisfier(ctx, &env);
783
784 let mut assert_branch = |witness0: Value, witness1: Value| {
785 let ctx = &satisfier.context;
786 let asm_program = serialize::verify_bexp(
787 &Arc::<ConstructNode>::pair(
788 &Arc::<ConstructNode>::witness(ctx, Some(witness0.clone())),
789 &Arc::<ConstructNode>::witness(ctx, Some(witness1.clone())),
790 )
791 .expect("sound types"),
792 &Arc::<ConstructNode>::jet(ctx, &Elements::Eq8),
793 );
794 let cmr = asm_program.cmr();
795 satisfier.assembly.insert(cmr, asm_program);
796
797 let policy = Policy::And {
798 left: Arc::new(Policy::Assembly(cmr)),
799 right: Arc::new(Policy::Older(41)),
800 };
801 let result = policy.satisfy(&satisfier, &env);
802
803 if witness0 == witness1 {
804 let program = result.expect("policy should be satisfiable");
805 let witness = to_witness(&program);
806
807 assert_eq!(2, witness.len());
808 assert_eq!(&witness0, witness[0]);
809 assert_eq!(&witness1, witness[1]);
810
811 execute_successful(program, &env);
812 } else {
813 assert!(matches!(result, Err(SatisfierError::AssemblyFailed(..))));
814 }
815 };
816
817 for a in 0..2 {
818 for b in 0..2 {
819 assert_branch(Value::u8(a), Value::u8(b))
820 }
821 }
822 });
823 }
824}