if: "matrix.build-no-std && !matrix.coverage"
run: |
cd lightning
- cargo test --verbose --color always --features hashbrown
+ cargo test --verbose --color always --no-default-features --features no_std
+ # check if there is a conflict between no_std and the default std feature
+ cargo test --verbose --color always --features no_std
cd ..
- name: Test on no_std bullds Rust ${{ matrix.toolchain }} and full code-linking for coverage generation
if: "matrix.build-no-std && matrix.coverage"
run: |
cd lightning
- RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --features hashbrown
+ RUSTFLAGS="-C link-dead-code" cargo test --verbose --color always --no-default-features --features no_std
cd ..
- name: Test on Rust ${{ matrix.toolchain }}
if: "! matrix.build-net-tokio"
# This is unsafe to use in production because it may result in the counterparty publishing taking our funds.
unsafe_revoked_tx_signing = []
unstable = []
+
no_std = ["hashbrown"]
+std = []
+
+default = ["std"]
[dependencies]
bitcoin = "0.26"
use util::events::EventHandler;
use prelude::*;
-use std::sync::RwLock;
+use sync::RwLock;
use core::ops::Deref;
/// An implementation of [`chain::Watch`] for monitoring channels.
use core::{cmp, mem};
use std::io::Error;
use core::ops::Deref;
-use std::sync::Mutex;
+use sync::Mutex;
/// An update generated by the underlying Channel itself which contains some new information the
/// ChannelMonitor should be made aware of.
use util::test_utils::{TestLogger, TestBroadcaster, TestFeeEstimator};
use bitcoin::secp256k1::key::{SecretKey,PublicKey};
use bitcoin::secp256k1::Secp256k1;
- use std::sync::{Arc, Mutex};
+ use sync::{Arc, Mutex};
use chain::keysinterface::InMemorySigner;
use prelude::*;
#[cfg(feature = "hashbrown")]
pub use self::hashbrown::{HashMap, HashSet, hash_map};
}
+
+#[cfg(feature = "std")]
+mod sync {
+ pub use ::std::sync::{Arc, Mutex, Condvar, MutexGuard, RwLock, RwLockReadGuard};
+}
+
+#[cfg(not(feature = "std"))]
+mod sync;
use util::test_utils;
use prelude::*;
-use std::sync::{Arc, Mutex};
+use sync::{Arc, Mutex};
// If persister_fail is true, we have the persister return a PermanentFailure
// instead of the higher-level ChainMonitor.
use prelude::*;
use core::{cmp,mem,fmt};
use core::ops::Deref;
-#[cfg(any(test, feature = "fuzztarget"))]
-use std::sync::Mutex;
+#[cfg(any(test, feature = "fuzztarget", debug_assertions))]
+use sync::Mutex;
use bitcoin::hashes::hex::ToHex;
use bitcoin::blockdata::opcodes::all::OP_PUSHBYTES_0;
#[cfg(debug_assertions)]
/// Max to_local and to_remote outputs in a locally-generated commitment transaction
- holder_max_commitment_tx_output: ::std::sync::Mutex<(u64, u64)>,
+ holder_max_commitment_tx_output: Mutex<(u64, u64)>,
#[cfg(debug_assertions)]
/// Max to_local and to_remote outputs in a remote-generated commitment transaction
- counterparty_max_commitment_tx_output: ::std::sync::Mutex<(u64, u64)>,
+ counterparty_max_commitment_tx_output: Mutex<(u64, u64)>,
last_sent_closing_fee: Option<(u32, u64, Signature)>, // (feerate, fee, holder_sig)
monitor_pending_failures: Vec::new(),
#[cfg(debug_assertions)]
- holder_max_commitment_tx_output: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
+ holder_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
#[cfg(debug_assertions)]
- counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
+ counterparty_max_commitment_tx_output: Mutex::new((channel_value_satoshis * 1000 - push_msat, push_msat)),
last_sent_closing_fee: None,
monitor_pending_failures: Vec::new(),
#[cfg(debug_assertions)]
- holder_max_commitment_tx_output: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
+ holder_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
#[cfg(debug_assertions)]
- counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
+ counterparty_max_commitment_tx_output: Mutex::new((msg.push_msat, msg.funding_satoshis * 1000 - msg.push_msat)),
last_sent_closing_fee: None,
feerate_per_kw,
#[cfg(debug_assertions)]
- holder_max_commitment_tx_output: ::std::sync::Mutex::new((0, 0)),
+ holder_max_commitment_tx_output: Mutex::new((0, 0)),
#[cfg(debug_assertions)]
- counterparty_max_commitment_tx_output: ::std::sync::Mutex::new((0, 0)),
+ counterparty_max_commitment_tx_output: Mutex::new((0, 0)),
last_sent_closing_fee,
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::hashes::Hash;
use bitcoin::hash_types::{Txid, WPubkeyHash};
- use std::sync::Arc;
+ use sync::Arc;
use prelude::*;
struct TestFeeEstimator {
use core::{cmp, mem};
use core::cell::RefCell;
use std::io::{Cursor, Read};
-use std::sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
+use sync::{Arc, Condvar, Mutex, MutexGuard, RwLock, RwLockReadGuard};
use core::sync::atomic::{AtomicUsize, Ordering};
use core::time::Duration;
#[cfg(any(test, feature = "allow_wallclock_use"))]
#[cfg(test)]
mod tests {
use ln::channelmanager::PersistenceNotifier;
- use std::sync::Arc;
+ use sync::Arc;
use core::sync::atomic::{AtomicBool, Ordering};
use std::thread;
use core::time::Duration;
use ln::features::InitFeatures;
use ln::msgs::ChannelMessageHandler;
+ #[cfg(feature = "std")]
#[test]
fn test_wait_timeout() {
let persistence_notifier = Arc::new(PersistenceNotifier::new());
use bitcoin::hashes::sha256::Hash as Sha256;
use bitcoin::{Block, BlockHeader, Transaction, TxOut};
- use std::sync::{Arc, Mutex};
+ use sync::{Arc, Mutex};
use test::Bencher;
set_shutdown_any_segwit_required);
#[cfg(test)]
- define_context!(TestingContext {
- required_features: [
- // Byte 0
- ,
- // Byte 1
- ,
- // Byte 2
- UnknownFeature,
- ],
- optional_features: [
- // Byte 0
- ,
- // Byte 1
- ,
- // Byte 2
- ,
- ],
- });
-
- #[cfg(test)]
- define_feature!(23, UnknownFeature, [TestingContext],
+ define_feature!(123456789, UnknownFeature, [NodeContext, ChannelContext, InvoiceContext],
"Feature flags for an unknown feature used in testing.", set_unknown_feature_optional,
set_unknown_feature_required);
}
/// Converts `Features<T>` to `Features<C>`. Only known `T` features relevant to context `C` are
/// included in the result.
fn to_context_internal<C: sealed::Context>(&self) -> Features<C> {
- let byte_count = C::KNOWN_FEATURE_MASK.len();
+ let from_byte_count = T::KNOWN_FEATURE_MASK.len();
+ let to_byte_count = C::KNOWN_FEATURE_MASK.len();
let mut flags = Vec::new();
for (i, byte) in self.flags.iter().enumerate() {
- if i < byte_count {
- let known_source_features = T::KNOWN_FEATURE_MASK[i];
- let known_target_features = C::KNOWN_FEATURE_MASK[i];
- flags.push(byte & known_source_features & known_target_features);
+ if i < from_byte_count && i < to_byte_count {
+ let from_known_features = T::KNOWN_FEATURE_MASK[i];
+ let to_known_features = C::KNOWN_FEATURE_MASK[i];
+ flags.push(byte & from_known_features & to_known_features);
}
}
Features::<C> { flags, mark: PhantomData, }
pub(crate) fn byte_count(&self) -> usize {
self.flags.len()
}
-
- #[cfg(test)]
- pub(crate) fn set_required_unknown_bits(&mut self) {
- <sealed::TestingContext as sealed::UnknownFeature>::set_required_bit(&mut self.flags);
- }
-
- #[cfg(test)]
- pub(crate) fn set_optional_unknown_bits(&mut self) {
- <sealed::TestingContext as sealed::UnknownFeature>::set_optional_bit(&mut self.flags);
- }
-
- #[cfg(test)]
- pub(crate) fn clear_unknown_bits(&mut self) {
- <sealed::TestingContext as sealed::UnknownFeature>::clear_bits(&mut self.flags);
- }
}
impl<T: sealed::DataLossProtect> Features<T> {
#[test]
fn sanity_test_unknown_bits() {
- let mut features = ChannelFeatures::empty();
+ let features = ChannelFeatures::empty();
assert!(!features.requires_unknown_bits());
assert!(!features.supports_unknown_bits());
- features.set_required_unknown_bits();
+ let features = ChannelFeatures::empty().set_unknown_feature_required();
assert!(features.requires_unknown_bits());
assert!(features.supports_unknown_bits());
- features.clear_unknown_bits();
- assert!(!features.requires_unknown_bits());
- assert!(!features.supports_unknown_bits());
-
- features.set_optional_unknown_bits();
+ let features = ChannelFeatures::empty().set_unknown_feature_optional();
assert!(!features.requires_unknown_bits());
assert!(features.supports_unknown_bits());
}
assert!(!init_features.supports_gossip_queries());
}
+ #[test]
+ fn convert_to_context_with_unknown_flags() {
+ // Ensure the `from` context has fewer known feature bytes than the `to` context.
+ assert!(InvoiceFeatures::known().byte_count() < NodeFeatures::known().byte_count());
+ let invoice_features = InvoiceFeatures::known().set_unknown_feature_optional();
+ assert!(invoice_features.supports_unknown_bits());
+ let node_features: NodeFeatures = invoice_features.to_context();
+ assert!(!node_features.supports_unknown_bits());
+ }
+
#[test]
fn set_feature_bits() {
let features = InvoiceFeatures::empty()
use prelude::*;
use core::cell::RefCell;
use std::rc::Rc;
-use std::sync::{Arc, Mutex};
+use sync::{Arc, Mutex};
use core::mem;
pub const CHAN_CONFIRM_DEPTH: u32 = 10;
use prelude::*;
use alloc::collections::BTreeSet;
use core::default::Default;
-use std::sync::{Arc, Mutex};
+use sync::{Arc, Mutex};
use ln::functional_test_utils::*;
use ln::chan_utils::CommitmentTransaction;
use prelude::*;
use alloc::collections::LinkedList;
use alloc::fmt::Debug;
-use std::sync::{Arc, Mutex};
+use sync::{Arc, Mutex};
use core::sync::atomic::{AtomicUsize, Ordering};
use core::{cmp, hash, fmt, mem};
use core::ops::Deref;
use bitcoin::secp256k1::key::{SecretKey, PublicKey};
use prelude::*;
- use std::sync::{Arc, Mutex};
+ use sync::{Arc, Mutex};
use core::sync::atomic::Ordering;
#[derive(Clone)]
use prelude::*;
use alloc::collections::{BTreeMap, btree_map::Entry as BtreeEntry};
use core::{cmp, fmt};
-use std::sync::{RwLock, RwLockReadGuard};
+use sync::{RwLock, RwLockReadGuard};
use core::sync::atomic::{AtomicUsize, Ordering};
-use std::sync::Mutex;
+use sync::Mutex;
use core::ops::Deref;
use bitcoin::hashes::hex::ToHex;
use bitcoin::secp256k1::{All, Secp256k1};
use prelude::*;
- use std::sync::Arc;
+ use sync::Arc;
fn create_net_graph_msg_handler() -> (Secp256k1<All>, NetGraphMsgHandler<Arc<test_utils::TestChainSource>, Arc<test_utils::TestLogger>>) {
let secp_ctx = Secp256k1::new();
htlc_maximum_msat: hop.htlc_maximum_msat,
fees: hop.fees,
};
- if add_entry!(hop.short_channel_id, hop.src_node_id, payee, directional_info, None::<u64>, &empty_channel_features, 0, path_value_msat, 0) {
+ // We assume that the recipient only included route hints for routes which had
+ // sufficient value to route `final_value_msat`. Note that in the case of "0-value"
+ // invoices where the invoice does not specify value this may not be the case, but
+ // better to include the hints than not.
+ if add_entry!(hop.short_channel_id, hop.src_node_id, payee, directional_info, Some((final_value_msat + 999) / 1000), &empty_channel_features, 0, path_value_msat, 0) {
// If this hop connects to a node with which we have a direct channel,
// ignore the network graph and, if the last hop was added, add our
// direct channel to the candidate set.
use bitcoin::secp256k1::{Secp256k1, All};
use prelude::*;
- use std::sync::Arc;
+ use sync::{self, Arc};
fn get_channel_details(short_channel_id: Option<u64>, node_id: PublicKey,
features: InitFeatures, outbound_capacity_msat: u64) -> channelmanager::ChannelDetails {
}
}
- fn build_graph() -> (Secp256k1<All>, NetGraphMsgHandler<std::sync::Arc<test_utils::TestChainSource>, std::sync::Arc<crate::util::test_utils::TestLogger>>, std::sync::Arc<test_utils::TestChainSource>, std::sync::Arc<test_utils::TestLogger>) {
+ fn build_graph() -> (Secp256k1<All>, NetGraphMsgHandler<sync::Arc<test_utils::TestChainSource>, sync::Arc<crate::util::test_utils::TestLogger>>, sync::Arc<test_utils::TestChainSource>, sync::Arc<test_utils::TestLogger>) {
let secp_ctx = Secp256k1::new();
let logger = Arc::new(test_utils::TestLogger::new());
let chain_monitor = Arc::new(test_utils::TestChainSource::new(Network::Testnet));
let (_, our_id, privkeys, nodes) = get_nodes(&secp_ctx);
// Disable nodes 1, 2, and 8 by requiring unknown feature bits
- let mut unknown_features = NodeFeatures::known();
- unknown_features.set_required_unknown_bits();
+ let unknown_features = NodeFeatures::known().set_unknown_feature_required();
add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[0], unknown_features.clone(), 1);
add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[1], unknown_features.clone(), 1);
add_or_update_node(&net_graph_msg_handler, &secp_ctx, &privkeys[7], unknown_features.clone(), 1);
--- /dev/null
+pub use ::alloc::sync::Arc;
+use core::ops::{Deref, DerefMut};
+use core::time::Duration;
+use core::cell::{RefCell, Ref, RefMut};
+
+pub type LockResult<Guard> = Result<Guard, ()>;
+
+pub struct Condvar {}
+
+impl Condvar {
+ pub fn new() -> Condvar {
+ Condvar { }
+ }
+
+ pub fn wait<'a, T>(&'a self, guard: MutexGuard<'a, T>) -> LockResult<MutexGuard<'a, T>> {
+ Ok(guard)
+ }
+
+ #[allow(unused)]
+ pub fn wait_timeout<'a, T>(&'a self, guard: MutexGuard<'a, T>, _dur: Duration) -> LockResult<(MutexGuard<'a, T>, ())> {
+ Ok((guard, ()))
+ }
+
+ pub fn notify_all(&self) {}
+}
+
+pub struct Mutex<T: ?Sized> {
+ inner: RefCell<T>
+}
+
+#[must_use = "if unused the Mutex will immediately unlock"]
+pub struct MutexGuard<'a, T: ?Sized + 'a> {
+ lock: RefMut<'a, T>,
+}
+
+impl<T: ?Sized> Deref for MutexGuard<'_, T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &self.lock.deref()
+ }
+}
+
+impl<T: ?Sized> DerefMut for MutexGuard<'_, T> {
+ fn deref_mut(&mut self) -> &mut T {
+ self.lock.deref_mut()
+ }
+}
+
+impl<T> Mutex<T> {
+ pub fn new(inner: T) -> Mutex<T> {
+ Mutex { inner: RefCell::new(inner) }
+ }
+
+ pub fn lock<'a>(&'a self) -> LockResult<MutexGuard<'a, T>> {
+ Ok(MutexGuard { lock: self.inner.borrow_mut() })
+ }
+
+ pub fn try_lock<'a>(&'a self) -> LockResult<MutexGuard<'a, T>> {
+ Ok(MutexGuard { lock: self.inner.borrow_mut() })
+ }
+}
+
+pub struct RwLock<T: ?Sized> {
+ inner: RefCell<T>
+}
+
+pub struct RwLockReadGuard<'a, T: ?Sized + 'a> {
+ lock: Ref<'a, T>,
+}
+
+pub struct RwLockWriteGuard<'a, T: ?Sized + 'a> {
+ lock: RefMut<'a, T>,
+}
+
+impl<T: ?Sized> Deref for RwLockReadGuard<'_, T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &self.lock.deref()
+ }
+}
+
+impl<T: ?Sized> Deref for RwLockWriteGuard<'_, T> {
+ type Target = T;
+
+ fn deref(&self) -> &T {
+ &self.lock.deref()
+ }
+}
+
+impl<T: ?Sized> DerefMut for RwLockWriteGuard<'_, T> {
+ fn deref_mut(&mut self) -> &mut T {
+ self.lock.deref_mut()
+ }
+}
+
+impl<T> RwLock<T> {
+ pub fn new(inner: T) -> RwLock<T> {
+ RwLock { inner: RefCell::new(inner) }
+ }
+
+ pub fn read<'a>(&'a self) -> LockResult<RwLockReadGuard<'a, T>> {
+ Ok(RwLockReadGuard { lock: self.inner.borrow() })
+ }
+
+ pub fn write<'a>(&'a self) -> LockResult<RwLockWriteGuard<'a, T>> {
+ Ok(RwLockWriteGuard { lock: self.inner.borrow_mut() })
+ }
+
+ pub fn try_write<'a>(&'a self) -> LockResult<RwLockWriteGuard<'a, T>> {
+ // There is no try, grasshopper - only used for tests and expected to fail
+ Err(())
+ }
+}
use prelude::*;
use core::cmp;
-use std::sync::{Mutex, Arc};
+use sync::{Mutex, Arc};
use bitcoin::blockdata::transaction::{Transaction, SigHashType};
use bitcoin::util::bip143;
mod tests {
use util::logger::{Logger, Level};
use util::test_utils::TestLogger;
- use std::sync::Arc;
+ use sync::Arc;
#[test]
fn test_level_show() {
}
fn sigrec_decode(sig_rec: Vec<u8>) -> Result<RecoverableSignature, Error> {
+ // Signature must be 64 + 1 bytes long (compact signature + recovery id)
+ if sig_rec.len() != 65 {
+ return Err(Error::InvalidSignature);
+ }
+
let rsig = &sig_rec[1..];
let rid = sig_rec[0] as i32 - 31;
use prelude::*;
use std::io::{Read, Write};
use core::hash::Hash;
-use std::sync::Mutex;
+use sync::Mutex;
use core::cmp;
use bitcoin::secp256k1::Signature;
use prelude::*;
use core::time::Duration;
-use std::sync::{Mutex, Arc};
+use sync::{Mutex, Arc};
use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
use core::{cmp, mem};
use chain::keysinterface::InMemorySigner;