Skip to content

Commit da43e40

Browse files
committed
Add no_std support
1 parent 709d641 commit da43e40

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+428
-103
lines changed

.github/workflows/rust.yml

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
- name: Checkout Crate
1515
uses: actions/checkout@v2
1616
- name: Install hongfuzz dependancies
17-
run: sudo apt install build-essential binutils-dev libunwind-dev libblocksruntime-dev liblzma-dev
17+
run: sudo apt update && sudo apt install build-essential binutils-dev libunwind-dev libblocksruntime-dev liblzma-dev
1818
- name: Checkout Toolchain
1919
uses: actions-rs/toolchain@v1
2020
with:
@@ -25,6 +25,7 @@ jobs:
2525
env:
2626
DO_FUZZ: true
2727
DO_LINT: true
28+
DO_NO_STD: true
2829
run: ./contrib/test.sh
2930

3031
bench_nightly:
@@ -46,16 +47,21 @@ jobs:
4647
- name: Running cargo test
4748
env:
4849
DO_BENCH: true
50+
DO_NO_STD: true
4951
run: ./contrib/test.sh
5052

5153
UnitTests:
5254
name: Tests
5355
runs-on: ubuntu-latest
5456
strategy:
57+
fail-fast: false
5558
matrix:
56-
rust:
57-
- 1.29.0
58-
- beta
59+
include:
60+
- rust: 1.29.0
61+
- rust: beta
62+
- rust: 1.47
63+
env:
64+
DO_NO_STD: true
5965
steps:
6066
- name: Checkout Crate
6167
uses: actions/checkout@v2
@@ -73,6 +79,7 @@ jobs:
7379
cargo update --verbose --package "serde" --precise "1.0.98" && \
7480
cargo update --verbose --package "serde_derive" --precise "1.0.98"
7581
- name: Running cargo
82+
env: ${{ matrix.env }}
7683
run: ./contrib/test.sh
7784

7885
AllTests:
@@ -95,3 +102,24 @@ jobs:
95102
env:
96103
BITCOINVERSION: '22.0'
97104
run: ./contrib/test.sh
105+
106+
Embedded:
107+
runs-on: ubuntu-latest
108+
steps:
109+
- name: Checkout
110+
uses: actions/checkout@v2
111+
- name: Set up QEMU
112+
run: sudo apt update && sudo apt install qemu-system-arm gcc-arm-none-eabi
113+
- name: Checkout Toolchain
114+
uses: actions-rs/toolchain@v1
115+
with:
116+
profile: minimal
117+
toolchain: nightly
118+
override: true
119+
components: rust-src
120+
target: thumbv7m-none-eabi
121+
- name: Run
122+
env:
123+
RUSTFLAGS: "-C link-arg=-Tlink.x"
124+
CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER: "qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -m 1G -nographic -semihosting-config enable=on,target=native -kernel"
125+
run: cd embedded && cargo run --target thumbv7m-none-eabi

Cargo.toml

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,32 +10,42 @@ keywords = [ "crypto", "bitcoin"]
1010
readme = "README.md"
1111

1212
[features]
13+
default = ["std"]
14+
# rust-bitcoin default features
15+
# necessary because bitcoin/secp-recovery is a default feature
16+
std = ["bitcoin/std", "bitcoin/secp-recovery"]
17+
no-std = ["hashbrown", "bitcoin/no-std", "secp256k1/alloc"]
1318
compiler = []
1419
trace = []
1520
unstable = []
16-
default = []
17-
use-serde = ["serde", "bitcoin/use-serde"]
21+
use-serde = ["bitcoin/use-serde", "serde"]
1822
rand = ["bitcoin/rand"]
1923

2024
[dependencies]
2125
bitcoin = "0.28.0"
2226
serde = { version = "1.0", optional = true}
27+
hashbrown = { version = "0.11", optional = true }
2328

2429
[[example]]
2530
name = "htlc"
26-
required-features = ["compiler"]
31+
required-features = ["std", "compiler"]
2732

2833
[[example]]
2934
name = "parse"
35+
required-features = ["std"]
3036

3137
[[example]]
3238
name = "sign_multisig"
39+
required-features = ["std"]
3340

3441
[[example]]
3542
name = "verify_tx"
43+
required-features = ["std"]
3644

3745
[[example]]
3846
name = "psbt"
47+
required-features = ["std"]
3948

4049
[[example]]
4150
name = "xpub_descriptors"
51+
required-features = ["std"]

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,8 @@ are convertible to `bitcoin::PublicKey`
3030
completing an unsigned `bitcoin::TxIn` with appropriate data
3131
* Determining the specific keys, hash preimages and timelocks used to spend
3232
coins in a given Bitcoin transaction
33+
* `no_std` support enabled by disabling the `default-features` and enabling
34+
`"no-std"`. See `embedded/` for an example.
3335

3436
More information can be found in [the documentation](https://docs.rs/miniscript)
3537
or in [the `examples/` directory](https://github.com/apoelstra/rust-miniscript/tree/master/examples)

contrib/test.sh

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#!/bin/sh -ex
22

3-
FEATURES="compiler use-serde rand"
3+
FEATURES="compiler rand use-serde"
44

55
# Use toolchain if explicitly specified
66
if [ -n "$TOOLCHAIN" ]
@@ -30,9 +30,27 @@ then
3030
)
3131
fi
3232

33-
# Test without any features first
33+
# Then test with the default features
3434
cargo test --verbose
3535

36+
if [ "$DO_NO_STD" = true ]
37+
then
38+
# Build no_std, to make sure that cfg(test) doesn't hide any issues
39+
cargo build --verbose --no-default-features --features="no-std"
40+
41+
# Test no_std
42+
cargo test --verbose --no-default-features --features="no-std"
43+
44+
# Build all features
45+
cargo build --verbose --no-default-features --features="no-std $FEATURES"
46+
47+
# Build specific features
48+
for feature in ${FEATURES}
49+
do
50+
cargo build --verbose --no-default-features --features="no-std $feature"
51+
done
52+
fi
53+
3654
# Test each feature
3755
for feature in ${FEATURES}
3856
do

embedded/Cargo.toml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
[package]
2+
authors = [
3+
"Riccardo Casatta <[email protected]>",
4+
"Dev Random <[email protected]>",
5+
]
6+
edition = "2018"
7+
readme = "README.md"
8+
name = "embedded"
9+
version = "0.1.0"
10+
11+
[dependencies]
12+
cortex-m = "0.6.0"
13+
cortex-m-rt = "0.6.10"
14+
cortex-m-semihosting = "0.3.3"
15+
panic-halt = "0.2.0"
16+
alloc-cortex-m = "0.4.1"
17+
miniscript = { path = "../", default-features = false, features = ["no-std"] }
18+
19+
[[bin]]
20+
name = "embedded"
21+
test = false
22+
bench = false
23+
24+
[profile.release]
25+
codegen-units = 1 # better optimizations
26+
debug = true # symbols are nice and they don't increase the size on Flash
27+
lto = true # better optimizations

embedded/README.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# Running
2+
3+
To run the embedded test, first prepare your environment:
4+
5+
```shell
6+
sudo ./scripts/install-deps
7+
rustup target add thumbv7m-none-eabi
8+
```
9+
10+
Then:
11+
12+
```shell
13+
source ./scripts/env.sh && cargo run +nightly --target thumbv7m-none-eabi
14+
```
15+
16+
Output should be something like:
17+
18+
```text
19+
heap size 1048576
20+
descriptor sh(wsh(or_d(c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352))))
21+
p2sh address 3CJxbQBfWAe1ZkKiGQNEYrioV73ZwvBWns
22+
```

embedded/memory.x

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
MEMORY
2+
{
3+
FLASH : ORIGIN = 0x00000000, LENGTH = 1024K
4+
RAM : ORIGIN = 0x20000000, LENGTH = 512K
5+
}

embedded/scripts/env.sh

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export RUSTFLAGS="-C link-arg=-Tlink.x"
2+
export CARGO_TARGET_THUMBV7M_NONE_EABI_RUNNER="qemu-system-arm -cpu cortex-m3 -machine mps2-an385 -m 1G -nographic -semihosting-config enable=on,target=native -kernel"

embedded/scripts/install-deps

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#!/bin/sh
2+
3+
apt install gcc-arm-none-eabi qemu-system-arm gdb-multiarch

embedded/src/main.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#![no_std]
2+
#![no_main]
3+
#![feature(alloc_error_handler)]
4+
#![feature(panic_info_message)]
5+
6+
extern crate alloc;
7+
8+
use alloc::string::ToString;
9+
use core::alloc::Layout;
10+
use core::panic::PanicInfo;
11+
12+
use alloc_cortex_m::CortexMHeap;
13+
14+
use core::str::FromStr;
15+
use miniscript::DescriptorTrait;
16+
17+
use cortex_m::asm;
18+
use cortex_m_rt::entry;
19+
use cortex_m_semihosting::{debug, hprintln};
20+
21+
// this is the allocator the application will use
22+
#[global_allocator]
23+
static ALLOCATOR: CortexMHeap = CortexMHeap::empty();
24+
25+
const HEAP_SIZE: usize = 1024 * 1024; // 1024 KB
26+
27+
#[entry]
28+
fn main() -> ! {
29+
hprintln!("heap size {}", HEAP_SIZE).unwrap();
30+
31+
unsafe { ALLOCATOR.init(cortex_m_rt::heap_start() as usize, HEAP_SIZE) }
32+
33+
// begin miniscript test
34+
let descriptor = "sh(wsh(or_d(\
35+
c:pk_k(020e0338c96a8870479f2396c373cc7696ba124e8635d41b0ea581112b67817261),\
36+
c:pk_k(0250863ad64a87ae8a2fe83c1af1a8403cb53f53e486d8511dad8a04887e5b2352)\
37+
)))";
38+
hprintln!("descriptor {}", descriptor).unwrap();
39+
let desc =
40+
miniscript::Descriptor::<miniscript::bitcoin::PublicKey>::from_str(descriptor).unwrap();
41+
42+
// Derive the P2SH address
43+
let p2sh_addr = desc
44+
.address(miniscript::bitcoin::Network::Bitcoin)
45+
.unwrap()
46+
.to_string();
47+
hprintln!("p2sh address {}", p2sh_addr).unwrap();
48+
assert_eq!(p2sh_addr, "3CJxbQBfWAe1ZkKiGQNEYrioV73ZwvBWns");
49+
50+
// Check whether the descriptor is safe
51+
// This checks whether all spend paths are accessible in bitcoin network.
52+
// It maybe possible that some of the spend require more than 100 elements in Wsh scripts
53+
// Or they contain a combination of timelock and heightlock.
54+
assert!(desc.sanity_check().is_ok());
55+
56+
// Estimate the satisfaction cost
57+
assert_eq!(desc.max_satisfaction_weight().unwrap(), 293);
58+
// end miniscript test
59+
60+
// exit QEMU
61+
// NOTE do not run this on hardware; it can corrupt OpenOCD state
62+
debug::exit(debug::EXIT_SUCCESS);
63+
64+
loop {}
65+
}
66+
67+
// define what happens in an Out Of Memory (OOM) condition
68+
#[alloc_error_handler]
69+
fn alloc_error(_layout: Layout) -> ! {
70+
hprintln!("alloc error").unwrap();
71+
debug::exit(debug::EXIT_FAILURE);
72+
asm::bkpt();
73+
74+
loop {}
75+
}
76+
77+
#[inline(never)]
78+
#[panic_handler]
79+
fn panic(info: &PanicInfo) -> ! {
80+
hprintln!("panic {:?}", info.message()).unwrap();
81+
debug::exit(debug::EXIT_FAILURE);
82+
loop {}
83+
}

src/descriptor/bare.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@
1818
//! Also includes pk, and pkh descriptors
1919
//!
2020
21-
use std::{fmt, str::FromStr};
21+
use core::{fmt, str::FromStr};
22+
use prelude::*;
2223

2324
use bitcoin::{self, blockdata::script, Script};
2425

src/descriptor/checksum.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
//! This module contains a re-implementation of the function used by Bitcoin Core to calculate the
44
//! checksum of a descriptor
55
6-
use std::iter::FromIterator;
6+
use core::iter::FromIterator;
7+
use prelude::*;
78

89
use Error;
910

@@ -102,7 +103,7 @@ pub(super) fn verify_checksum(s: &str) -> Result<&str, Error> {
102103
#[cfg(test)]
103104
mod test {
104105
use super::*;
105-
use std::str;
106+
use core::str;
106107

107108
macro_rules! check_expected {
108109
($desc: expr, $checksum: expr) => {

0 commit comments

Comments
 (0)