From f9acac8fec03f9120b943ec64d50de087cc0f43a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 6 Oct 2022 15:42:41 +0000 Subject: [PATCH 1/5] Correct `rapid-gossip-sync` `no-std` build and test While `rapid-gossip-sync` recently gained a `no-std` feature, it didn't actually work, as there were still dangling references to `std` and prelude assumptions. This makes `rapid-gossip-sync` build (and test) properly in `no-std`. --- lightning-rapid-gossip-sync/Cargo.toml | 2 +- lightning-rapid-gossip-sync/src/error.rs | 8 ++++---- lightning-rapid-gossip-sync/src/lib.rs | 6 ++++++ lightning-rapid-gossip-sync/src/processing.rs | 9 ++++++--- 4 files changed, 17 insertions(+), 8 deletions(-) diff --git a/lightning-rapid-gossip-sync/Cargo.toml b/lightning-rapid-gossip-sync/Cargo.toml index 2fa598dc1..4dec0aa85 100644 --- a/lightning-rapid-gossip-sync/Cargo.toml +++ b/lightning-rapid-gossip-sync/Cargo.toml @@ -16,7 +16,7 @@ std = ["lightning/std"] _bench_unstable = [] [dependencies] -lightning = { version = "0.0.111", path = "../lightning" } +lightning = { version = "0.0.111", path = "../lightning", default-features = false } bitcoin = { version = "0.29.0", default-features = false } [dev-dependencies] diff --git a/lightning-rapid-gossip-sync/src/error.rs b/lightning-rapid-gossip-sync/src/error.rs index fee8feafc..ffd6760f8 100644 --- a/lightning-rapid-gossip-sync/src/error.rs +++ b/lightning-rapid-gossip-sync/src/error.rs @@ -1,5 +1,5 @@ use core::fmt::Debug; -use std::fmt::Formatter; +use core::fmt::Formatter; use lightning::ln::msgs::{DecodeError, LightningError}; /// All-encompassing standard error type that processing can return @@ -12,8 +12,8 @@ pub enum GraphSyncError { LightningError(LightningError), } -impl From for GraphSyncError { - fn from(error: std::io::Error) -> Self { +impl From for GraphSyncError { + fn from(error: lightning::io::Error) -> Self { Self::DecodeError(DecodeError::Io(error.kind())) } } @@ -31,7 +31,7 @@ impl From for GraphSyncError { } impl Debug for GraphSyncError { - fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result { match self { GraphSyncError::DecodeError(e) => f.write_fmt(format_args!("DecodeError: {:?}", e)), GraphSyncError::LightningError(e) => f.write_fmt(format_args!("LightningError: {:?}", e)) diff --git a/lightning-rapid-gossip-sync/src/lib.rs b/lightning-rapid-gossip-sync/src/lib.rs index eb6e28571..b3d1f0133 100644 --- a/lightning-rapid-gossip-sync/src/lib.rs +++ b/lightning-rapid-gossip-sync/src/lib.rs @@ -60,11 +60,16 @@ //! ``` //! [sync_network_graph_with_file_path]: RapidGossipSync::sync_network_graph_with_file_path +#![cfg_attr(all(not(feature = "std"), not(test)), no_std)] + // Allow and import test features for benching #![cfg_attr(all(test, feature = "_bench_unstable"), feature(test))] #[cfg(all(test, feature = "_bench_unstable"))] extern crate test; +#[cfg(not(feature = "std"))] +extern crate alloc; + #[cfg(feature = "std")] use std::fs::File; use core::ops::Deref; @@ -143,6 +148,7 @@ impl>, L: Deref> RapidGossipSync where L } } +#[cfg(feature = "std")] #[cfg(test)] mod tests { use std::fs; diff --git a/lightning-rapid-gossip-sync/src/processing.rs b/lightning-rapid-gossip-sync/src/processing.rs index 18f991631..3a60b7c98 100644 --- a/lightning-rapid-gossip-sync/src/processing.rs +++ b/lightning-rapid-gossip-sync/src/processing.rs @@ -16,6 +16,9 @@ use lightning::io; use crate::error::GraphSyncError; use crate::RapidGossipSync; +#[cfg(not(feature = "std"))] +use alloc::{vec::Vec, borrow::ToOwned}; + /// The purpose of this prefix is to identify the serialization format, should other rapid gossip /// sync formats arise in the future. /// @@ -47,7 +50,7 @@ impl>, L: Deref> RapidGossipSync where L let backdated_timestamp = latest_seen_timestamp.saturating_sub(24 * 3600 * 7); let node_id_count: u32 = Readable::read(read_cursor)?; - let mut node_ids: Vec = Vec::with_capacity(std::cmp::min( + let mut node_ids: Vec = Vec::with_capacity(core::cmp::min( node_id_count, MAX_INITIAL_NODE_ID_VECTOR_CAPACITY, ) as usize); @@ -132,7 +135,7 @@ impl>, L: Deref> RapidGossipSync where L htlc_maximum_msat: default_htlc_maximum_msat, fee_base_msat: default_fee_base_msat, fee_proportional_millionths: default_fee_proportional_millionths, - excess_data: vec![], + excess_data: Vec::new(), } } else { // incremental update, field flags will indicate mutated values @@ -162,7 +165,7 @@ impl>, L: Deref> RapidGossipSync where L htlc_maximum_msat: directional_info.htlc_maximum_msat, fee_base_msat: directional_info.fees.base_msat, fee_proportional_millionths: directional_info.fees.proportional_millionths, - excess_data: vec![], + excess_data: Vec::new(), } }; From 3852d528018f66eaf87dc846d919228e8339248b Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 6 Oct 2022 19:38:17 +0000 Subject: [PATCH 2/5] Update `rapid-gossip-sync` docs to not reference `std`-only methods --- lightning-rapid-gossip-sync/src/lib.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lightning-rapid-gossip-sync/src/lib.rs b/lightning-rapid-gossip-sync/src/lib.rs index b3d1f0133..06ce7eb20 100644 --- a/lightning-rapid-gossip-sync/src/lib.rs +++ b/lightning-rapid-gossip-sync/src/lib.rs @@ -38,7 +38,7 @@ //! //! After the gossip data snapshot has been downloaded, one of the client's graph processing //! functions needs to be called. In this example, we process the update by reading its contents -//! from disk, which we do by calling [sync_network_graph_with_file_path]: +//! from disk, which we do by calling [`RapidGossipSync::update_network_graph`]: //! //! ``` //! use bitcoin::blockdata::constants::genesis_block; @@ -56,9 +56,9 @@ //! let block_hash = genesis_block(Network::Bitcoin).header.block_hash(); //! let network_graph = NetworkGraph::new(block_hash, &logger); //! let rapid_sync = RapidGossipSync::new(&network_graph); -//! let new_last_sync_timestamp_result = rapid_sync.sync_network_graph_with_file_path("./rapid_sync.lngossip"); +//! let snapshot_contents: &[u8] = &[0; 0]; +//! let new_last_sync_timestamp_result = rapid_sync.update_network_graph(snapshot_contents); //! ``` -//! [sync_network_graph_with_file_path]: RapidGossipSync::sync_network_graph_with_file_path #![cfg_attr(all(not(feature = "std"), not(test)), no_std)] From e2e884725444e772140b47f0a4e36632dec3a261 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 6 Oct 2022 15:41:58 +0000 Subject: [PATCH 3/5] Test `rapid-gossip-sync` in `no-std` in CI --- .github/workflows/build.yml | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 49b857c39..a48ecc743 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -113,24 +113,19 @@ jobs: if: "matrix.build-no-std && !matrix.coverage" shell: bash # Default on Winblows is powershell run: | - cd lightning - 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 - # check that things still pass without grind_signatures - # note that outbound_commitment_test only runs in this mode, because of hardcoded signature values - cargo test --verbose --color always --no-default-features --features std - # check if there is a conflict between no-std and the c_bindings cfg - RUSTFLAGS="--cfg=c_bindings" cargo test --verbose --color always --no-default-features --features=no-std - cd .. - cd lightning-invoice - 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 - # check if there is a conflict between no-std and the c_bindings cfg - RUSTFLAGS="--cfg=c_bindings" cargo test --verbose --color always --no-default-features --features=no-std + for DIR in lightning lightning-invoice lightning-rapid-gossip-sync; do + cd $DIR + 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 + # check that things still pass without grind_signatures + # note that outbound_commitment_test only runs in this mode, because of hardcoded signature values + cargo test --verbose --color always --no-default-features --features std + # check if there is a conflict between no-std and the c_bindings cfg + RUSTFLAGS="--cfg=c_bindings" cargo test --verbose --color always --no-default-features --features=no-std + cd .. + done # check no-std compatibility across dependencies - cd .. cd no-std-check cargo check --verbose --color always cd .. From 92963ebe521d51e3938295157107accea53f1a2a Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Thu, 6 Oct 2022 16:48:14 +0000 Subject: [PATCH 4/5] Support platforms with only 32-bit atomics Given there is only one instance in our code of `AtomicU64` its simplest to just remove it rather than try to add some kind of wrapper. --- lightning/src/ln/peer_handler.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/lightning/src/ln/peer_handler.rs b/lightning/src/ln/peer_handler.rs index d38afcbac..d1a9744ed 100644 --- a/lightning/src/ln/peer_handler.rs +++ b/lightning/src/ln/peer_handler.rs @@ -36,7 +36,7 @@ use prelude::*; use io; use alloc::collections::LinkedList; use sync::{Arc, Mutex, MutexGuard, FairRwLock}; -use core::sync::atomic::{AtomicBool, AtomicU64, Ordering}; +use core::sync::atomic::{AtomicBool, AtomicU32, Ordering}; use core::{cmp, hash, fmt, mem}; use core::ops::Deref; use core::convert::Infallible; @@ -540,7 +540,7 @@ pub struct PeerManager PeerManager Self { + pub fn new_channel_only(channel_message_handler: CM, onion_message_handler: OM, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L) -> Self { Self::new(MessageHandler { chan_handler: channel_message_handler, route_handler: IgnoringMessageHandler{}, @@ -620,7 +620,7 @@ impl PeerManager Self { + pub fn new_routing_only(routing_message_handler: RM, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L) -> Self { Self::new(MessageHandler { chan_handler: ErroringMessageHandler::new(), route_handler: routing_message_handler, @@ -684,7 +684,7 @@ impl, our_node_secret: SecretKey, current_time: u64, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self { + pub fn new(message_handler: MessageHandler, our_node_secret: SecretKey, current_time: u32, ephemeral_random_data: &[u8; 32], logger: L, custom_message_handler: CMH) -> Self { let mut ephemeral_key_midstate = Sha256::engine(); ephemeral_key_midstate.input(ephemeral_random_data); @@ -701,7 +701,7 @@ impl Date: Thu, 6 Oct 2022 15:44:03 +0000 Subject: [PATCH 5/5] Test a full `no-std` build in the `no-std-check` crate in CI Rust is incredibly forgiving in attempts to access `std`, making it rather difficult to test `no-std` properly. In practice, the only decent way to do so is to actually build for a platform that does not have `std`, which we do here by building the `no-std-check` crate for `arm-thumbv7m-none-eabi`. --- .github/workflows/build.yml | 8 +++++++- no-std-check/src/lib.rs | 1 + 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index a48ecc743..799d22a64 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -128,7 +128,13 @@ jobs: # check no-std compatibility across dependencies cd no-std-check cargo check --verbose --color always - cd .. + - name: Build no-std-check on Rust ${{ matrix.toolchain }} for ARM Embedded + if: "matrix.build-no-std && matrix.platform == 'ubuntu-latest'" + run: | + cd no-std-check + rustup target add thumbv7m-none-eabi + sudo apt-get -y install gcc-arm-none-eabi + cargo build --target=thumbv7m-none-eabi - name: Test on no-std builds Rust ${{ matrix.toolchain }} and full code-linking for coverage generation if: "matrix.build-no-std && matrix.coverage" run: | diff --git a/no-std-check/src/lib.rs b/no-std-check/src/lib.rs index e69de29bb..0c9ac1ac8 100644 --- a/no-std-check/src/lib.rs +++ b/no-std-check/src/lib.rs @@ -0,0 +1 @@ +#![no_std]