From 169d8498567e33b5ccf9ff37788884538914c72d Mon Sep 17 00:00:00 2001 From: Aman Rojjha <aman.rojjha@research.iiit.ac.in> Date: Wed, 20 Apr 2022 01:13:59 +0530 Subject: [PATCH] Add policy to descriptor target compilation method --- src/policy/concrete.rs | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index fc79704e3..f2e4853e3 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -100,6 +100,21 @@ pub enum PolicyError { DuplicatePubKeys, } +/// Descriptor context for [`Policy`] compilation into a [`Descriptor`] +pub enum DescriptorCtx<Pk> { + /// [Bare][`Descriptor::Bare`] + Bare, + /// [Sh][`Descriptor::Sh`] + Sh, + /// [Wsh][`Descriptor::Wsh`] + Wsh, + /// Sh-wrapped [Wsh][`Descriptor::Wsh`] + ShWsh, + /// [Tr][`Descriptor::Tr`] where the Option<Pk> corresponds to the internal_key if no internal + /// key can be inferred from the given policy + Tr(Option<Pk>), +} + impl fmt::Display for PolicyError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { @@ -289,6 +304,31 @@ impl<Pk: MiniscriptKey> Policy<Pk> { } } + /// Compile the [`Policy`] into desc_ctx [`Descriptor`] + /// + /// In case of [Tr][`DescriptorCtx::Tr`], `internal_key` is used for the Taproot comilation when + /// no public key can be inferred from the given policy + #[cfg(feature = "compiler")] + pub fn compile_to_descriptor<Ctx: ScriptContext>( + &self, + desc_ctx: DescriptorCtx<Pk>, + ) -> Result<Descriptor<Pk>, Error> { + self.is_valid()?; + match self.is_safe_nonmalleable() { + (false, _) => Err(Error::from(CompilerError::TopLevelNonSafe)), + (_, false) => Err(Error::from( + CompilerError::ImpossibleNonMalleableCompilation, + )), + _ => match desc_ctx { + DescriptorCtx::Bare => Descriptor::new_bare(compiler::best_compilation(self)?), + DescriptorCtx::Sh => Descriptor::new_sh(compiler::best_compilation(self)?), + DescriptorCtx::Wsh => Descriptor::new_wsh(compiler::best_compilation(self)?), + DescriptorCtx::ShWsh => Descriptor::new_sh_wsh(compiler::best_compilation(self)?), + DescriptorCtx::Tr(unspendable_key) => self.compile_tr(unspendable_key), + }, + } + } + /// Compile the descriptor into an optimized `Miniscript` representation #[cfg(feature = "compiler")] pub fn compile<Ctx: ScriptContext>(&self) -> Result<Miniscript<Pk, Ctx>, CompilerError> {