Skip to content

Commit

Permalink
Add initial no_std support
Browse files Browse the repository at this point in the history
Add initial no_std support for embedded platforms
  • Loading branch information
GeneFerneau committed May 15, 2021
1 parent 7297e13 commit faa43a0
Show file tree
Hide file tree
Showing 37 changed files with 186 additions and 106 deletions.
1 change: 1 addition & 0 deletions ci/check-compiles.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ cargo check
cargo doc
cargo doc --document-private-items
cd fuzz && cargo check --features=stdin_fuzz
cd ../lightning && cargo check --default-features=false --features=core
4 changes: 4 additions & 0 deletions lightning/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,18 @@ max_level_error = []
max_level_warn = []
max_level_info = []
max_level_debug = []
std = []
core = ["hashbrown"]
# Allow signing of local transactions that may have been revoked or will be revoked, for functional testing (e.g. justice tx handling).
# This is unsafe to use in production because it may result in the counterparty publishing taking our funds.
unsafe_revoked_tx_signing = []
unstable = []
default = ["std"]

[dependencies]
bitcoin = "0.26"

hashbrown = { version = "0.9", optional = true }
hex = { version = "0.3", optional = true }
regex = { version = "0.1.80", optional = true }

Expand Down
9 changes: 7 additions & 2 deletions lightning/src/chain/chainmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,11 @@ use util::logger::Logger;
use util::events;
use util::events::Event;

use std::collections::{HashMap, hash_map};
use alloc::vec::Vec;
use core::ops::Deref;
use crate::{HashMap, hash_map};
use std::sync::RwLock;
use std::ops::Deref;


/// An implementation of [`chain::Watch`] for monitoring channels.
///
Expand Down Expand Up @@ -324,6 +326,9 @@ mod tests {
use util::events::MessageSendEventsProvider;
use util::test_utils::{OnRegisterOutput, TxOutReference};

#[macro_use]
use alloc::vec;

/// Tests that in-block dependent transactions are processed by `block_connected` when not
/// included in `txdata` but returned by [`chain::Filter::register_output`]. For instance,
/// a (non-anchor) commitment transaction's HTLC output may be spent in the same block as the
Expand Down
16 changes: 9 additions & 7 deletions lightning/src/chain/channelmonitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,11 @@ use util::ser::{Readable, ReadableArgs, MaybeReadable, Writer, Writeable, U48};
use util::byte_utils;
use util::events::Event;

use std::collections::{HashMap, HashSet};
use std::{cmp, mem};
#[macro_use]
use alloc::{boxed::Box, vec, vec::Vec};
use crate::{HashMap, HashSet};
use core::{cmp, mem, ops::Deref};
use std::io::Error;
use std::ops::Deref;
use std::sync::Mutex;

/// An update generated by the underlying Channel itself which contains some new information the
Expand Down Expand Up @@ -85,7 +86,7 @@ pub struct ChannelMonitorUpdate {
/// then we allow the `ChannelManager` to send a `ChannelMonitorUpdate` with this update ID,
/// with the update providing said payment preimage. No other update types are allowed after
/// force-close.
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = std::u64::MAX;
pub const CLOSED_CHANNEL_UPDATE_ID: u64 = ::core::u64::MAX;

impl Writeable for ChannelMonitorUpdate {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
Expand All @@ -101,7 +102,7 @@ impl Readable for ChannelMonitorUpdate {
fn read<R: ::std::io::Read>(r: &mut R) -> Result<Self, DecodeError> {
let update_id: u64 = Readable::read(r)?;
let len: u64 = Readable::read(r)?;
let mut updates = Vec::with_capacity(cmp::min(len as usize, MAX_ALLOC_SIZE / ::std::mem::size_of::<ChannelMonitorUpdateStep>()));
let mut updates = Vec::with_capacity(cmp::min(len as usize, MAX_ALLOC_SIZE / ::core::mem::size_of::<ChannelMonitorUpdateStep>()));
for _ in 0..len {
updates.push(Readable::read(r)?);
}
Expand Down Expand Up @@ -1932,7 +1933,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {

for &(ref htlc, _, _) in holder_tx.htlc_outputs.iter() {
if let Some(transaction_output_index) = htlc.transaction_output_index {
claim_requests.push(ClaimRequest { absolute_timelock: ::std::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: holder_tx.txid, vout: transaction_output_index as u32 },
claim_requests.push(ClaimRequest { absolute_timelock: ::core::u32::MAX, aggregable: false, outpoint: BitcoinOutPoint { txid: holder_tx.txid, vout: transaction_output_index as u32 },
witness_data: InputMaterial::HolderHTLC {
preimage: if !htlc.offered {
if let Some(preimage) = self.payment_preimages.get(&htlc.payment_hash) {
Expand Down Expand Up @@ -2594,7 +2595,7 @@ impl<Signer: Sign> ChannelMonitorImpl<Signer> {
fn is_paying_spendable_output<L: Deref>(&mut self, tx: &Transaction, height: u32, logger: &L) where L::Target: Logger {
let mut spendable_output = None;
for (i, outp) in tx.output.iter().enumerate() { // There is max one spendable output for any channel tx, including ones generated by us
if i > ::std::u16::MAX as usize {
if i > ::core::u16::MAX as usize {
// While it is possible that an output exists on chain which is greater than the
// 2^16th output in a given transaction, this is only possible if the output is not
// in a lightning transaction and was instead placed there by some third party who
Expand Down Expand Up @@ -3060,6 +3061,7 @@ mod tests {
use bitcoin::secp256k1::Secp256k1;
use std::sync::{Arc, Mutex};
use chain::keysinterface::InMemorySigner;
use alloc::vec::Vec;

#[test]
fn test_prune_preimages() {
Expand Down
10 changes: 6 additions & 4 deletions lightning/src/chain/keysinterface.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,10 @@ use ln::chan_utils;
use ln::chan_utils::{HTLCOutputInCommitment, make_funding_redeemscript, ChannelPublicKeys, HolderCommitmentTransaction, ChannelTransactionParameters, CommitmentTransaction};
use ln::msgs::UnsignedChannelAnnouncement;

use std::collections::HashSet;
use std::sync::atomic::{AtomicUsize, Ordering};
#[macro_use]
use alloc::{vec, vec::Vec};
use core::sync::atomic::{AtomicUsize, Ordering};
use crate::HashSet;
use std::io::Error;
use ln::msgs::{DecodeError, MAX_VALUE_MSAT};

Expand Down Expand Up @@ -850,7 +852,7 @@ impl KeysManager {
/// onchain output detection for which a corresponding delayed_payment_key must be derived.
pub fn derive_channel_keys(&self, channel_value_satoshis: u64, params: &[u8; 32]) -> InMemorySigner {
let chan_id = byte_utils::slice_to_be64(&params[0..8]);
assert!(chan_id <= std::u32::MAX as u64); // Otherwise the params field wasn't created by us
assert!(chan_id <= core::u32::MAX as u64); // Otherwise the params field wasn't created by us
let mut unique_start = Sha256::engine();
unique_start.input(params);
unique_start.input(&self.seed);
Expand Down Expand Up @@ -1032,7 +1034,7 @@ impl KeysInterface for KeysManager {

fn get_channel_signer(&self, _inbound: bool, channel_value_satoshis: u64) -> Self::Signer {
let child_ix = self.channel_child_index.fetch_add(1, Ordering::AcqRel);
assert!(child_ix <= std::u32::MAX as usize);
assert!(child_ix <= core::u32::MAX as usize);
let mut id = [0; 32];
id[0..8].copy_from_slice(&byte_utils::be64_to_array(child_ix as u64));
id[8..16].copy_from_slice(&byte_utils::be64_to_array(self.starting_time_nanos as u64));
Expand Down
6 changes: 4 additions & 2 deletions lightning/src/chain/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

//! Structs and traits which allow other parts of rust-lightning to interact with the blockchain.

use alloc::vec::Vec;

use bitcoin::blockdata::block::{Block, BlockHeader};
use bitcoin::blockdata::script::Script;
use bitcoin::blockdata::transaction::{Transaction, TxOut};
Expand Down Expand Up @@ -246,7 +248,7 @@ pub struct WatchedOutput {
pub script_pubkey: Script,
}

impl<T: Listen> Listen for std::ops::Deref<Target = T> {
impl<T: Listen> Listen for core::ops::Deref<Target = T> {
fn block_connected(&self, block: &Block, height: u32) {
(**self).block_connected(block, height);
}
Expand All @@ -256,7 +258,7 @@ impl<T: Listen> Listen for std::ops::Deref<Target = T> {
}
}

impl<T: std::ops::Deref, U: std::ops::Deref> Listen for (T, U)
impl<T: core::ops::Deref, U: core::ops::Deref> Listen for (T, U)
where
T::Target: Listen,
U::Target: Listen,
Expand Down
10 changes: 10 additions & 0 deletions lightning/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#![cfg_attr(not(any(feature = "fuzztarget", feature = "_test_utils")), deny(missing_docs))]
#![cfg_attr(not(any(test, feature = "fuzztarget", feature = "_test_utils")), forbid(unsafe_code))]
#![deny(broken_intra_doc_links)]
#![cfg_attr(feature = "core", no_std)]

// In general, rust is absolutely horrid at supporting users doing things like,
// for example, compiling Rust code for real environments. Disable useless lints
Expand All @@ -35,6 +36,15 @@ extern crate bitcoin;
#[cfg(any(test, feature = "_test_utils"))] extern crate hex;
#[cfg(any(test, feature = "fuzztarget", feature = "_test_utils"))] extern crate regex;

extern crate alloc;
#[cfg(feature = "std")] extern crate core;
#[cfg(feature = "core")] extern crate hashbrown;

#[cfg(feature = "core")]
use hashbrown::{HashMap, HashSet, hash_map};
#[cfg(feature = "std")]
use std::collections::{HashMap, HashSet, hash_map};

#[macro_use]
pub mod util;
pub mod chain;
Expand Down
5 changes: 3 additions & 2 deletions lightning/src/ln/chan_utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ use bitcoin::secp256k1::{Secp256k1, Signature, Message};
use bitcoin::secp256k1::Error as SecpError;
use bitcoin::secp256k1;

use std::cmp;
use alloc::vec::Vec;
use core::{cmp, ops::Deref};
use ln::chan_utils;
use util::transaction_utils::sort_outputs;
use ln::channel::INITIAL_COMMITMENT_NUMBER;
use std::io::Read;
use std::ops::Deref;
use chain;

// Maximum size of a serialized HTLCOutputInCommitment
Expand Down Expand Up @@ -1235,6 +1235,7 @@ fn script_for_p2wpkh(key: &PublicKey) -> Script {
mod tests {
use super::CounterpartyCommitmentSecrets;
use hex;
use alloc::vec::Vec;

#[test]
fn test_per_commitment_storage() {
Expand Down
3 changes: 3 additions & 0 deletions lightning/src/ln/chanmon_update_fail_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ use ln::functional_test_utils::*;

use util::test_utils;

#[macro_use]
use alloc::{vec, vec::Vec};

// If persister_fail is true, we have the persister return a PermanentFailure
// instead of the higher-level ChainMonitor.
fn do_test_simple_monitor_permanent_update_fail(persister_fail: bool) {
Expand Down
21 changes: 12 additions & 9 deletions lightning/src/ln/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ use util::errors::APIError;
use util::config::{UserConfig,ChannelConfig};
use util::scid_utils::scid_from_parts;

use std;
use std::{cmp,mem,fmt};
use std::ops::Deref;
#[macro_use]
use alloc::{format, boxed::Box, string::String, vec, vec::Vec};
use core::{cmp, mem, fmt, ops::Deref};
#[cfg(any(test, feature = "fuzztarget"))]
use std::sync::Mutex;
use bitcoin::hashes::hex::ToHex;
Expand Down Expand Up @@ -1217,7 +1217,7 @@ impl<Signer: Sign> Channel<Signer> {
// on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop
// these, but for now we just have to treat them as normal.

let mut pending_idx = std::usize::MAX;
let mut pending_idx = core::usize::MAX;
for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() {
if htlc.htlc_id == htlc_id_arg {
assert_eq!(htlc.payment_hash, payment_hash_calc);
Expand All @@ -1240,7 +1240,7 @@ impl<Signer: Sign> Channel<Signer> {
break;
}
}
if pending_idx == std::usize::MAX {
if pending_idx == core::usize::MAX {
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned()));
}

Expand Down Expand Up @@ -1339,7 +1339,7 @@ impl<Signer: Sign> Channel<Signer> {
// on-chain ChannelsMonitors during block rescan. Ideally we'd figure out a way to drop
// these, but for now we just have to treat them as normal.

let mut pending_idx = std::usize::MAX;
let mut pending_idx = core::usize::MAX;
for (idx, htlc) in self.pending_inbound_htlcs.iter().enumerate() {
if htlc.htlc_id == htlc_id_arg {
match htlc.state {
Expand All @@ -1356,7 +1356,7 @@ impl<Signer: Sign> Channel<Signer> {
pending_idx = idx;
}
}
if pending_idx == std::usize::MAX {
if pending_idx == core::usize::MAX {
return Err(ChannelError::Ignore("Unable to find a pending HTLC which matched the given HTLC ID".to_owned()));
}

Expand Down Expand Up @@ -4394,8 +4394,8 @@ impl<Signer: Sign> Writeable for Channel<Signer> {

let mut key_data = VecWriter(Vec::new());
self.holder_signer.write(&mut key_data)?;
assert!(key_data.0.len() < std::usize::MAX);
assert!(key_data.0.len() < std::u32::MAX as usize);
assert!(key_data.0.len() < core::usize::MAX);
assert!(key_data.0.len() < core::u32::MAX as usize);
(key_data.0.len() as u32).write(writer)?;
writer.write_all(&key_data.0[..])?;

Expand Down Expand Up @@ -4859,6 +4859,9 @@ mod tests {
use bitcoin::hash_types::{Txid, WPubkeyHash};
use std::sync::Arc;

#[macro_use]
use alloc::{vec, vec::Vec};

struct TestFeeEstimator {
fee_est: u32
}
Expand Down
22 changes: 14 additions & 8 deletions lightning/src/ln/channelmanager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,15 +61,20 @@ use util::chacha20::{ChaCha20, ChaChaReader};
use util::logger::Logger;
use util::errors::APIError;

use std::{cmp, mem};
use std::collections::{HashMap, hash_map, HashSet};
#[macro_use]
use alloc::{format, vec, string::String, vec::Vec};
use core::{
cmp,
mem,
ops::Deref,
sync::atomic::{AtomicUsize, Ordering},
time::Duration,
};
use crate::{HashMap, HashSet, hash_map};
use std::io::{Cursor, Read};
use std::sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
use std::sync::atomic::{AtomicUsize, Ordering};
use std::time::Duration;
#[cfg(any(test, feature = "allow_wallclock_use"))]
use std::time::Instant;
use std::ops::Deref;
use bitcoin::hashes::hex::ToHex;

// We hold various information about HTLC relay in the HTLC objects in Channel itself:
Expand Down Expand Up @@ -1748,7 +1753,7 @@ impl<Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref> ChannelMana
// be absurd. We ensure this by checking that at least 500 (our stated public contract on when
// broadcast_node_announcement panics) of the maximum-length addresses would fit in a 64KB
// message...
const HALF_MESSAGE_IS_ADDRS: u32 = ::std::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2;
const HALF_MESSAGE_IS_ADDRS: u32 = core::u16::MAX as u32 / (NetAddress::MAX_LEN as u32 + 1) / 2;
#[deny(const_err)]
#[allow(dead_code)]
// ...by failing to compile if the number of addresses that would be half of a message is
Expand Down Expand Up @@ -4716,9 +4721,8 @@ impl<'a, Signer: Sign, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
mod tests {
use ln::channelmanager::PersistenceNotifier;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use core::{sync::atomic::{AtomicBool, Ordering}, time::Duration};
use std::thread;
use std::time::Duration;

#[test]
fn test_wait_timeout() {
Expand Down Expand Up @@ -4783,6 +4787,8 @@ pub mod bench {
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::{Block, BlockHeader, Transaction, TxOut};

use alloc::vec::Vec;
use core::default::Default;
use std::sync::Mutex;

use test::Bencher;
Expand Down

0 comments on commit faa43a0

Please sign in to comment.