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