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