Skip to content

Commit

Permalink
Merge pull request #2426 from TheBlueMatt/2023-07-proc-macro2-msrv
Browse files Browse the repository at this point in the history
  • Loading branch information
wpaulino committed Jul 19, 2023
2 parents c5c5f3f + f38b80a commit 2e86a59
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 28 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ exclude = [
"lightning-custom-message",
"lightning-transaction-sync",
"no-std-check",
"msrv-no-dev-deps-check",
"bench",
]

Expand Down
42 changes: 34 additions & 8 deletions ci/ci-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,18 +4,33 @@ set -eox pipefail
RUSTC_MINOR_VERSION=$(rustc --version | awk '{ split($2,a,"."); print a[2] }')
HOST_PLATFORM="$(rustc --version --verbose | grep "host:" | awk '{ print $2 }')"

# Tokio MSRV on versions 1.17 through 1.26 is rustc 1.49. Above 1.26 MSRV is 1.56.
[ "$RUSTC_MINOR_VERSION" -lt 49 ] && cargo update -p tokio --precise "1.14.1" --verbose
[[ "$RUSTC_MINOR_VERSION" -gt 48 && "$RUSTC_MINOR_VERSION" -lt 56 ]] && cargo update -p tokio --precise "1.25.1" --verbose
# Some crates require pinning to meet our MSRV even for our downstream users,
# which we do here.
# Further crates which appear only as dev-dependencies are pinned further down.
function PIN_RELEASE_DEPS {
# Tokio MSRV on versions 1.17 through 1.26 is rustc 1.49. Above 1.26 MSRV is 1.56.
[ "$RUSTC_MINOR_VERSION" -lt 49 ] && cargo update -p tokio --precise "1.14.1" --verbose
[[ "$RUSTC_MINOR_VERSION" -gt 48 && "$RUSTC_MINOR_VERSION" -lt 56 ]] && cargo update -p tokio --precise "1.25.1" --verbose

# Sadly the log crate is always a dependency of tokio until 1.20, and has no reasonable MSRV guarantees
[ "$RUSTC_MINOR_VERSION" -lt 49 ] && cargo update -p log --precise "0.4.18" --verbose
# Sadly the log crate is always a dependency of tokio until 1.20, and has no reasonable MSRV guarantees
[ "$RUSTC_MINOR_VERSION" -lt 49 ] && cargo update -p log --precise "0.4.18" --verbose

# The serde_json crate switched to Rust edition 2021 starting with v1.0.101, i.e., has MSRV of 1.56
[ "$RUSTC_MINOR_VERSION" -lt 56 ] && cargo update -p serde_json --precise "1.0.100" --verbose

return 0 # Don't fail the script if our rustc is higher than the last check
}

PIN_RELEASE_DEPS # pin the release dependencies in our main workspace

# The addr2line v0.20 crate (a dependency of `backtrace` starting with 0.3.68) relies on 1.55+
[ "$RUSTC_MINOR_VERSION" -lt 55 ] && cargo update -p backtrace --precise "0.3.67" --verbose

# The serde_json crate switched to Rust edition 2021 starting with v1.0.101, i.e., has MSRV of 1.56
[ "$RUSTC_MINOR_VERSION" -lt 56 ] && cargo update -p serde_json --precise "1.0.100" --verbose
# The quote crate switched to Rust edition 2021 starting with v1.0.31, i.e., has MSRV of 1.56
[ "$RUSTC_MINOR_VERSION" -lt 56 ] && cargo update -p quote --precise "1.0.30" --verbose

# The proc-macro2 crate switched to Rust edition 2021 starting with v1.0.66, i.e., has MSRV of 1.56
[ "$RUSTC_MINOR_VERSION" -lt 56 ] && cargo update -p proc-macro2 --precise "1.0.65" --verbose

[ "$LDK_COVERAGE_BUILD" != "" ] && export RUSTFLAGS="-C link-dead-code"

Expand Down Expand Up @@ -62,7 +77,18 @@ popd
echo -e "\n\nTesting no-std build on a downstream no-std crate"
# check no-std compatibility across dependencies
pushd no-std-check
cargo check --verbose --color always --features lightning-transaction-sync
if [[ $RUSTC_MINOR_VERSION -gt 67 ]]; then
# lightning-transaction-sync's MSRV is 1.67
cargo check --verbose --color always --features lightning-transaction-sync
else
cargo check --verbose --color always
fi
popd

# Test that we can build downstream code with only the "release pins".
pushd msrv-no-dev-deps-check
PIN_RELEASE_DEPS
cargo check
popd

if [ -f "$(which arm-none-eabi-gcc)" ]; then
Expand Down
2 changes: 1 addition & 1 deletion lightning-net-tokio/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ rustdoc-args = ["--cfg", "docsrs"]
[dependencies]
bitcoin = "0.29.0"
lightning = { version = "0.0.116-rc1", path = "../lightning" }
tokio = { version = "1.0", features = [ "io-util", "macros", "rt", "sync", "net", "time" ] }
tokio = { version = "1.0", features = [ "io-util", "rt", "sync", "net", "time" ] }

[dev-dependencies]
tokio = { version = "1.14", features = [ "io-util", "macros", "rt", "rt-multi-thread", "sync", "net", "time" ] }
Expand Down
116 changes: 97 additions & 19 deletions lightning-net-tokio/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,16 +42,79 @@ use lightning::ln::peer_handler::APeerManager;
use lightning::ln::msgs::NetAddress;

use std::ops::Deref;
use std::task;
use std::task::{self, Poll};
use std::future::Future;
use std::net::SocketAddr;
use std::net::TcpStream as StdTcpStream;
use std::sync::{Arc, Mutex};
use std::sync::atomic::{AtomicU64, Ordering};
use std::time::Duration;
use std::pin::Pin;
use std::hash::Hash;

static ID_COUNTER: AtomicU64 = AtomicU64::new(0);

// We only need to select over multiple futures in one place, and taking on the full `tokio/macros`
// dependency tree in order to do so (which has broken our MSRV before) is excessive. Instead, we
// define a trivial two- and three- select macro with the specific types we need and just use that.

pub(crate) enum SelectorOutput {
A(Option<()>), B(Option<()>), C(tokio::io::Result<usize>),
}

pub(crate) struct TwoSelector<
A: Future<Output=Option<()>> + Unpin, B: Future<Output=Option<()>> + Unpin
> {
pub a: A,
pub b: B,
}

impl<
A: Future<Output=Option<()>> + Unpin, B: Future<Output=Option<()>> + Unpin
> Future for TwoSelector<A, B> {
type Output = SelectorOutput;
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> Poll<SelectorOutput> {
match Pin::new(&mut self.a).poll(ctx) {
Poll::Ready(res) => { return Poll::Ready(SelectorOutput::A(res)); },
Poll::Pending => {},
}
match Pin::new(&mut self.b).poll(ctx) {
Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); },
Poll::Pending => {},
}
Poll::Pending
}
}

pub(crate) struct ThreeSelector<
A: Future<Output=Option<()>> + Unpin, B: Future<Output=Option<()>> + Unpin, C: Future<Output=tokio::io::Result<usize>> + Unpin
> {
pub a: A,
pub b: B,
pub c: C,
}

impl<
A: Future<Output=Option<()>> + Unpin, B: Future<Output=Option<()>> + Unpin, C: Future<Output=tokio::io::Result<usize>> + Unpin
> Future for ThreeSelector<A, B, C> {
type Output = SelectorOutput;
fn poll(mut self: Pin<&mut Self>, ctx: &mut task::Context<'_>) -> Poll<SelectorOutput> {
match Pin::new(&mut self.a).poll(ctx) {
Poll::Ready(res) => { return Poll::Ready(SelectorOutput::A(res)); },
Poll::Pending => {},
}
match Pin::new(&mut self.b).poll(ctx) {
Poll::Ready(res) => { return Poll::Ready(SelectorOutput::B(res)); },
Poll::Pending => {},
}
match Pin::new(&mut self.c).poll(ctx) {
Poll::Ready(res) => { return Poll::Ready(SelectorOutput::C(res)); },
Poll::Pending => {},
}
Poll::Pending
}
}

/// Connection contains all our internal state for a connection - we hold a reference to the
/// Connection object (in an Arc<Mutex<>>) in each SocketDescriptor we create as well as in the
/// read future (which is returned by schedule_read).
Expand Down Expand Up @@ -127,29 +190,44 @@ impl Connection {
}
us_lock.read_paused
};
tokio::select! {
v = write_avail_receiver.recv() => {
// TODO: Drop the Box'ing of the futures once Rust has pin-on-stack support.
let select_result = if read_paused {
TwoSelector {
a: Box::pin(write_avail_receiver.recv()),
b: Box::pin(read_wake_receiver.recv()),
}.await
} else {
ThreeSelector {
a: Box::pin(write_avail_receiver.recv()),
b: Box::pin(read_wake_receiver.recv()),
c: Box::pin(reader.read(&mut buf)),
}.await
};
match select_result {
SelectorOutput::A(v) => {
assert!(v.is_some()); // We can't have dropped the sending end, its in the us Arc!
if peer_manager.as_ref().write_buffer_space_avail(&mut our_descriptor).is_err() {
break Disconnect::CloseConnection;
}
},
_ = read_wake_receiver.recv() => {},
read = reader.read(&mut buf), if !read_paused => match read {
Ok(0) => break Disconnect::PeerDisconnected,
Ok(len) => {
let read_res = peer_manager.as_ref().read_event(&mut our_descriptor, &buf[0..len]);
let mut us_lock = us.lock().unwrap();
match read_res {
Ok(pause_read) => {
if pause_read {
us_lock.read_paused = true;
}
},
Err(_) => break Disconnect::CloseConnection,
}
},
Err(_) => break Disconnect::PeerDisconnected,
SelectorOutput::B(_) => {},
SelectorOutput::C(read) => {
match read {
Ok(0) => break Disconnect::PeerDisconnected,
Ok(len) => {
let read_res = peer_manager.as_ref().read_event(&mut our_descriptor, &buf[0..len]);
let mut us_lock = us.lock().unwrap();
match read_res {
Ok(pause_read) => {
if pause_read {
us_lock.read_paused = true;
}
},
Err(_) => break Disconnect::CloseConnection,
}
},
Err(_) => break Disconnect::PeerDisconnected,
}
},
}
let _ = event_waker.try_send(());
Expand Down
13 changes: 13 additions & 0 deletions msrv-no-dev-deps-check/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
[package]
name = "msrv-check"
version = "0.1.0"
edition = "2018"

[dependencies]
lightning = { path = "../lightning" }
lightning-block-sync = { path = "../lightning-block-sync", features = [ "rest-client", "rpc-client" ] }
lightning-invoice = { path = "../lightning-invoice" }
lightning-net-tokio = { path = "../lightning-net-tokio" }
lightning-persister = { path = "../lightning-persister" }
lightning-background-processor = { path = "../lightning-background-processor", features = ["futures"] }
lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync" }
Empty file.

0 comments on commit 2e86a59

Please sign in to comment.