From ac16e05aa9943152e4235b490fd4ad03a496a7c1 Mon Sep 17 00:00:00 2001 From: mcroad Date: Sun, 22 May 2022 16:11:22 -0500 Subject: [PATCH] Add no_std support --- .github/workflows/rust.yml | 36 +++++++++- Cargo.toml | 16 +++-- README.md | 5 +- contrib/test.sh | 18 +++++ embedded/Cargo.toml | 28 ++++++++ embedded/README.md | 22 ++++++ embedded/memory.x | 5 ++ embedded/scripts/env.sh | 2 + embedded/scripts/install-deps | 3 + embedded/src/main.rs | 82 +++++++++++++++++++++++ src/descriptor/bare.rs | 5 +- src/descriptor/checksum.rs | 5 +- src/descriptor/key.rs | 40 ++++++++--- src/descriptor/mod.rs | 15 ++--- src/descriptor/segwitv0.rs | 5 +- src/descriptor/sh.rs | 5 +- src/descriptor/sortedmulti.rs | 7 +- src/descriptor/tr.rs | 10 +-- src/expression.rs | 4 +- src/interpreter/error.rs | 6 +- src/interpreter/inner.rs | 3 +- src/interpreter/mod.rs | 6 +- src/interpreter/stack.rs | 1 + src/lib.rs | 100 +++++++++++++++++++++++++++- src/macros.rs | 26 ++++---- src/miniscript/analyzable.rs | 9 ++- src/miniscript/astelem.rs | 7 +- src/miniscript/context.rs | 6 +- src/miniscript/decode.rs | 10 ++- src/miniscript/iter.rs | 6 +- src/miniscript/lex.rs | 3 +- src/miniscript/mod.rs | 19 +++--- src/miniscript/ms_tests.rs | 2 +- src/miniscript/satisfy.rs | 6 +- src/miniscript/types/extra_props.rs | 11 +-- src/miniscript/types/mod.rs | 5 +- src/policy/compiler.rs | 20 +++--- src/policy/concrete.rs | 12 ++-- src/policy/mod.rs | 12 ++-- src/policy/semantic.rs | 7 +- src/psbt/finalizer.rs | 3 +- src/psbt/mod.rs | 14 ++-- src/util.rs | 1 + 43 files changed, 488 insertions(+), 120 deletions(-) create mode 100644 embedded/Cargo.toml create mode 100644 embedded/README.md create mode 100644 embedded/memory.x create mode 100644 embedded/scripts/env.sh create mode 100755 embedded/scripts/install-deps create mode 100644 embedded/src/main.rs diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 94f70af99..eb3b0fd3d 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout Crate uses: actions/checkout@v2 - name: Install hongfuzz dependancies - run: sudo apt install build-essential binutils-dev libunwind-dev libblocksruntime-dev liblzma-dev + run: sudo apt update && sudo apt install build-essential binutils-dev libunwind-dev libblocksruntime-dev liblzma-dev - name: Checkout Toolchain uses: actions-rs/toolchain@v1 with: @@ -24,6 +24,7 @@ jobs: - name: Running fuzzer env: DO_FUZZ: true + DO_NO_STD: true run: ./contrib/test.sh Nightly: @@ -41,6 +42,7 @@ jobs: - name: Running benchmarks env: DO_BENCH: true + DO_NO_STD: true run: ./contrib/test.sh - name: Building docs env: @@ -56,7 +58,13 @@ jobs: runs-on: ubuntu-latest strategy: matrix: - rust: [stable, beta, nightly, 1.41.1] + include: + - rust: stable + - rust: beta + - rust: nightly + - rust: 1.41.1 + - rust: 1.47 + DO_NO_STD: true steps: - name: Checkout Crate uses: actions/checkout@v2 @@ -69,4 +77,26 @@ jobs: - name: Running cargo env: DO_FEATURE_MATRIX: true - run: ./contrib/test.sh \ No newline at end of file + DO_NO_STD: ${{ matrix.DO_NO_STD }} + run: ./contrib/test.sh + + Embedded: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up QEMU + run: sudo apt update && sudo apt install -y qemu-system-arm gcc-arm-none-eabi + - name: Checkout Toolchain + uses: actions-rs/toolchain@v1 + with: + profile: minimal + toolchain: nightly + override: true + components: rust-src + target: thumbv7m-none-eabi + - name: Run + env: + RUSTFLAGS: "-C link-arg=-Tlink.x" + CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER: "qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -nographic -semihosting-config enable=on,target=native -kernel" + run: cd embedded && cargo run --target thumbv7m-none-eabi --release diff --git a/Cargo.toml b/Cargo.toml index d749c71c6..7e8c6f475 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -11,16 +11,19 @@ readme = "README.md" edition = "2018" [features] +default = ["std"] +std = ["bitcoin/std", "bitcoin/secp-recovery"] +no-std = ["hashbrown", "bitcoin/no-std"] compiler = [] trace = [] unstable = [] -default = [] use-serde = ["serde", "bitcoin/use-serde"] rand = ["bitcoin/rand"] [dependencies] -bitcoin = "0.28.0" -serde = { version = "1.0", optional = true} +bitcoin = { version = "0.28.1", default-features = false } +serde = { version = "1.0", optional = true } +hashbrown = { version = "0.11", optional = true } [dev-dependencies] bitcoind = {version = "0.26.1", features=["22_0"]} @@ -28,19 +31,24 @@ actual-rand = { package = "rand", version = "0.8.4"} [[example]] name = "htlc" -required-features = ["compiler"] +required-features = ["std", "compiler"] [[example]] name = "parse" +required-features = ["std"] [[example]] name = "sign_multisig" +required-features = ["std"] [[example]] name = "verify_tx" +required-features = ["std"] [[example]] name = "psbt" +required-features = ["std"] [[example]] name = "xpub_descriptors" +required-features = ["std"] diff --git a/README.md b/README.md index ba9e318b4..f7cd476d9 100644 --- a/README.md +++ b/README.md @@ -27,13 +27,16 @@ are convertible to `bitcoin::PublicKey` completing an unsigned `bitcoin::TxIn` with appropriate data * Determining the specific keys, hash preimages and timelocks used to spend coins in a given Bitcoin transaction +* `no_std` support enabled by disabling the `default-features` and enabling +`"no-std"`. See `embedded/` for an example. More information can be found in [the documentation](https://docs.rs/miniscript) or in [the `examples/` directory](https://github.com/apoelstra/rust-miniscript/tree/master/examples) ## Minimum Supported Rust Version (MSRV) -This library should always compile with any combination of features on **Rust 1.41.1**. +This library should always compile with any combination of features (minus +`no-std`) on **Rust 1.41.1** or **Rust 1.47** with `no-std`. ## Contributing Contributions are generally welcome. If you intend to make larger changes please diff --git a/contrib/test.sh b/contrib/test.sh index 34b4109b2..a6f9d2c53 100755 --- a/contrib/test.sh +++ b/contrib/test.sh @@ -55,6 +55,24 @@ then cargo run --example xpub_descriptors fi +if [ "$DO_NO_STD" = true ] +then + # Build no_std, to make sure that cfg(test) doesn't hide any issues + cargo build --verbose --no-default-features --features="no-std" + + # Test no_std + cargo test --verbose --no-default-features --features="no-std" + + # Build all features + cargo build --verbose --no-default-features --features="no-std $FEATURES" + + # Build specific features + for feature in ${FEATURES} + do + cargo build --verbose --no-default-features --features="no-std $feature" + done +fi + # Bench if told to (this only works with the nightly toolchain) if [ "$DO_BENCH" = true ] then diff --git a/embedded/Cargo.toml b/embedded/Cargo.toml new file mode 100644 index 000000000..53a8338d3 --- /dev/null +++ b/embedded/Cargo.toml @@ -0,0 +1,28 @@ +[package] +authors = [ + "Riccardo Casatta ", + "Dev Random ", +] +edition = "2018" +readme = "README.md" +name = "embedded" +version = "0.1.0" + +[dependencies] +cortex-m = "0.6.0" +cortex-m-rt = "0.6.10" +cortex-m-semihosting = "0.3.3" +panic-halt = "0.2.0" +alloc-cortex-m = "0.4.1" +miniscript = { path = "../", default-features = false, features = ["no-std"] } + +[[bin]] +name = "embedded" +test = false +bench = false + +[profile.release] +codegen-units = 1 # better optimizations +debug = true # symbols are nice and they don't increase the size on Flash +lto = true # better optimizations +opt-level = "z" \ No newline at end of file diff --git a/embedded/README.md b/embedded/README.md new file mode 100644 index 000000000..d223a39ff --- /dev/null +++ b/embedded/README.md @@ -0,0 +1,22 @@ +# Running + +To run the embedded test, first prepare your environment: + +```shell +sudo ./scripts/install-deps +rustup target add thumbv7m-none-eabi +``` + +Then: + +```shell +source ./scripts/env.sh && cargo run +nightly --target thumbv7m-none-eabi +``` + +Output should be something like: + +```text +heap size 1048576 +descriptor sh(wsh(or_d(c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)))) +p2sh address 3CJxbQBfWAe1ZkKiGQNEYrioV73ZwvBWns +``` diff --git a/embedded/memory.x b/embedded/memory.x new file mode 100644 index 000000000..d07ea1454 --- /dev/null +++ b/embedded/memory.x @@ -0,0 +1,5 @@ +MEMORY +{ + FLASH : ORIGIN = 0x00000000, LENGTH = 2048K + RAM : ORIGIN = 0x20000000, LENGTH = 512K +} \ No newline at end of file diff --git a/embedded/scripts/env.sh b/embedded/scripts/env.sh new file mode 100644 index 000000000..f1c93fd90 --- /dev/null +++ b/embedded/scripts/env.sh @@ -0,0 +1,2 @@ +export RUSTFLAGS="-C link-arg=-Tlink.x" +export CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER="qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -nographic -semihosting-config enable=on,target=native -kernel" \ No newline at end of file diff --git a/embedded/scripts/install-deps b/embedded/scripts/install-deps new file mode 100755 index 000000000..d4d70dce0 --- /dev/null +++ b/embedded/scripts/install-deps @@ -0,0 +1,3 @@ +#!/bin/sh + +apt install gcc-arm-none-eabi qemu-system-arm gdb-multiarch \ No newline at end of file diff --git a/embedded/src/main.rs b/embedded/src/main.rs new file mode 100644 index 000000000..df67759db --- /dev/null +++ b/embedded/src/main.rs @@ -0,0 +1,82 @@ +#![no_std] +#![no_main] +#![feature(alloc_error_handler)] +#![feature(panic_info_message)] + +extern crate alloc; + +use alloc::string::ToString; +use core::alloc::Layout; +use core::panic::PanicInfo; + +use alloc_cortex_m::CortexMHeap; + +use core::str::FromStr; + +use cortex_m::asm; +use cortex_m_rt::entry; +use cortex_m_semihosting::{debug, hprintln}; + +// this is the allocator the application will use +#[global_allocator] +static ALLOCATOR: CortexMHeap = CortexMHeap::empty(); + +const HEAP_SIZE: usize = 1024 * 256; // 256 KB + +#[entry] +fn main() -> ! { + hprintln!("heap size {}", HEAP_SIZE).unwrap(); + + unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) } + + // begin miniscript test + let descriptor = "sh(wsh(or_d(\ + c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),\ + c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)\ + )))"; + hprintln!("descriptor {}", descriptor).unwrap(); + let desc = + miniscript::Descriptor::::from_str(descriptor).unwrap(); + + // Derive the P2SH address + let p2sh_addr = desc + .address(miniscript::bitcoin::Network::Bitcoin) + .unwrap() + .to_string(); + hprintln!("p2sh address {}", p2sh_addr).unwrap(); + assert_eq!(p2sh_addr, "3CJxbQBfWAe1ZkKiGQNEYrioV73ZwvBWns"); + + // Check whether the descriptor is safe + // This checks whether all spend paths are accessible in bitcoin network. + // It maybe possible that some of the spend require more than 100 elements in Wsh scripts + // Or they contain a combination of timelock and heightlock. + assert!(desc.sanity_check().is_ok()); + + // Estimate the satisfaction cost + assert_eq!(desc.max_satisfaction_weight().unwrap(), 293); + // end miniscript test + + // exit QEMU + // NOTE do not run this on hardware; it can corrupt OpenOCD state + debug::exit(debug::EXIT_SUCCESS); + + loop {} +} + +// define what happens in an Out Of Memory (OOM) condition +#[alloc_error_handler] +fn alloc_error(_layout: Layout) -> ! { + hprintln!("alloc error").unwrap(); + debug::exit(debug::EXIT_FAILURE); + asm::bkpt(); + + loop {} +} + +#[inline(never)] +#[panic_handler] +fn panic(info: &PanicInfo) -> ! { + hprintln!("panic {:?}", info.message()).unwrap(); + debug::exit(debug::EXIT_FAILURE); + loop {} +} diff --git a/src/descriptor/bare.rs b/src/descriptor/bare.rs index 269317d9c..be5be5483 100644 --- a/src/descriptor/bare.rs +++ b/src/descriptor/bare.rs @@ -18,8 +18,8 @@ //! Also includes pk, and pkh descriptors //! -use std::fmt; -use std::str::FromStr; +use core::fmt; +use core::str::FromStr; use bitcoin::blockdata::script; use bitcoin::{Address, Network, Script}; @@ -28,6 +28,7 @@ use super::checksum::{desc_checksum, verify_checksum}; use crate::expression::{self, FromTree}; use crate::miniscript::context::ScriptContext; use crate::policy::{semantic, Liftable}; +use crate::prelude::*; use crate::util::{varint_len, witness_to_scriptsig}; use crate::{ BareCtx, Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, Satisfier, ToPublicKey, diff --git a/src/descriptor/checksum.rs b/src/descriptor/checksum.rs index 31a9ad966..8ecced007 100644 --- a/src/descriptor/checksum.rs +++ b/src/descriptor/checksum.rs @@ -3,8 +3,9 @@ //! This module contains a re-implementation of the function used by Bitcoin Core to calculate the //! checksum of a descriptor -use std::iter::FromIterator; +use core::iter::FromIterator; +use crate::prelude::*; use crate::Error; const INPUT_CHARSET: &str = "0123456789()[],'/*abcdefgh@:$%{}IJKLMNOPQRSTUVWXYZ&+-.;<=>?!^_|~ijklmnopqrstuvwxyzABCDEFGH`#\"\\ "; @@ -100,7 +101,7 @@ pub(super) fn verify_checksum(s: &str) -> Result<&str, Error> { } #[cfg(test)] mod test { - use std::str; + use core::str; use super::*; diff --git a/src/descriptor/key.rs b/src/descriptor/key.rs index 369fd411f..657100d6e 100644 --- a/src/descriptor/key.rs +++ b/src/descriptor/key.rs @@ -1,5 +1,7 @@ -use std::str::FromStr; -use std::{error, fmt}; +use core::fmt; +use core::str::FromStr; +#[cfg(feature = "std")] +use std::error; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, Hash, HashEngine}; @@ -7,6 +9,7 @@ use bitcoin::secp256k1::{Secp256k1, Signing, Verification}; use bitcoin::util::bip32; use bitcoin::{self, XOnlyPublicKey, XpubIdentifier}; +use crate::prelude::*; use crate::{MiniscriptKey, ToPublicKey}; /// The descriptor pubkey, either a single pubkey or an xpub. @@ -219,6 +222,7 @@ impl fmt::Display for DescriptorKeyParseError { } } +#[cfg(feature = "std")] impl error::Error for DescriptorKeyParseError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { None @@ -373,6 +377,7 @@ impl fmt::Display for ConversionError { } } +#[cfg(feature = "std")] impl error::Error for ConversionError { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { use self::ConversionError::*; @@ -651,21 +656,39 @@ impl DescriptorXKey { /// /// ``` /// # use std::str::FromStr; - /// # fn body() -> Result<(), Box> { + /// # fn body() -> Result<(), ()> { /// use miniscript::bitcoin::util::bip32; /// use miniscript::descriptor::DescriptorPublicKey; /// /// let ctx = miniscript::bitcoin::secp256k1::Secp256k1::signing_only(); /// - /// let key = DescriptorPublicKey::from_str("[d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*")?; + /// let key = DescriptorPublicKey::from_str("[d34db33f/44'/0'/0']xpub6ERApfZwUNrhLCkDtcHTcxd75RbzS1ed54G1LkBUHQVHQKqhMkhgbmJbZRkrgZw4koxb5JaHWkY4ALHY2grBGRjaDMzQLcgJvLJuZZvRcEL/1/*").or(Err(()))?; /// let xpub = match key { /// DescriptorPublicKey::XPub(xpub) => xpub, /// _ => panic!("Parsing Error"), /// }; /// - /// assert_eq!(xpub.matches(&(bip32::Fingerprint::from_str("d34db33f")?, bip32::DerivationPath::from_str("m/44'/0'/0'/1/42")?), &ctx), Some(bip32::DerivationPath::from_str("m/44'/0'/0'/1")?)); - /// assert_eq!(xpub.matches(&(bip32::Fingerprint::from_str("ffffffff")?, bip32::DerivationPath::from_str("m/44'/0'/0'/1/42")?), &ctx), None); - /// assert_eq!(xpub.matches(&(bip32::Fingerprint::from_str("d34db33f")?, bip32::DerivationPath::from_str("m/44'/0'/0'/100/0")?), &ctx), None); + /// assert_eq!( + /// xpub.matches(&( + /// bip32::Fingerprint::from_str("d34db33f").or(Err(()))?, + /// bip32::DerivationPath::from_str("m/44'/0'/0'/1/42").or(Err(()))? + /// ), &ctx), + /// Some(bip32::DerivationPath::from_str("m/44'/0'/0'/1").or(Err(()))?) + /// ); + /// assert_eq!( + /// xpub.matches(&( + /// bip32::Fingerprint::from_str("ffffffff").or(Err(()))?, + /// bip32::DerivationPath::from_str("m/44'/0'/0'/1/42").or(Err(()))? + /// ), &ctx), + /// None + /// ); + /// assert_eq!( + /// xpub.matches(&( + /// bip32::Fingerprint::from_str("d34db33f").or(Err(()))?, + /// bip32::DerivationPath::from_str("m/44'/0'/0'/100/0").or(Err(()))? + /// ), &ctx), + /// None + /// ); /// # Ok(()) /// # } /// # body().unwrap() @@ -806,11 +829,12 @@ impl ToPublicKey for DerivedDescriptorKey { #[cfg(test)] mod test { - use std::str::FromStr; + use core::str::FromStr; use bitcoin::secp256k1; use super::{DescriptorKeyParseError, DescriptorPublicKey, DescriptorSecretKey}; + use crate::prelude::*; #[test] fn parse_descriptor_key_errors() { diff --git a/src/descriptor/mod.rs b/src/descriptor/mod.rs index f6a8e2628..57bc91de2 100644 --- a/src/descriptor/mod.rs +++ b/src/descriptor/mod.rs @@ -23,18 +23,18 @@ //! these with BIP32 paths, pay-to-contract instructions, etc. //! -use std::collections::HashMap; -use std::fmt; -use std::ops::Range; -use std::str::{self, FromStr}; -use std::sync::Arc; +use core::fmt; +use core::ops::Range; +use core::str::{self, FromStr}; use bitcoin::blockdata::witness::Witness; use bitcoin::util::address::WitnessVersion; use bitcoin::{self, secp256k1, Address, Network, Script, TxIn}; +use sync::Arc; use self::checksum::verify_checksum; use crate::miniscript::{Legacy, Miniscript, Segwitv0}; +use crate::prelude::*; use crate::{ expression, miniscript, BareCtx, Error, ForEach, ForEachKey, MiniscriptKey, Satisfier, ToPublicKey, TranslatePk, TranslatePk2, @@ -724,9 +724,8 @@ serde_string_impl_pk!(Descriptor, "a script descriptor"); #[cfg(test)] mod tests { - use std::cmp; - use std::collections::HashMap; - use std::str::FromStr; + use core::cmp; + use core::str::FromStr; use bitcoin::blockdata::opcodes::all::{OP_CLTV, OP_CSV}; use bitcoin::blockdata::script::Instruction; diff --git a/src/descriptor/segwitv0.rs b/src/descriptor/segwitv0.rs index bc452e02c..8ec2e2348 100644 --- a/src/descriptor/segwitv0.rs +++ b/src/descriptor/segwitv0.rs @@ -16,8 +16,8 @@ //! Implementation of Segwit Descriptors. Contains the implementation //! of wsh, wpkh and sortedmulti inside wsh. -use std::fmt; -use std::str::FromStr; +use core::fmt; +use core::str::FromStr; use bitcoin::{self, Address, Network, Script}; @@ -26,6 +26,7 @@ use super::SortedMultiVec; use crate::expression::{self, FromTree}; use crate::miniscript::context::{ScriptContext, ScriptContextError}; use crate::policy::{semantic, Liftable}; +use crate::prelude::*; use crate::util::varint_len; use crate::{ Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, Satisfier, Segwitv0, ToPublicKey, diff --git a/src/descriptor/sh.rs b/src/descriptor/sh.rs index 1c628fde2..332328bea 100644 --- a/src/descriptor/sh.rs +++ b/src/descriptor/sh.rs @@ -18,8 +18,8 @@ //! sh(miniscript), and sh(wpkh) //! -use std::fmt; -use std::str::FromStr; +use core::fmt; +use core::str::FromStr; use bitcoin::blockdata::script; use bitcoin::{Address, Network, Script}; @@ -29,6 +29,7 @@ use super::{SortedMultiVec, Wpkh, Wsh}; use crate::expression::{self, FromTree}; use crate::miniscript::context::ScriptContext; use crate::policy::{semantic, Liftable}; +use crate::prelude::*; use crate::util::{varint_len, witness_to_scriptsig}; use crate::{ push_opcode_size, Error, ForEach, ForEachKey, Legacy, Miniscript, MiniscriptKey, Satisfier, diff --git a/src/descriptor/sortedmulti.rs b/src/descriptor/sortedmulti.rs index 6ac746042..e0a6c0910 100644 --- a/src/descriptor/sortedmulti.rs +++ b/src/descriptor/sortedmulti.rs @@ -16,15 +16,16 @@ //! Implementation of sorted multi primitive for descriptors //! -use std::fmt; -use std::marker::PhantomData; -use std::str::FromStr; +use core::fmt; +use core::marker::PhantomData; +use core::str::FromStr; use bitcoin::blockdata::script; use crate::miniscript::context::ScriptContext; use crate::miniscript::decode::Terminal; use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG; +use crate::prelude::*; use crate::{ errstr, expression, miniscript, policy, script_num_size, Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, Satisfier, ToPublicKey, diff --git a/src/descriptor/tr.rs b/src/descriptor/tr.rs index 9b063cff1..f0b40db5c 100644 --- a/src/descriptor/tr.rs +++ b/src/descriptor/tr.rs @@ -1,9 +1,7 @@ // Tapscript - -use std::cmp::{self, max}; -use std::str::FromStr; -use std::sync::{Arc, Mutex}; -use std::{fmt, hash}; +use core::cmp::{self, max}; +use core::str::FromStr; +use core::{fmt, hash}; use bitcoin::blockdata::opcodes; use bitcoin::util::taproot::{ @@ -11,12 +9,14 @@ use bitcoin::util::taproot::{ TAPROOT_CONTROL_MAX_NODE_COUNT, TAPROOT_CONTROL_NODE_SIZE, }; use bitcoin::{secp256k1, Address, Network, Script}; +use sync::Arc; use super::checksum::{desc_checksum, verify_checksum}; use crate::expression::{self, FromTree}; use crate::miniscript::Miniscript; use crate::policy::semantic::Policy; use crate::policy::Liftable; +use crate::prelude::*; use crate::util::{varint_len, witness_size}; use crate::{ errstr, Error, ForEach, ForEachKey, MiniscriptKey, Satisfier, Tap, ToPublicKey, TranslatePk, diff --git a/src/expression.rs b/src/expression.rs index edab011b7..bcecf2fe8 100644 --- a/src/expression.rs +++ b/src/expression.rs @@ -14,9 +14,9 @@ //! # Function-like Expression Language //! +use core::str::FromStr; -use std::str::FromStr; - +use crate::prelude::*; use crate::{errstr, Error, MAX_RECURSION_DEPTH}; #[derive(Debug)] diff --git a/src/interpreter/error.rs b/src/interpreter/error.rs index f4e840f9c..075b103aa 100644 --- a/src/interpreter/error.rs +++ b/src/interpreter/error.rs @@ -12,7 +12,9 @@ // If not, see . // -use std::{error, fmt}; +use core::fmt; +#[cfg(feature = "std")] +use std::error; use bitcoin::hashes::hash160; use bitcoin::hashes::hex::ToHex; @@ -20,6 +22,7 @@ use bitcoin::util::taproot; use bitcoin::{self, secp256k1}; use super::BitcoinKey; +use crate::prelude::*; /// Detailed Error type for Interpreter #[derive(Debug)] @@ -192,6 +195,7 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] impl error::Error for Error { fn cause(&self) -> Option<&dyn error::Error> { use self::Error::*; diff --git a/src/interpreter/inner.rs b/src/interpreter/inner.rs index eb0d5c050..e335107ec 100644 --- a/src/interpreter/inner.rs +++ b/src/interpreter/inner.rs @@ -19,6 +19,7 @@ use bitcoin::util::taproot::{ControlBlock, TAPROOT_ANNEX_PREFIX}; use super::{stack, BitcoinKey, Error, Stack, TypedHash160}; use crate::miniscript::context::{NoChecks, ScriptContext}; +use crate::prelude::*; use crate::{BareCtx, Legacy, Miniscript, MiniscriptKey, Segwitv0, Tap}; /// Attempts to parse a slice as a Bitcoin public key, checking compressedness @@ -397,7 +398,7 @@ impl ToNoChecks for Miniscript #[cfg(test)] mod tests { - use std::str::FromStr; + use core::str::FromStr; use bitcoin::blockdata::script; use bitcoin::hashes::hex::FromHex; diff --git a/src/interpreter/mod.rs b/src/interpreter/mod.rs index 20a9fc52b..0c96da5fe 100644 --- a/src/interpreter/mod.rs +++ b/src/interpreter/mod.rs @@ -19,9 +19,8 @@ //! assuming that the spent coin was descriptor controlled. //! -use std::borrow::Borrow; -use std::fmt; -use std::str::FromStr; +use core::fmt; +use core::str::FromStr; use bitcoin::blockdata::witness::Witness; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; @@ -30,6 +29,7 @@ use bitcoin::{self, secp256k1, TxOut}; use crate::miniscript::context::NoChecks; use crate::miniscript::ScriptContext; +use crate::prelude::*; use crate::{Descriptor, Miniscript, Terminal, ToPublicKey}; mod error; diff --git a/src/interpreter/stack.rs b/src/interpreter/stack.rs index a31d56e3f..c85cb21d0 100644 --- a/src/interpreter/stack.rs +++ b/src/interpreter/stack.rs @@ -22,6 +22,7 @@ use super::error::PkEvalErrInner; use super::{ verify_sersig, BitcoinKey, Error, HashLockType, KeySigPair, SatisfiedConstraint, TypedHash160, }; +use crate::prelude::*; /// Definition of Stack Element of the Stack used for interpretation of Miniscript. /// All stack elements with vec![] go to Dissatisfied and vec![1] are marked to Satisfied. diff --git a/src/lib.rs b/src/lib.rs index e2aa7973a..9354c8f48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -78,6 +78,7 @@ //! ``` //! +#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] #![cfg_attr(all(test, feature = "unstable"), feature(test))] // Coding conventions #![deny(unsafe_code)] @@ -90,6 +91,17 @@ #![deny(missing_docs)] pub use bitcoin; + +#[cfg(not(feature = "std"))] +#[macro_use] +extern crate alloc; + +#[cfg(not(feature = "std"))] +extern crate hashbrown; + +#[cfg(any(feature = "std", test))] +extern crate core; + #[cfg(feature = "serde")] pub use serde; #[cfg(all(test, feature = "unstable"))] @@ -108,8 +120,10 @@ pub mod timelock; mod util; -use std::str::FromStr; -use std::{error, fmt, hash, str}; +use core::str::FromStr; +use core::{fmt, hash, str}; +#[cfg(feature = "std")] +use std::error; use bitcoin::blockdata::{opcodes, script}; use bitcoin::hashes::{hash160, sha256, Hash}; @@ -120,6 +134,7 @@ pub use crate::miniscript::context::{BareCtx, Legacy, ScriptContext, Segwitv0, T pub use crate::miniscript::decode::Terminal; pub use crate::miniscript::satisfy::{Preimage32, Satisfier}; pub use crate::miniscript::Miniscript; +use crate::prelude::*; ///Public key trait which can be converted to Hash type pub trait MiniscriptKey: Clone + Eq + Ord + fmt::Debug + fmt::Display + hash::Hash { @@ -659,6 +674,7 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] impl error::Error for Error { fn cause(&self) -> Option<&dyn error::Error> { use self::Error::*; @@ -865,3 +881,83 @@ mod tests { assert_eq!(hash, pk) } } + +mod prelude { + // Mutex implementation from LDK + // https://github.com/lightningdevkit/rust-lightning/blob/9bdce47f0e0516e37c89c09f1975dfc06b5870b1/lightning-invoice/src/sync.rs + #[cfg(all(not(feature = "std"), not(test)))] + mod mutex { + use core::cell::{RefCell, RefMut}; + use core::ops::{Deref, DerefMut}; + + pub type LockResult = Result; + + /// `Mutex` is not a real mutex as it cannot be used in a multi-threaded + /// context. `Mutex` is a dummy implementation of [`std::sync::Mutex`] + /// for `no_std` environments. + pub struct Mutex { + inner: RefCell, + } + + #[must_use = "if unused the Mutex will immediately unlock"] + pub struct MutexGuard<'a, T: ?Sized + 'a> { + lock: RefMut<'a, T>, + } + + impl Deref for MutexGuard<'_, T> { + type Target = T; + + fn deref(&self) -> &T { + &self.lock.deref() + } + } + + impl DerefMut for MutexGuard<'_, T> { + fn deref_mut(&mut self) -> &mut T { + self.lock.deref_mut() + } + } + + impl Mutex { + pub fn new(inner: T) -> Mutex { + Mutex { + inner: RefCell::new(inner), + } + } + + pub fn lock<'a>(&'a self) -> LockResult> { + Ok(MutexGuard { + lock: self.inner.borrow_mut(), + }) + } + } + } + + #[cfg(all(not(feature = "std"), not(test)))] + pub use alloc::{ + borrow::{Borrow, Cow, ToOwned}, + boxed::Box, + collections::{vec_deque::VecDeque, BTreeMap, BinaryHeap}, + rc, slice, + string::{String, ToString}, + sync, + vec::Vec, + }; + #[cfg(any(feature = "std", test))] + pub use std::{ + borrow::{Borrow, Cow, ToOwned}, + boxed::Box, + collections::{vec_deque::VecDeque, BTreeMap, BinaryHeap, HashMap, HashSet}, + rc, slice, + string::{String, ToString}, + sync, + sync::Mutex, + vec::Vec, + }; + + #[cfg(all(not(feature = "std"), not(test)))] + pub use hashbrown::{HashMap, HashSet}; + + #[cfg(all(not(feature = "std"), not(test)))] + pub use self::mutex::Mutex; +} diff --git a/src/macros.rs b/src/macros.rs index 6ecea710b..b154919b3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -23,30 +23,30 @@ macro_rules! serde_string_impl_pk { #[cfg(feature = "serde")] impl<'de, Pk $(, $gen)*> $crate::serde::Deserialize<'de> for $name where - Pk: $crate::MiniscriptKey + std::str::FromStr, - Pk::Hash: std::str::FromStr, - ::Err: std::fmt::Display, - <::Hash as std::str::FromStr>::Err: - std::fmt::Display, + Pk: $crate::MiniscriptKey + core::str::FromStr, + Pk::Hash: core::str::FromStr, + ::Err: core::fmt::Display, + <::Hash as core::str::FromStr>::Err: + core::fmt::Display, $($gen : $gen_con,)* { fn deserialize(deserializer: D) -> Result<$name, D::Error> where D: $crate::serde::de::Deserializer<'de>, { - use std::fmt::{self, Formatter}; - use std::marker::PhantomData; - use std::str::FromStr; + use core::fmt::{self, Formatter}; + use core::marker::PhantomData; + use core::str::FromStr; #[allow(unused_parens)] struct Visitor(PhantomData<(Pk $(, $gen)*)>); impl<'de, Pk $(, $gen)*> $crate::serde::de::Visitor<'de> for Visitor where - Pk: $crate::MiniscriptKey + std::str::FromStr, - Pk::Hash: std::str::FromStr, - ::Err: std::fmt::Display, - <::Hash as std::str::FromStr>::Err: - std::fmt::Display, + Pk: $crate::MiniscriptKey + core::str::FromStr, + Pk::Hash: core::str::FromStr, + ::Err: core::fmt::Display, + <::Hash as core::str::FromStr>::Err: + core::fmt::Display, $($gen: $gen_con,)* { type Value = $name; diff --git a/src/miniscript/analyzable.rs b/src/miniscript/analyzable.rs index 158a1735c..7f2f2f11a 100644 --- a/src/miniscript/analyzable.rs +++ b/src/miniscript/analyzable.rs @@ -17,11 +17,13 @@ //! Tools for determining whether the guarantees offered by the library //! actually hold. -use std::collections::HashSet; -use std::fmt; +use core::fmt; +#[cfg(feature = "std")] +use std::error; use crate::miniscript::iter::PkPkh; -use crate::{error, Miniscript, MiniscriptKey, ScriptContext}; +use crate::prelude::*; +use crate::{Miniscript, MiniscriptKey, ScriptContext}; /// Possible reasons Miniscript guarantees can fail /// We currently mark Miniscript as Non-Analyzable if @@ -66,6 +68,7 @@ impl fmt::Display for AnalysisError { } } +#[cfg(feature = "std")] impl error::Error for AnalysisError { fn cause(&self) -> Option<&dyn error::Error> { use self::AnalysisError::*; diff --git a/src/miniscript/astelem.rs b/src/miniscript/astelem.rs index ea5c2d30c..e5cf13f74 100644 --- a/src/miniscript/astelem.rs +++ b/src/miniscript/astelem.rs @@ -19,17 +19,18 @@ //! encoding in Bitcoin script, as well as a datatype. Full details //! are given on the Miniscript website. -use std::str::FromStr; -use std::sync::Arc; -use std::{fmt, str}; +use core::str::FromStr; +use core::{fmt, str}; use bitcoin::blockdata::{opcodes, script}; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use sync::Arc; use crate::miniscript::context::SigType; use crate::miniscript::types::{self, Property}; use crate::miniscript::ScriptContext; +use crate::prelude::*; use crate::util::MsKeyBuilder; use crate::{ errstr, expression, script_num_size, Error, ForEach, ForEachKey, Miniscript, MiniscriptKey, diff --git a/src/miniscript/context.rs b/src/miniscript/context.rs index e3260d79b..8d0c451b8 100644 --- a/src/miniscript/context.rs +++ b/src/miniscript/context.rs @@ -12,7 +12,9 @@ // If not, see . // -use std::{error, fmt, hash}; +use core::{fmt, hash}; +#[cfg(feature = "std")] +use std::error; use bitcoin; use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT; @@ -24,6 +26,7 @@ use crate::miniscript::limits::{ MAX_STANDARD_P2WSH_STACK_ITEMS, }; use crate::miniscript::types; +use crate::prelude::*; use crate::util::witness_to_scriptsig; use crate::{Error, Miniscript, MiniscriptKey, Terminal}; @@ -75,6 +78,7 @@ pub enum ScriptContextError { MultiANotAllowed, } +#[cfg(feature = "std")] impl error::Error for ScriptContextError { fn cause(&self) -> Option<&dyn error::Error> { use self::ScriptContextError::*; diff --git a/src/miniscript/decode.rs b/src/miniscript/decode.rs index b137f535e..2e10139ae 100644 --- a/src/miniscript/decode.rs +++ b/src/miniscript/decode.rs @@ -17,18 +17,21 @@ //! Functionality to parse a Bitcoin Script into a `Miniscript` //! -use std::marker::PhantomData; -use std::sync::Arc; -use std::{error, fmt}; +use core::fmt; +use core::marker::PhantomData; +#[cfg(feature = "std")] +use std::error; use bitcoin::blockdata::constants::MAX_BLOCK_WEIGHT; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d, Hash}; +use sync::Arc; use crate::miniscript::lex::{Token as Tk, TokenIter}; use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG; use crate::miniscript::types::extra_props::ExtData; use crate::miniscript::types::{Property, Type}; use crate::miniscript::ScriptContext; +use crate::prelude::*; use crate::{bitcoin, Error, Miniscript, MiniscriptKey, ToPublicKey}; fn return_none(_: usize) -> Option { @@ -72,6 +75,7 @@ impl fmt::Display for KeyParseError { } } +#[cfg(feature = "std")] impl error::Error for KeyParseError { fn cause(&self) -> Option<&(dyn error::Error + 'static)> { match self { diff --git a/src/miniscript/iter.rs b/src/miniscript/iter.rs index f8d1ad0eb..5207c0ce7 100644 --- a/src/miniscript/iter.rs +++ b/src/miniscript/iter.rs @@ -16,11 +16,13 @@ //! //! Iterators for Miniscript with special functions for iterating //! over Public Keys, Public Key Hashes or both. -use std::ops::Deref; -use std::sync::Arc; +use core::ops::Deref; + +use sync::Arc; use super::decode::Terminal; use super::{Miniscript, MiniscriptKey, ScriptContext}; +use crate::prelude::*; /// Iterator-related extensions for [Miniscript] impl Miniscript { diff --git a/src/miniscript/lex.rs b/src/miniscript/lex.rs index 00e2b7650..a113824d3 100644 --- a/src/miniscript/lex.rs +++ b/src/miniscript/lex.rs @@ -17,11 +17,12 @@ //! Translates a script into a reversed sequence of tokens //! -use std::fmt; +use core::fmt; use bitcoin::blockdata::{opcodes, script}; use super::Error; +use crate::prelude::*; /// Atom of a tokenized version of a script #[derive(Debug, Copy, Clone, PartialEq, Eq)] diff --git a/src/miniscript/mod.rs b/src/miniscript/mod.rs index 559f0e286..66d0b1f86 100644 --- a/src/miniscript/mod.rs +++ b/src/miniscript/mod.rs @@ -24,13 +24,14 @@ //! components of the AST. //! -use std::marker::PhantomData; -use std::{fmt, hash, str}; +use core::marker::PhantomData; +use core::{fmt, hash, str}; use bitcoin::blockdata::script; use bitcoin::util::taproot::{LeafVersion, TapLeafHash}; pub use self::context::{BareCtx, Legacy, Segwitv0, Tap}; +use crate::prelude::*; pub mod analyzable; pub mod astelem; @@ -42,8 +43,9 @@ pub mod limits; pub mod satisfy; pub mod types; -use std::cmp; -use std::sync::Arc; +use core::cmp; + +use sync::Arc; use self::lex::{lex, TokenIter}; use self::types::Property; @@ -474,20 +476,21 @@ serde_string_impl_pk!(Miniscript, "a miniscript", Ctx; ScriptContext); #[cfg(test)] mod tests { - use std::marker::PhantomData; - use std::str; - use std::str::FromStr; - use std::sync::Arc; + use core::marker::PhantomData; + use core::str; + use core::str::FromStr; use bitcoin::hashes::{hash160, sha256, Hash}; use bitcoin::secp256k1::XOnlyPublicKey; use bitcoin::util::taproot::TapLeafHash; use bitcoin::{self, secp256k1}; + use sync::Arc; use super::{Miniscript, ScriptContext, Segwitv0, Tap}; use crate::miniscript::types::{self, ExtData, Property, Type}; use crate::miniscript::Terminal; use crate::policy::Liftable; + use crate::prelude::*; use crate::{ hex_script, DummyKey, DummyKeyHash, MiniscriptKey, Satisfier, ToPublicKey, TranslatePk, TranslatePk1, TranslatePk2, diff --git a/src/miniscript/ms_tests.rs b/src/miniscript/ms_tests.rs index ac456aaf4..2b44e2025 100644 --- a/src/miniscript/ms_tests.rs +++ b/src/miniscript/ms_tests.rs @@ -18,7 +18,7 @@ //! #[cfg(test)] mod tests { - use std::fmt; + use core::fmt; use crate::miniscript::types; use crate::{Miniscript, Segwitv0}; diff --git a/src/miniscript/satisfy.rs b/src/miniscript/satisfy.rs index deb547ea1..6f74ab61a 100644 --- a/src/miniscript/satisfy.rs +++ b/src/miniscript/satisfy.rs @@ -18,18 +18,18 @@ //! scriptpubkeys. //! -use std::collections::{BTreeMap, HashMap}; -use std::sync::Arc; -use std::{cmp, i64, mem}; +use core::{cmp, i64, mem}; use bitcoin; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; use bitcoin::secp256k1::XOnlyPublicKey; use bitcoin::util::taproot::{ControlBlock, LeafVersion, TapLeafHash}; +use sync::Arc; use crate::miniscript::limits::{ LOCKTIME_THRESHOLD, SEQUENCE_LOCKTIME_DISABLE_FLAG, SEQUENCE_LOCKTIME_TYPE_FLAG, }; +use crate::prelude::*; use crate::util::witness_size; use crate::{Miniscript, MiniscriptKey, ScriptContext, Terminal, ToPublicKey}; diff --git a/src/miniscript/types/extra_props.rs b/src/miniscript/types/extra_props.rs index b6f396a7c..3ef667e89 100644 --- a/src/miniscript/types/extra_props.rs +++ b/src/miniscript/types/extra_props.rs @@ -1,14 +1,15 @@ //! Other miscellaneous type properties which are not related to //! correctness or malleability. -use std::cmp; -use std::iter::once; +use core::cmp; +use core::iter::once; use super::{Error, ErrorKind, Property, ScriptContext}; use crate::miniscript::context::SigType; use crate::miniscript::limits::{ LOCKTIME_THRESHOLD, SEQUENCE_LOCKTIME_DISABLE_FLAG, SEQUENCE_LOCKTIME_TYPE_FLAG, }; +use crate::prelude::*; use crate::{script_num_size, MiniscriptKey, Terminal}; /// Timelock information for satisfaction of a fragment. @@ -1035,7 +1036,7 @@ impl Property for ExtData { fn sat_minus_dissat<'r, 's>( a: &'r (Option, usize), b: &'s (Option, usize), -) -> std::cmp::Ordering { +) -> cmp::Ordering { a.0.map(|x| x as isize - a.1 as isize) .cmp(&b.0.map(|x| x as isize - b.1 as isize)) } @@ -1049,7 +1050,7 @@ fn sat_minus_dissat<'r, 's>( fn sat_minus_option_dissat<'r, 's>( a: &'r (Option, Option), b: &'s (Option, Option), -) -> std::cmp::Ordering { +) -> cmp::Ordering { a.0.map(|x| a.1.map(|y| x as isize - y as isize)) .cmp(&b.0.map(|x| b.1.map(|y| x as isize - y as isize))) } @@ -1061,7 +1062,7 @@ fn sat_minus_option_dissat<'r, 's>( fn sat_minus_dissat_witness<'r, 's>( a: &'r (Option<(usize, usize)>, Option<(usize, usize)>), b: &'s (Option<(usize, usize)>, Option<(usize, usize)>), -) -> std::cmp::Ordering { +) -> cmp::Ordering { a.0.map(|x| a.1.map(|y| x.0 as isize - y.0 as isize)) .cmp(&b.0.map(|x| b.1.map(|y| x.0 as isize - y.0 as isize))) } diff --git a/src/miniscript/types/mod.rs b/src/miniscript/types/mod.rs index 728a4abcc..90fb5fca5 100644 --- a/src/miniscript/types/mod.rs +++ b/src/miniscript/types/mod.rs @@ -20,7 +20,9 @@ pub mod correctness; pub mod extra_props; pub mod malleability; -use std::{error, fmt}; +use core::fmt; +#[cfg(feature = "std")] +use std::error; pub use self::correctness::{Base, Correctness, Input}; pub use self::extra_props::ExtData; @@ -213,6 +215,7 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] impl error::Error for Error { fn cause(&self) -> Option<&dyn error::Error> { None diff --git a/src/policy/compiler.rs b/src/policy/compiler.rs index 0b2253e4c..90eec0e38 100644 --- a/src/policy/compiler.rs +++ b/src/policy/compiler.rs @@ -17,18 +17,20 @@ //! Optimizing compiler from concrete policies to Miniscript //! -use std::collections::vec_deque::VecDeque; -use std::collections::BTreeMap; -use std::convert::From; -use std::marker::PhantomData; -use std::sync::Arc; -use std::{cmp, error, f64, fmt, hash, mem}; +use core::convert::From; +use core::marker::PhantomData; +use core::{cmp, f64, fmt, hash, mem}; +#[cfg(feature = "std")] +use std::error; + +use sync::Arc; use crate::miniscript::context::SigType; use crate::miniscript::limits::MAX_PUBKEYS_PER_MULTISIG; use crate::miniscript::types::{self, ErrorKind, ExtData, Property, Type}; use crate::miniscript::ScriptContext; use crate::policy::Concrete; +use crate::prelude::*; use crate::{policy, Miniscript, MiniscriptKey, Terminal}; type PolicyCache = @@ -79,6 +81,7 @@ impl fmt::Display for CompilerError { } } +#[cfg(feature = "std")] impl error::Error for CompilerError { fn cause(&self) -> Option<&dyn error::Error> { use self::CompilerError::*; @@ -1185,9 +1188,7 @@ where #[cfg(test)] mod tests { - use std::collections::HashMap; - use std::str::FromStr; - use std::string::String; + use core::str::FromStr; use bitcoin::blockdata::{opcodes, script}; use bitcoin::{self, hashes, secp256k1}; @@ -1604,6 +1605,7 @@ mod benches { use super::{CompilerError, Concrete}; use crate::miniscript::Tap; + use crate::prelude::*; use crate::Miniscript; type TapMsRes = Result, CompilerError>; #[bench] diff --git a/src/policy/concrete.rs b/src/policy/concrete.rs index 542013219..f449b436b 100644 --- a/src/policy/concrete.rs +++ b/src/policy/concrete.rs @@ -15,8 +15,9 @@ //! Concrete Policies //! -use std::collections::HashSet; -use std::{error, fmt, str}; +use core::{fmt, str}; +#[cfg(feature = "std")] +use std::error; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; @@ -30,15 +31,15 @@ use { crate::Descriptor, crate::Miniscript, crate::Tap, - std::cmp::Reverse, - std::collections::{BinaryHeap, HashMap}, - std::sync::Arc, + core::cmp::Reverse, + sync::Arc, }; use super::ENTAILMENT_MAX_TERMINALS; use crate::expression::{self, FromTree}; use crate::miniscript::limits::{LOCKTIME_THRESHOLD, SEQUENCE_LOCKTIME_TYPE_FLAG}; use crate::miniscript::types::extra_props::TimelockInfo; +use crate::prelude::*; use crate::{errstr, Error, ForEach, ForEachKey, MiniscriptKey}; /// Concrete policy which corresponds directly to a Miniscript structure, @@ -132,6 +133,7 @@ impl fmt::Display for PolicyError { } } +#[cfg(feature = "std")] impl error::Error for PolicyError { fn cause(&self) -> Option<&dyn error::Error> { use self::PolicyError::*; diff --git a/src/policy/mod.rs b/src/policy/mod.rs index 10b1ee0ea..10ee3af61 100644 --- a/src/policy/mod.rs +++ b/src/policy/mod.rs @@ -21,7 +21,9 @@ //! The format represents EC public keys abstractly to allow wallets to replace //! these with BIP32 paths, pay-to-contract instructions, etc. //! -use crate::{error, fmt}; +use core::fmt; +#[cfg(feature = "std")] +use std::error; #[cfg(feature = "compiler")] pub mod compiler; @@ -79,6 +81,7 @@ impl fmt::Display for LiftError { } } +#[cfg(feature = "std")] impl error::Error for LiftError { fn cause(&self) -> Option<&dyn error::Error> { use self::LiftError::*; @@ -225,15 +228,16 @@ impl Liftable for Concrete { #[cfg(test)] mod tests { - use std::str::FromStr; - #[cfg(feature = "compiler")] - use std::sync::Arc; + use core::str::FromStr; use bitcoin; + #[cfg(feature = "compiler")] + use sync::Arc; use super::super::miniscript::context::Segwitv0; use super::super::miniscript::Miniscript; use super::{Concrete, Liftable, Semantic}; + use crate::prelude::*; use crate::DummyKey; #[cfg(feature = "compiler")] use crate::{descriptor::TapTree, Descriptor, Tap}; diff --git a/src/policy/semantic.rs b/src/policy/semantic.rs index 122d2b26e..83d60b172 100644 --- a/src/policy/semantic.rs +++ b/src/policy/semantic.rs @@ -14,14 +14,15 @@ //! Abstract Policies -use std::str::FromStr; -use std::{fmt, str}; +use core::str::FromStr; +use core::{fmt, str}; use bitcoin::hashes::hex::FromHex; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; use super::concrete::PolicyError; use super::ENTAILMENT_MAX_TERMINALS; +use crate::prelude::*; use crate::{errstr, expression, timelock, Error, ForEach, ForEachKey, MiniscriptKey}; /// Abstract policy which corresponds to the semantics of a Miniscript @@ -623,7 +624,7 @@ impl Policy { #[cfg(test)] mod tests { - use std::str::FromStr; + use core::str::FromStr; use bitcoin::PublicKey; diff --git a/src/psbt/finalizer.rs b/src/psbt/finalizer.rs index bb5de4455..4804bc581 100644 --- a/src/psbt/finalizer.rs +++ b/src/psbt/finalizer.rs @@ -19,8 +19,6 @@ //! `https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki` //! -use std::borrow::Borrow; - use bitcoin::blockdata::witness::Witness; use bitcoin::secp256k1::{self, Secp256k1}; use bitcoin::util::key::XOnlyPublicKey; @@ -29,6 +27,7 @@ use bitcoin::util::taproot::LeafVersion; use bitcoin::{self, PublicKey, Script, TxOut}; use super::{sanity_check, Error, InputError, Psbt, PsbtInputSatisfier}; +use crate::prelude::*; use crate::util::witness_size; use crate::{interpreter, BareCtx, Descriptor, Legacy, Miniscript, Satisfier, Segwitv0, Tap}; diff --git a/src/psbt/mod.rs b/src/psbt/mod.rs index 7d129148f..0a78ef6e2 100644 --- a/src/psbt/mod.rs +++ b/src/psbt/mod.rs @@ -19,9 +19,10 @@ //! `https://github.com/bitcoin/bips/blob/master/bip-0174.mediawiki` //! -use std::collections::BTreeMap; -use std::ops::Deref; -use std::{error, fmt}; +use core::fmt; +use core::ops::Deref; +#[cfg(feature = "std")] +use std::error; use bitcoin::hashes::{hash160, ripemd160, sha256, sha256d}; use bitcoin::secp256k1::{self, Secp256k1}; @@ -33,6 +34,7 @@ use bitcoin::{self, EcdsaSighashType, SchnorrSighashType, Script}; use crate::miniscript::iter::PkPkh; use crate::miniscript::limits::SEQUENCE_LOCKTIME_DISABLE_FLAG; use crate::miniscript::satisfy::{After, Older}; +use crate::prelude::*; use crate::{ descriptor, interpreter, Descriptor, DescriptorPublicKey, MiniscriptKey, Preimage32, Satisfier, ToPublicKey, TranslatePk, TranslatePk2, @@ -82,6 +84,7 @@ impl fmt::Display for Error { } } +#[cfg(feature = "std")] impl error::Error for Error { fn cause(&self) -> Option<&dyn error::Error> { use self::Error::*; @@ -157,6 +160,7 @@ pub enum InputError { }, } +#[cfg(feature = "std")] impl error::Error for InputError { fn cause(&self) -> Option<&dyn error::Error> { use self::InputError::*; @@ -936,7 +940,7 @@ fn update_input_with_descriptor_helper( // One needs the derived descriptor and the other needs to know whether the script_pubkey check // failed. ) -> Result<(Descriptor, bool), descriptor::ConversionError> { - use std::cell::RefCell; + use core::cell::RefCell; let secp = secp256k1::Secp256k1::verification_only(); let derived = if let Descriptor::Tr(_) = &descriptor { @@ -1104,6 +1108,7 @@ impl fmt::Display for UtxoUpdateError { } } +#[cfg(feature = "std")] impl error::Error for UtxoUpdateError { fn cause(&self) -> Option<&dyn error::Error> { use self::UtxoUpdateError::*; @@ -1154,6 +1159,7 @@ impl fmt::Display for SighashError { } } +#[cfg(feature = "std")] impl error::Error for SighashError { fn cause(&self) -> Option<&dyn error::Error> { use self::SighashError::*; diff --git a/src/util.rs b/src/util.rs index bc6977e0c..3189455fc 100644 --- a/src/util.rs +++ b/src/util.rs @@ -2,6 +2,7 @@ use bitcoin::blockdata::script; use bitcoin::Script; use crate::miniscript::context; +use crate::prelude::*; use crate::{ScriptContext, ToPublicKey}; pub(crate) fn varint_len(n: usize) -> usize { bitcoin::VarInt(n as u64).len()