Skip to content

Commit 57feb26

Browse files
authored
Merge pull request #1028 from lightning-signer/2021-08-no-std
Actual no_std support
2 parents 75f77a5 + 32d13a2 commit 57feb26

29 files changed

+297
-187
lines changed

.github/workflows/build.yml

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
1.41.0,
1717
# 1.45.2 is MSRV for lightning-net-tokio, lightning-block-sync, and coverage generation
1818
1.45.2,
19-
# 1.47.0 will be the MSRV for no_std builds using hashbrown once core2 is updated
19+
# 1.47.0 will be the MSRV for no-std builds using hashbrown once core2 is updated
2020
1.47.0]
2121
include:
2222
- toolchain: stable
@@ -95,19 +95,19 @@ jobs:
9595
- name: Test on Rust ${{ matrix.toolchain }} with net-tokio and full code-linking for coverage generation
9696
if: matrix.coverage
9797
run: RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always
98-
- name: Test on no_std bullds Rust ${{ matrix.toolchain }}
98+
- name: Test on no-std bullds Rust ${{ matrix.toolchain }}
9999
if: "matrix.build-no-std && !matrix.coverage"
100100
run: |
101101
cd lightning
102-
cargo test --verbose --color always --no-default-features --features no_std
103-
# check if there is a conflict between no_std and the default std feature
104-
cargo test --verbose --color always --features no_std
102+
cargo test --verbose --color always --no-default-features --features no-std
103+
# check if there is a conflict between no-std and the default std feature
104+
cargo test --verbose --color always --features no-std
105105
cd ..
106-
- name: Test on no_std bullds Rust ${{ matrix.toolchain }} and full code-linking for coverage generation
106+
- name: Test on no-std builds Rust ${{ matrix.toolchain }} and full code-linking for coverage generation
107107
if: "matrix.build-no-std && matrix.coverage"
108108
run: |
109109
cd lightning
110-
RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --no-default-features --features no_std
110+
RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --no-default-features --features no-std
111111
cd ..
112112
- name: Test on Rust ${{ matrix.toolchain }}
113113
if: "! matrix.build-net-tokio"

ci/check-compiles.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,4 +6,4 @@ cargo check
66
cargo doc
77
cargo doc --document-private-items
88
cd fuzz && cargo check --features=stdin_fuzz
9-
cd ../lightning && cargo check --no-default-features --features=no_std
9+
cd ../lightning && cargo check --no-default-features --features=no-std

lightning/Cargo.toml

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,25 +26,32 @@ max_level_debug = []
2626
unsafe_revoked_tx_signing = []
2727
unstable = []
2828

29-
no_std = ["hashbrown", "bitcoin/no-std"]
29+
no-std = ["hashbrown", "bitcoin/no-std", "core2/alloc"]
3030
std = ["bitcoin/std"]
3131

3232
default = ["std"]
3333

3434
[dependencies]
35-
bitcoin = "0.27"
35+
bitcoin = { version = "0.27", default-features = false, features = ["secp-recovery"] }
36+
# TODO remove this once rust-bitcoin PR #637 is released
37+
secp256k1 = { version = "0.20.2", default-features = false, features = ["alloc"] }
3638

3739
hashbrown = { version = "0.11", optional = true }
3840
hex = { version = "0.3", optional = true }
3941
regex = { version = "0.1.80", optional = true }
4042

43+
core2 = { version = "0.3.0", optional = true, default-features = false }
44+
4145
[dev-dependencies]
4246
hex = "0.3"
4347
regex = "0.1.80"
48+
# TODO remove this once rust-bitcoin PR #637 is released
49+
secp256k1 = { version = "0.20.2", default-features = false, features = ["alloc"] }
4450

4551
[dev-dependencies.bitcoin]
4652
version = "0.27"
47-
features = ["bitcoinconsensus"]
53+
default-features = false
54+
features = ["bitcoinconsensus", "secp-recovery"]
4855

4956
[package.metadata.docs.rs]
5057
features = ["allow_wallclock_use"] # When https://github.com/rust-lang/rust/issues/43781 complies with our MSVR, we can add nice banners in the docs for the methods behind this feature-gate.

lightning/src/chain/channelmonitor.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use util::events::Event;
5353

5454
use prelude::*;
5555
use core::{cmp, mem};
56-
use std::io::Error;
56+
use io::{self, Error};
5757
use core::ops::Deref;
5858
use sync::Mutex;
5959

@@ -88,7 +88,7 @@ pub struct ChannelMonitorUpdate {
8888
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = core::u64::MAX;
8989

9090
impl Writeable for ChannelMonitorUpdate {
91-
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
91+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
9292
write_ver_prefix!(w, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
9393
self.update_id.write(w)?;
9494
(self.updates.len() as u64).write(w)?;
@@ -100,7 +100,7 @@ impl Writeable for ChannelMonitorUpdate {
100100
}
101101
}
102102
impl Readable for ChannelMonitorUpdate {
103-
fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
103+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
104104
let _ver = read_ver_prefix!(r, SERIALIZATION_VERSION);
105105
let update_id: u64 = Readable::read(r)?;
106106
let len: u64 = Readable::read(r)?;
@@ -293,7 +293,7 @@ struct CounterpartyCommitmentTransaction {
293293
}
294294

295295
impl Writeable for CounterpartyCommitmentTransaction {
296-
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
296+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
297297
w.write_all(&byte_utils::be64_to_array(self.per_htlc.len() as u64))?;
298298
for (ref txid, ref htlcs) in self.per_htlc.iter() {
299299
w.write_all(&txid[..])?;
@@ -311,7 +311,7 @@ impl Writeable for CounterpartyCommitmentTransaction {
311311
}
312312
}
313313
impl Readable for CounterpartyCommitmentTransaction {
314-
fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
314+
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
315315
let counterparty_commitment_transaction = {
316316
let per_htlc_len: u64 = Readable::read(r)?;
317317
let mut per_htlc = HashMap::with_capacity(cmp::min(per_htlc_len as usize, MAX_ALLOC_SIZE / 64));
@@ -2581,7 +2581,7 @@ const MAX_ALLOC_SIZE: usize = 64*1024;
25812581

25822582
impl<'a, Signer: Sign, K: KeysInterface<Signer = Signer>> ReadableArgs<&'a K>
25832583
for (BlockHash, ChannelMonitor<Signer>) {
2584-
fn read<R: ::std::io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
2584+
fn read<R: io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
25852585
macro_rules! unwrap_obj {
25862586
($key: expr) => {
25872587
match $key {

lightning/src/chain/keysinterface.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use ln::msgs::UnsignedChannelAnnouncement;
3939

4040
use prelude::*;
4141
use core::sync::atomic::{AtomicUsize, Ordering};
42-
use std::io::Error;
42+
use io::{self, Error};
4343
use ln::msgs::{DecodeError, MAX_VALUE_MSAT};
4444

4545
/// Information about a spendable output to a P2WSH script. See
@@ -699,7 +699,7 @@ impl Writeable for InMemorySigner {
699699
}
700700

701701
impl Readable for InMemorySigner {
702-
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
702+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
703703
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
704704

705705
let funding_key = Readable::read(reader)?;
@@ -1039,7 +1039,7 @@ impl KeysInterface for KeysManager {
10391039
}
10401040

10411041
fn read_chan_signer(&self, reader: &[u8]) -> Result<Self::Signer, DecodeError> {
1042-
InMemorySigner::read(&mut std::io::Cursor::new(reader))
1042+
InMemorySigner::read(&mut io::Cursor::new(reader))
10431043
}
10441044

10451045
fn sign_invoice(&self, invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {

lightning/src/chain/onchaintx.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use util::logger::Logger;
3232
use util::ser::{Readable, ReadableArgs, Writer, Writeable, VecWriter};
3333
use util::byte_utils;
3434

35+
use io;
3536
use prelude::*;
3637
use alloc::collections::BTreeMap;
3738
use core::cmp;
@@ -94,7 +95,7 @@ impl_writeable_tlv_based_enum!(OnchainEvent,
9495
;);
9596

9697
impl Readable for Option<Vec<Option<(usize, Signature)>>> {
97-
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
98+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
9899
match Readable::read(reader)? {
99100
0u8 => Ok(None),
100101
1u8 => {
@@ -115,7 +116,7 @@ impl Readable for Option<Vec<Option<(usize, Signature)>>> {
115116
}
116117

117118
impl Writeable for Option<Vec<Option<(usize, Signature)>>> {
118-
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
119+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
119120
match self {
120121
&Some(ref vec) => {
121122
1u8.write(writer)?;
@@ -191,7 +192,7 @@ const SERIALIZATION_VERSION: u8 = 1;
191192
const MIN_SERIALIZATION_VERSION: u8 = 1;
192193

193194
impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
194-
pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
195+
pub(crate) fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
195196
write_ver_prefix!(writer, SERIALIZATION_VERSION, MIN_SERIALIZATION_VERSION);
196197

197198
self.destination_script.write(writer)?;
@@ -242,7 +243,7 @@ impl<ChannelSigner: Sign> OnchainTxHandler<ChannelSigner> {
242243
}
243244

244245
impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
245-
fn read<R: ::std::io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
246+
fn read<R: io::Read>(reader: &mut R, keys_manager: &'a K) -> Result<Self, DecodeError> {
246247
let _ver = read_ver_prefix!(reader, SERIALIZATION_VERSION);
247248

248249
let destination_script = Readable::read(reader)?;
@@ -285,7 +286,7 @@ impl<'a, K: KeysInterface> ReadableArgs<&'a K> for OnchainTxHandler<K::Signer> {
285286
for _ in 0..locktimed_packages_len {
286287
let locktime = Readable::read(reader)?;
287288
let packages_len: u64 = Readable::read(reader)?;
288-
let mut packages = Vec::with_capacity(cmp::min(packages_len as usize, MAX_ALLOC_SIZE / std::mem::size_of::<PackageTemplate>()));
289+
let mut packages = Vec::with_capacity(cmp::min(packages_len as usize, MAX_ALLOC_SIZE / core::mem::size_of::<PackageTemplate>()));
289290
for _ in 0..packages_len {
290291
packages.push(Readable::read(reader)?);
291292
}

lightning/src/chain/package.rs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ use util::byte_utils;
3131
use util::logger::Logger;
3232
use util::ser::{Readable, Writer, Writeable};
3333

34+
use io;
35+
use prelude::*;
3436
use core::cmp;
3537
use core::mem;
3638
use core::ops::Deref;
@@ -395,8 +397,8 @@ impl PackageSolvingData {
395397
PackageSolvingData::RevokedOutput(_) => output_conf_height + 1,
396398
PackageSolvingData::RevokedHTLCOutput(_) => output_conf_height + 1,
397399
PackageSolvingData::CounterpartyOfferedHTLCOutput(_) => output_conf_height + 1,
398-
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => std::cmp::max(outp.htlc.cltv_expiry, output_conf_height + 1),
399-
PackageSolvingData::HolderHTLCOutput(ref outp) => std::cmp::max(outp.cltv_expiry, output_conf_height + 1),
400+
PackageSolvingData::CounterpartyReceivedHTLCOutput(ref outp) => cmp::max(outp.htlc.cltv_expiry, output_conf_height + 1),
401+
PackageSolvingData::HolderHTLCOutput(ref outp) => cmp::max(outp.cltv_expiry, output_conf_height + 1),
400402
PackageSolvingData::HolderFundingOutput(_) => output_conf_height + 1,
401403
};
402404
absolute_timelock
@@ -682,7 +684,7 @@ impl PackageTemplate {
682684
}
683685

684686
impl Writeable for PackageTemplate {
685-
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
687+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
686688
writer.write_all(&byte_utils::be64_to_array(self.inputs.len() as u64))?;
687689
for (ref outpoint, ref rev_outp) in self.inputs.iter() {
688690
outpoint.write(writer)?;
@@ -699,7 +701,7 @@ impl Writeable for PackageTemplate {
699701
}
700702

701703
impl Readable for PackageTemplate {
702-
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
704+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
703705
let inputs_count = <u64 as Readable>::read(reader)?;
704706
let mut inputs: Vec<(BitcoinOutPoint, PackageSolvingData)> = Vec::with_capacity(cmp::min(inputs_count as usize, MAX_ALLOC_SIZE / 128));
705707
for _ in 0..inputs_count {

lightning/src/lib.rs

Lines changed: 89 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,31 +28,119 @@
2828
#![allow(bare_trait_objects)]
2929
#![allow(ellipsis_inclusive_range_patterns)]
3030

31+
#![cfg_attr(all(not(feature = "std"), not(test)), no_std)]
32+
3133
#![cfg_attr(all(any(test, feature = "_test_utils"), feature = "unstable"), feature(test))]
3234
#[cfg(all(any(test, feature = "_test_utils"), feature = "unstable"))] extern crate test;
3335

36+
#[cfg(not(any(feature = "std", feature = "no-std")))]
37+
compile_error!("at least one of the `std` or `no-std` features must be enabled");
38+
3439
#[macro_use]
3540
extern crate alloc;
3641
extern crate bitcoin;
42+
#[cfg(any(test, feature = "std"))]
3743
extern crate core;
44+
3845
#[cfg(any(test, feature = "_test_utils"))] extern crate hex;
3946
#[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))] extern crate regex;
4047

48+
#[cfg(not(feature = "std"))] extern crate core2;
49+
4150
#[macro_use]
4251
pub mod util;
4352
pub mod chain;
4453
pub mod ln;
4554
pub mod routing;
4655

56+
#[cfg(feature = "std")]
57+
use std::io;
58+
#[cfg(not(feature = "std"))]
59+
use core2::io;
60+
61+
#[cfg(not(feature = "std"))]
62+
mod io_extras {
63+
use core2::io::{self, Read, Write};
64+
65+
/// A writer which will move data into the void.
66+
pub struct Sink {
67+
_priv: (),
68+
}
69+
70+
/// Creates an instance of a writer which will successfully consume all data.
71+
pub const fn sink() -> Sink {
72+
Sink { _priv: () }
73+
}
74+
75+
impl core2::io::Write for Sink {
76+
#[inline]
77+
fn write(&mut self, buf: &[u8]) -> core2::io::Result<usize> {
78+
Ok(buf.len())
79+
}
80+
81+
#[inline]
82+
fn flush(&mut self) -> core2::io::Result<()> {
83+
Ok(())
84+
}
85+
}
86+
87+
pub fn copy<R: ?Sized, W: ?Sized>(reader: &mut R, writer: &mut W) -> Result<u64, io::Error>
88+
where
89+
R: Read,
90+
W: Write,
91+
{
92+
let mut count = 0;
93+
let mut buf = [0u8; 64];
94+
95+
loop {
96+
match reader.read(&mut buf) {
97+
Ok(0) => break,
98+
Ok(n) => { writer.write_all(&buf[0..n])?; count += n as u64; },
99+
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
100+
Err(e) => return Err(e.into()),
101+
};
102+
}
103+
Ok(count)
104+
}
105+
106+
pub fn read_to_end<D: io::Read>(mut d: D) -> Result<alloc::vec::Vec<u8>, io::Error> {
107+
let mut result = vec![];
108+
let mut buf = [0u8; 64];
109+
loop {
110+
match d.read(&mut buf) {
111+
Ok(0) => break,
112+
Ok(n) => result.extend_from_slice(&buf[0..n]),
113+
Err(ref e) if e.kind() == io::ErrorKind::Interrupted => {},
114+
Err(e) => return Err(e.into()),
115+
};
116+
}
117+
Ok(result)
118+
}
119+
}
120+
121+
#[cfg(feature = "std")]
122+
mod io_extras {
123+
pub fn read_to_end<D: ::std::io::Read>(mut d: D) -> Result<Vec<u8>, ::std::io::Error> {
124+
let mut buf = Vec::new();
125+
d.read_to_end(&mut buf)?;
126+
Ok(buf)
127+
}
128+
129+
pub use std::io::{copy, sink};
130+
}
131+
47132
mod prelude {
48133
#[cfg(feature = "hashbrown")]
49134
extern crate hashbrown;
50135

51-
pub use alloc::{vec, vec::Vec, string::String, collections::VecDeque};
136+
pub use alloc::{vec, vec::Vec, string::String, collections::VecDeque, boxed::Box};
52137
#[cfg(not(feature = "hashbrown"))]
53138
pub use std::collections::{HashMap, HashSet, hash_map};
54139
#[cfg(feature = "hashbrown")]
55140
pub use self::hashbrown::{HashMap, HashSet, hash_map};
141+
142+
pub use alloc::borrow::ToOwned;
143+
pub use alloc::string::ToString;
56144
}
57145

58146
#[cfg(feature = "std")]

lightning/src/ln/chan_utils.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ use bitcoin::secp256k1::{Secp256k1, Signature, Message};
3131
use bitcoin::secp256k1::Error as SecpError;
3232
use bitcoin::secp256k1;
3333

34+
use io;
3435
use prelude::*;
3536
use core::cmp;
3637
use ln::chan_utils;
@@ -167,7 +168,7 @@ impl CounterpartyCommitmentSecrets {
167168
}
168169

169170
impl Writeable for CounterpartyCommitmentSecrets {
170-
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), ::std::io::Error> {
171+
fn write<W: Writer>(&self, writer: &mut W) -> Result<(), io::Error> {
171172
for &(ref secret, ref idx) in self.old_secrets.iter() {
172173
writer.write_all(secret)?;
173174
writer.write_all(&byte_utils::be64_to_array(*idx))?;
@@ -177,7 +178,7 @@ impl Writeable for CounterpartyCommitmentSecrets {
177178
}
178179
}
179180
impl Readable for CounterpartyCommitmentSecrets {
180-
fn read<R: ::std::io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
181+
fn read<R: io::Read>(reader: &mut R) -> Result<Self, DecodeError> {
181182
let mut old_secrets = [([0; 32], 1 << 48); 49];
182183
for &mut (ref mut secret, ref mut idx) in old_secrets.iter_mut() {
183184
*secret = Readable::read(reader)?;

0 commit comments

Comments
 (0)