diff --git a/cli/Cargo.toml b/cli/Cargo.toml index e6978712..eb8e5ddb 100644 --- a/cli/Cargo.toml +++ b/cli/Cargo.toml @@ -18,7 +18,7 @@ serde_derive = "1.0" clap = "=3.0.0-beta.2" base64 = "0.13.0" lazy_static = "1.4.0" -bitcoincore-rpc-async = "4.0.1-alpha.1" +bitcoincore-rpc-async = "4.0.1-alpha.2" tokio = { version = "1", features = ["full"] } directories = "3.0.1" rand = "^0.6" diff --git a/examples/dcf_mining_pool/Cargo.toml b/examples/dcf_mining_pool/Cargo.toml index c55c866f..063d793e 100644 --- a/examples/dcf_mining_pool/Cargo.toml +++ b/examples/dcf_mining_pool/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0" serde = "1.0" serde_derive = "1.0" tokio = { version = "1", features = ["full"] } -bitcoincore-rpc-async = "4.0.1-alpha.1" +bitcoincore-rpc-async = "4.0.1-alpha.2" [dependencies.bitcoin] diff --git a/sapio-base/Cargo.toml b/sapio-base/Cargo.toml index a8723431..da3c56b9 100644 --- a/sapio-base/Cargo.toml +++ b/sapio-base/Cargo.toml @@ -19,10 +19,10 @@ serde_derive = "1.0" [dependencies.miniscript] package = "sapio-miniscript" -version = "^7.0.0" +version = "^7.0.1" features = ['compiler', 'use-serde', 'use-schemars', 'serde'] [dependencies.bitcoin] package = "sapio-bitcoin" -version = "0.28.0" +version = "0.28.2" features = ['use-serde'] diff --git a/sapio/Cargo.toml b/sapio/Cargo.toml index 1785c2a1..4a9ef872 100644 --- a/sapio/Cargo.toml +++ b/sapio/Cargo.toml @@ -13,7 +13,7 @@ description = "A programming framework for bitcoin smart contracts." [dependencies.miniscript] package = "sapio-miniscript" -version = "^7.0.0" +version = "^7.0.1" features = ['compiler', 'use-serde', 'use-schemars', 'serde'] [features] @@ -37,7 +37,7 @@ features = ['impl_json_schema', 'derive'] [dependencies.bitcoin] package = "sapio-bitcoin" -version = "0.28.0" +version = "0.28.2" features = ['use-serde'] diff --git a/sapio/src/contract/compiler/mod.rs b/sapio/src/contract/compiler/mod.rs index ee10fd6d..49d8ea95 100644 --- a/sapio/src/contract/compiler/mod.rs +++ b/sapio/src/contract/compiler/mod.rs @@ -72,7 +72,7 @@ impl Compilable for bitcoin::XOnlyPublicKey { } } -#[derive(PartialEq, Eq)] +#[derive(PartialEq, Eq, Debug)] enum Nullable { Yes, No, @@ -90,19 +90,20 @@ fn compute_all_effects( return Ok(def); } let mut applied_effects_ctx = top_effect_ctx.derive(PathFragment::Effects)?; - top_effect_ctx + let r = top_effect_ctx .get_effects(InternalCompilerTag { _secret: () }) .get_value(top_effect_ctx.path()) // always gets the default expansion, but will also attempt // operating with the effects passed in through the Context Object. - .fold(Ok(def), |a: TxTmplIt, (k, arg)| -> TxTmplIt { - let v = a?; + .try_fold(def, |a, (k, arg)| -> TxTmplIt { + let v = a; let c = applied_effects_ctx .derive(PathFragment::Named(SArc(k.clone()))) .expect(UNIQUE_DERIVE_PANIC_MSG); let w = func.call_json(self_ref, c, arg.clone())?; Ok(Box::new(v.chain(w))) - }) + }); + r } struct Renamer { @@ -252,6 +253,7 @@ where } .entry(h) .or_insert(txtmpl); + let extractor = func.get_extract_clause_from_txtmpl(); (extractor)(txtmpl, &ctx) }) @@ -262,11 +264,12 @@ where // N.B. the order of the matches below is significant Ok(if func.get_returned_txtmpls_modify_guards() { - ( + let r = ( None, combine_txtmpls(nullability, txtmpl_clauses, guards)?, guard_metadata, - ) + ); + r } else { let mut cp = ContinuationPoint::at(func.get_schema().clone(), effect_path.clone()); @@ -346,6 +349,9 @@ where Err(CompilationError::MinFeerateError) } else { let metadata_ctx = ctx.derive(PathFragment::Metadata)?; + let metadata = self + .metadata(metadata_ctx)? + .add_guard_simps(all_guard_simps)?; Ok(Compiled { ctv_to_tx: comitted_txns, suggested_txs: other_txns, @@ -354,9 +360,7 @@ where address, descriptor, amount_range, - metadata: self - .metadata(metadata_ctx)? - .add_guard_simps(all_guard_simps)?, + metadata, }) } } @@ -394,10 +398,13 @@ fn combine_txtmpls( // Error if 0 templates return and we don't want to be nullable (Nullable::No, 0, _) => Err(CompilationError::MissingTemplates), // If the guard is trivial, return the hashes standalone - (_, _, Clause::Trivial) => Ok(txtmpl_clauses - .into_iter() - .map(|policy| policy.compile().map_err(Into::::into)) - .collect::, _>>()?), + (_, _, Clause::Trivial) => { + let r = Ok(txtmpl_clauses + .into_iter() + .map(|policy| policy.compile().map_err(Into::::into)) + .collect::, _>>()?); + r + } // If the guard is non-trivial, zip it to each hash // TODO: Arc in miniscript to dedup memory? // This could be Clause::Shared(x) or something... diff --git a/sapio/src/template/builder.rs b/sapio/src/template/builder.rs index 1f84f5cd..3ea29f92 100644 --- a/sapio/src/template/builder.rs +++ b/sapio/src/template/builder.rs @@ -9,9 +9,10 @@ use super::input::InputMetadata; pub use super::{Output, OutputMeta}; use super::{Template, TemplateMetadata}; use crate::contract::{CompilationError, Context}; +use crate::util::extended_address::ExtendedAddress; use bitcoin::util::amount::Amount; -use bitcoin::VarInt; use bitcoin::Witness; +use bitcoin::{Script, VarInt}; use sapio_base::effects::PathFragment; use sapio_base::simp::SIMPAttachableAt; use sapio_base::simp::TemplateInputLT; @@ -20,7 +21,6 @@ use sapio_base::timelocks::*; use sapio_base::CTVHash; use sapio_base::Clause; use std::convert::TryFrom; -use std::convert::TryInto; /// Builder can be used to interactively put together a transaction template before /// finalizing into a Template. @@ -229,28 +229,36 @@ impl Builder { pub fn get_tx(&self) -> bitcoin::Transaction { let default_seq = RelTime::try_from(0).unwrap().into(); let default_nlt = AbsHeight::try_from(0).unwrap().into(); - bitcoin::Transaction { + let input = self + .sequences + .iter() + .map(|sequence| bitcoin::TxIn { + previous_output: Default::default(), + script_sig: Default::default(), + sequence: sequence.unwrap_or(default_seq).get(), + witness: Witness::new(), + }) + .collect(); + let output = self + .outputs + .iter() + .map(|out| { + let value = out.amount.as_sat(); + + let script_pubkey: Script = From::<&ExtendedAddress>::from(&out.contract.address); + bitcoin::TxOut { + value, + script_pubkey, + } + }) + .collect(); + let t = bitcoin::Transaction { version: self.version, lock_time: self.lock_time.unwrap_or(default_nlt).get(), - input: self - .sequences - .iter() - .map(|sequence| bitcoin::TxIn { - previous_output: Default::default(), - script_sig: Default::default(), - sequence: sequence.unwrap_or(default_seq).get(), - witness: Witness::new(), - }) - .collect(), - output: self - .outputs - .iter() - .map(|out| bitcoin::TxOut { - value: TryInto::::try_into(out.amount).unwrap().as_sat(), - script_pubkey: out.contract.address.clone().into(), - }) - .collect(), - } + input, + output, + }; + t } /// Sets the feerate if not set, and then sets the value to the min of the diff --git a/sapio/src/util/extended_address.rs b/sapio/src/util/extended_address.rs index 479561c1..ea69aa05 100644 --- a/sapio/src/util/extended_address.rs +++ b/sapio/src/util/extended_address.rs @@ -88,3 +88,17 @@ impl From for Script { } } } + +impl From<&ExtendedAddress> for Script { + fn from(s: &ExtendedAddress) -> Self { + match s { + ExtendedAddress::Address(a) => a.script_pubkey(), + ExtendedAddress::OpReturn(OpReturn(s)) => s.clone(), + ExtendedAddress::Unknown(s) => s.clone(), + ExtendedAddress::Descriptor(d) => { + let r = d.script_pubkey(); + r + } + } + } +} diff --git a/tools/Cargo.toml b/tools/Cargo.toml index c33c2639..b3e9ccbc 100644 --- a/tools/Cargo.toml +++ b/tools/Cargo.toml @@ -14,7 +14,7 @@ serde_json = "1.0" serde = "1.0" serde_derive = "1.0" tokio = { version = "1", features = ["full"] } -bitcoincore-rpc-async = "4.0.1-alpha.1" +bitcoincore-rpc-async = "4.0.1-alpha.2" [dependencies.miniscript] package = "sapio-miniscript"