Skip to content

Commit 1070c6d

Browse files
authored
Merge branch 'main' into handshake-1
2 parents 4a2cbf5 + d29ae18 commit 1070c6d

35 files changed

+3244
-1204
lines changed

.github/dependabot.yml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
2+
3+
version: 2
4+
updates:
5+
- package-ecosystem: "cargo"
6+
directory: "/"
7+
schedule:
8+
interval: "daily"
9+
- package-ecosystem: "cargo"
10+
directory: "/lightning-background-processor"
11+
schedule:
12+
interval: "daily"
13+
- package-ecosystem: "cargo"
14+
directory: "/lightning-block-sync"
15+
schedule:
16+
interval: "daily"
17+
- package-ecosystem: "cargo"
18+
directory: "/lightning-invoice"
19+
schedule:
20+
interval: "daily"
21+
- package-ecosystem: "cargo"
22+
directory: "/lightning-net-tokio"
23+
schedule:
24+
interval: "daily"
25+
- package-ecosystem: "cargo"
26+
directory: "/lightning-persister"
27+
schedule:
28+
interval: "daily"
29+
- package-ecosystem: "cargo"
30+
directory: "/lightning"
31+
schedule:
32+
interval: "daily"
33+
- package-ecosystem: "github-actions"
34+
directory: "/"
35+
schedule:
36+
interval: "daily"

.github/workflows/build.yml

+4
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,10 @@ jobs:
101101
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client
102102
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client
103103
RUSTFLAGS="-C link-dead-code" cargo build --verbose --color always --features rpc-client,rest-client,tokio
104+
- name: Test backtrace-debug builds on Rust ${{ matrix.toolchain }}
105+
if: "matrix.build-no-std"
106+
run: |
107+
cd lightning && cargo test --verbose --color always --features backtrace
104108
- name: Test on Rust ${{ matrix.toolchain }} with net-tokio
105109
if: "matrix.build-net-tokio && !matrix.coverage"
106110
run: cargo test --verbose --color always

README.md

+18
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,24 @@ production-worthy implementation in 2021.
3333
Communications for Rust-Lightning and Lightning Development Kit happens through
3434
[LDK slack](http://lightningdevkit.org/).
3535

36+
Crates
37+
-----------
38+
1. [lightning](./lightning)
39+
The Core of the LDK library, implements the lightning protocol, channel state machine,
40+
and on-chain logic. Supports no-std and exposes on relatively low-level interfaces.
41+
2. [lightning-background-processor](./lightning-background-processor)
42+
Utilities to perform required background tasks for Rust Lightning.
43+
3. [lightning-block-sync](./lightning-block-sync)
44+
Utilities to fetch the chain data from a block source and feed them into Rust Lightning.
45+
4. [lightning-invoice](./lightning-invoice)
46+
Data structures to parse and serialize BOLT11 lightning invoices.
47+
5. [lightning-net-tokio](./lightning-net-tokio)
48+
Implementation of the rust-lightning network stack using Tokio.
49+
For Rust-Lightning clients which wish to make direct connections to Lightning P2P nodes,
50+
this is a simple alternative to implementing the required network stack, especially for those already using Tokio.
51+
6. [lightning-persister](./lightning-persister)
52+
Utilities to manage Rust-Lightning channel data persistence and retrieval.
53+
3654
About
3755
-----------
3856
LDK/Rust-Lightning is a generic library which allows you to build a lightning

fuzz/src/chanmon_consistency.rs

+6-4
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ use std::collections::{HashSet, hash_map, HashMap};
6363
use std::sync::{Arc,Mutex};
6464
use std::sync::atomic;
6565
use std::io::Cursor;
66+
use bitcoin::bech32::u5;
6667

6768
const MAX_FEE: u32 = 10_000;
6869
struct FuzzEstimator {
@@ -187,6 +188,7 @@ impl KeysInterface for KeyProvider {
187188
let id = self.rand_bytes_id.fetch_add(1, atomic::Ordering::Relaxed);
188189
let keys = InMemorySigner::new(
189190
&secp_ctx,
191+
self.get_node_secret(),
190192
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, self.node_id]).unwrap(),
191193
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 5, self.node_id]).unwrap(),
192194
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, self.node_id]).unwrap(),
@@ -210,7 +212,7 @@ impl KeysInterface for KeyProvider {
210212
fn read_chan_signer(&self, buffer: &[u8]) -> Result<Self::Signer, DecodeError> {
211213
let mut reader = std::io::Cursor::new(buffer);
212214

213-
let inner: InMemorySigner = Readable::read(&mut reader)?;
215+
let inner: InMemorySigner = ReadableArgs::read(&mut reader, self.get_node_secret())?;
214216
let state = self.make_enforcement_state_cell(inner.commitment_seed);
215217

216218
Ok(EnforcingSigner {
@@ -220,7 +222,7 @@ impl KeysInterface for KeyProvider {
220222
})
221223
}
222224

223-
fn sign_invoice(&self, _invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {
225+
fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
224226
unreachable!()
225227
}
226228
}
@@ -308,7 +310,7 @@ fn send_payment(source: &ChanMan, dest: &ChanMan, dest_chan_id: u64, amt: u64, p
308310
fee_msat: amt,
309311
cltv_expiry_delta: 200,
310312
}]],
311-
payee: None,
313+
payment_params: None,
312314
}, payment_hash, &Some(payment_secret)) {
313315
check_payment_err(err);
314316
false
@@ -334,7 +336,7 @@ fn send_hop_payment(source: &ChanMan, middle: &ChanMan, middle_chan_id: u64, des
334336
fee_msat: amt,
335337
cltv_expiry_delta: 200,
336338
}]],
337-
payee: None,
339+
payment_params: None,
338340
}, payment_hash, &Some(payment_secret)) {
339341
check_payment_err(err);
340342
false

fuzz/src/full_stack.rs

+13-10
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,14 @@ use lightning::ln::peer_handler::{MessageHandler,PeerManager,SocketDescriptor,Ig
3838
use lightning::ln::msgs::DecodeError;
3939
use lightning::ln::script::ShutdownScript;
4040
use lightning::routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
41-
use lightning::routing::router::{find_route, Payee, RouteParameters};
42-
use lightning::routing::scoring::Scorer;
41+
use lightning::routing::router::{find_route, PaymentParameters, RouteParameters};
42+
use lightning::routing::scoring::FixedPenaltyScorer;
4343
use lightning::util::config::UserConfig;
4444
use lightning::util::errors::APIError;
4545
use lightning::util::events::Event;
4646
use lightning::util::enforcing_trait_impls::{EnforcingSigner, EnforcementState};
4747
use lightning::util::logger::Logger;
48-
use lightning::util::ser::Readable;
48+
use lightning::util::ser::ReadableArgs;
4949

5050
use utils::test_logger;
5151
use utils::test_persister::TestPersister;
@@ -60,6 +60,7 @@ use std::convert::TryInto;
6060
use std::cmp;
6161
use std::sync::{Arc, Mutex};
6262
use std::sync::atomic::{AtomicU64,AtomicUsize,Ordering};
63+
use bitcoin::bech32::u5;
6364

6465
#[inline]
6566
pub fn slice_to_be16(v: &[u8]) -> u16 {
@@ -292,6 +293,7 @@ impl KeysInterface for KeyProvider {
292293
EnforcingSigner::new(if inbound {
293294
InMemorySigner::new(
294295
&secp_ctx,
296+
self.node_secret.clone(),
295297
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, ctr]).unwrap(),
296298
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, ctr]).unwrap(),
297299
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, ctr]).unwrap(),
@@ -304,6 +306,7 @@ impl KeysInterface for KeyProvider {
304306
} else {
305307
InMemorySigner::new(
306308
&secp_ctx,
309+
self.node_secret.clone(),
307310
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 7, ctr]).unwrap(),
308311
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, ctr]).unwrap(),
309312
SecretKey::from_slice(&[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, ctr]).unwrap(),
@@ -323,7 +326,7 @@ impl KeysInterface for KeyProvider {
323326
}
324327

325328
fn read_chan_signer(&self, mut data: &[u8]) -> Result<EnforcingSigner, DecodeError> {
326-
let inner: InMemorySigner = Readable::read(&mut data)?;
329+
let inner: InMemorySigner = ReadableArgs::read(&mut data, self.node_secret.clone())?;
327330
let state = Arc::new(Mutex::new(EnforcementState::new()));
328331

329332
Ok(EnforcingSigner::new_with_revoked(
@@ -333,7 +336,7 @@ impl KeysInterface for KeyProvider {
333336
))
334337
}
335338

336-
fn sign_invoice(&self, _invoice_preimage: Vec<u8>) -> Result<RecoverableSignature, ()> {
339+
fn sign_invoice(&self, _hrp_bytes: &[u8], _invoice_data: &[u5]) -> Result<RecoverableSignature, ()> {
337340
unreachable!()
338341
}
339342
}
@@ -390,7 +393,7 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
390393
let our_id = PublicKey::from_secret_key(&Secp256k1::signing_only(), &keys_manager.get_node_secret());
391394
let network_graph = Arc::new(NetworkGraph::new(genesis_block(network).block_hash()));
392395
let net_graph_msg_handler = Arc::new(NetGraphMsgHandler::new(Arc::clone(&network_graph), None, Arc::clone(&logger)));
393-
let scorer = Scorer::with_fixed_penalty(0);
396+
let scorer = FixedPenaltyScorer::with_penalty(0);
394397

395398
let peers = RefCell::new([false; 256]);
396399
let mut loss_detector = MoneyLossDetector::new(&peers, channelmanager.clone(), monitor.clone(), PeerManager::new(MessageHandler {
@@ -446,9 +449,9 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
446449
},
447450
4 => {
448451
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
449-
let payee = Payee::from_node_id(get_pubkey!());
452+
let payment_params = PaymentParameters::from_node_id(get_pubkey!());
450453
let params = RouteParameters {
451-
payee,
454+
payment_params,
452455
final_value_msat,
453456
final_cltv_expiry_delta: 42,
454457
};
@@ -469,9 +472,9 @@ pub fn do_test(data: &[u8], logger: &Arc<dyn Logger>) {
469472
},
470473
15 => {
471474
let final_value_msat = slice_to_be24(get_slice!(3)) as u64;
472-
let payee = Payee::from_node_id(get_pubkey!());
475+
let payment_params = PaymentParameters::from_node_id(get_pubkey!());
473476
let params = RouteParameters {
474-
payee,
477+
payment_params,
475478
final_value_msat,
476479
final_cltv_expiry_delta: 42,
477480
};

fuzz/src/router.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ use lightning::chain::transaction::OutPoint;
1616
use lightning::ln::channelmanager::{ChannelDetails, ChannelCounterparty};
1717
use lightning::ln::features::InitFeatures;
1818
use lightning::ln::msgs;
19-
use lightning::routing::router::{find_route, Payee, RouteHint, RouteHintHop, RouteParameters};
20-
use lightning::routing::scoring::Scorer;
19+
use lightning::routing::router::{find_route, PaymentParameters, RouteHint, RouteHintHop, RouteParameters};
20+
use lightning::routing::scoring::FixedPenaltyScorer;
2121
use lightning::util::logger::Logger;
2222
use lightning::util::ser::Readable;
2323
use lightning::routing::network_graph::{NetworkGraph, RoutingFees};
@@ -249,14 +249,14 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
249249
}]));
250250
}
251251
}
252-
let scorer = Scorer::with_fixed_penalty(0);
252+
let scorer = FixedPenaltyScorer::with_penalty(0);
253253
for target in node_pks.iter() {
254-
let params = RouteParameters {
255-
payee: Payee::from_node_id(*target).with_route_hints(last_hops.clone()),
254+
let route_params = RouteParameters {
255+
payment_params: PaymentParameters::from_node_id(*target).with_route_hints(last_hops.clone()),
256256
final_value_msat: slice_to_be64(get_slice!(8)),
257257
final_cltv_expiry_delta: slice_to_be32(get_slice!(4)),
258258
};
259-
let _ = find_route(&our_pubkey, &params, &net_graph,
259+
let _ = find_route(&our_pubkey, &route_params, &net_graph,
260260
first_hops.map(|c| c.iter().collect::<Vec<_>>()).as_ref().map(|a| a.as_slice()),
261261
Arc::clone(&logger), &scorer);
262262
}

lightning-background-processor/src/lib.rs

+24-9
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ const FRESHNESS_TIMER: u64 = 60;
6161
const FRESHNESS_TIMER: u64 = 1;
6262

6363
#[cfg(all(not(test), not(debug_assertions)))]
64-
const PING_TIMER: u64 = 5;
64+
const PING_TIMER: u64 = 10;
6565
/// Signature operations take a lot longer without compiler optimisations.
6666
/// Increasing the ping timer allows for this but slower devices will be disconnected if the
6767
/// timeout is reached.
@@ -219,11 +219,17 @@ impl BackgroundProcessor {
219219
let mut have_pruned = false;
220220

221221
loop {
222-
peer_manager.process_events();
222+
peer_manager.process_events(); // Note that this may block on ChannelManager's locking
223223
channel_manager.process_pending_events(&event_handler);
224224
chain_monitor.process_pending_events(&event_handler);
225+
226+
// We wait up to 100ms, but track how long it takes to detect being put to sleep,
227+
// see `await_start`'s use below.
228+
let await_start = Instant::now();
225229
let updates_available =
226230
channel_manager.await_persistable_update_timeout(Duration::from_millis(100));
231+
let await_time = await_start.elapsed();
232+
227233
if updates_available {
228234
log_trace!(logger, "Persisting ChannelManager...");
229235
persister.persist_manager(&*channel_manager)?;
@@ -232,22 +238,27 @@ impl BackgroundProcessor {
232238
// Exit the loop if the background processor was requested to stop.
233239
if stop_thread.load(Ordering::Acquire) == true {
234240
log_trace!(logger, "Terminating background processor.");
235-
return Ok(());
241+
break;
236242
}
237243
if last_freshness_call.elapsed().as_secs() > FRESHNESS_TIMER {
238244
log_trace!(logger, "Calling ChannelManager's timer_tick_occurred");
239245
channel_manager.timer_tick_occurred();
240246
last_freshness_call = Instant::now();
241247
}
242-
if last_ping_call.elapsed().as_secs() > PING_TIMER * 2 {
248+
if await_time > Duration::from_secs(1) {
243249
// On various platforms, we may be starved of CPU cycles for several reasons.
244250
// E.g. on iOS, if we've been in the background, we will be entirely paused.
245251
// Similarly, if we're on a desktop platform and the device has been asleep, we
246252
// may not get any cycles.
247-
// In any case, if we've been entirely paused for more than double our ping
248-
// timer, we should have disconnected all sockets by now (and they're probably
249-
// dead anyway), so disconnect them by calling `timer_tick_occurred()` twice.
250-
log_trace!(logger, "Awoke after more than double our ping timer, disconnecting peers.");
253+
// We detect this by checking if our max-100ms-sleep, above, ran longer than a
254+
// full second, at which point we assume sockets may have been killed (they
255+
// appear to be at least on some platforms, even if it has only been a second).
256+
// Note that we have to take care to not get here just because user event
257+
// processing was slow at the top of the loop. For example, the sample client
258+
// may call Bitcoin Core RPCs during event handling, which very often takes
259+
// more than a handful of seconds to complete, and shouldn't disconnect all our
260+
// peers.
261+
log_trace!(logger, "100ms sleep took more than a second, disconnecting peers.");
251262
peer_manager.disconnect_all_peers();
252263
last_ping_call = Instant::now();
253264
} else if last_ping_call.elapsed().as_secs() > PING_TIMER {
@@ -269,6 +280,10 @@ impl BackgroundProcessor {
269280
}
270281
}
271282
}
283+
// After we exit, ensure we persist the ChannelManager one final time - this avoids
284+
// some races where users quit while channel updates were in-flight, with
285+
// ChannelMonitor update(s) persisted without a corresponding ChannelManager update.
286+
persister.persist_manager(&*channel_manager)
272287
});
273288
Self { stop_thread: stop_thread_clone, thread_handle: Some(handle) }
274289
}
@@ -658,7 +673,7 @@ mod tests {
658673
let data_dir = nodes[0].persister.get_data_dir();
659674
let persister = move |node: &ChannelManager<InMemorySigner, Arc<ChainMonitor>, Arc<test_utils::TestBroadcaster>, Arc<KeysManager>, Arc<test_utils::TestFeeEstimator>, Arc<test_utils::TestLogger>>| FilesystemPersister::persist_manager(data_dir.clone(), node);
660675
let router = DefaultRouter::new(Arc::clone(&nodes[0].network_graph), Arc::clone(&nodes[0].logger));
661-
let scorer = Arc::new(Mutex::new(test_utils::TestScorer::default()));
676+
let scorer = Arc::new(Mutex::new(test_utils::TestScorer::with_penalty(0)));
662677
let invoice_payer = Arc::new(InvoicePayer::new(Arc::clone(&nodes[0].node), router, scorer, Arc::clone(&nodes[0].logger), |_: &_| {}, RetryAttempts(2)));
663678
let event_handler = Arc::clone(&invoice_payer);
664679
let bg_processor = BackgroundProcessor::start(persister, event_handler, nodes[0].chain_monitor.clone(), nodes[0].node.clone(), nodes[0].net_graph_msg_handler.clone(), nodes[0].peer_manager.clone(), nodes[0].logger.clone());

lightning-invoice/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,4 @@ core2 = { version = "0.3.0", default-features = false, optional = true }
2424

2525
[dev-dependencies]
2626
lightning = { version = "0.0.104", path = "../lightning", default-features = false, features = ["_test_utils"] }
27-
hex = "0.3"
27+
hex = "0.4"

lightning-invoice/src/de.rs

+3-8
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ use secp256k1::key::PublicKey;
2424

2525
use super::{Invoice, Sha256, TaggedField, ExpiryTime, MinFinalCltvExpiry, Fallback, PayeePubKey, InvoiceSignature, PositiveTimestamp,
2626
SemanticError, PrivateRoute, Description, RawTaggedField, Currency, RawHrp, SiPrefix, RawInvoice, constants, SignedRawInvoice,
27-
RawDataPart, CreationError, InvoiceFeatures};
27+
RawDataPart, InvoiceFeatures};
2828

2929
use self::hrp_sm::parse_hrp;
3030

@@ -359,7 +359,6 @@ impl FromBase32 for PositiveTimestamp {
359359
.expect("7*5bit < 64bit, no overflow possible");
360360
match PositiveTimestamp::from_unix_timestamp(timestamp) {
361361
Ok(t) => Ok(t),
362-
Err(CreationError::TimestampOutOfBounds) => Err(ParseError::TimestampOverflow),
363362
Err(_) => unreachable!(),
364363
}
365364
}
@@ -516,7 +515,7 @@ impl FromBase32 for ExpiryTime {
516515

517516
fn from_base32(field_data: &[u5]) -> Result<ExpiryTime, ParseError> {
518517
match parse_int_be::<u64, u5>(field_data, 32)
519-
.and_then(|t| ExpiryTime::from_seconds(t).ok()) // ok, since the only error is out of bounds
518+
.map(|t| ExpiryTime::from_seconds(t))
520519
{
521520
Some(t) => Ok(t),
522521
None => Err(ParseError::IntegerOverflowError),
@@ -646,7 +645,6 @@ pub enum ParseError {
646645
/// Not an error, but used internally to signal that a part of the invoice should be ignored
647646
/// according to BOLT11
648647
Skip,
649-
TimestampOverflow,
650648
}
651649

652650
/// Indicates that something went wrong while parsing or validating the invoice. Parsing errors
@@ -709,9 +707,6 @@ impl Display for ParseError {
709707
ParseError::Skip => {
710708
f.write_str("the tagged field has to be skipped because of an unexpected, but allowed property")
711709
},
712-
ParseError::TimestampOverflow => {
713-
f.write_str("the invoice's timestamp could not be represented as SystemTime")
714-
},
715710
}
716711
}
717712
}
@@ -877,7 +872,7 @@ mod test {
877872
use bech32::FromBase32;
878873

879874
let input = from_bech32("pu".as_bytes());
880-
let expected = Ok(ExpiryTime::from_seconds(60).unwrap());
875+
let expected = Ok(ExpiryTime::from_seconds(60));
881876
assert_eq!(ExpiryTime::from_base32(&input), expected);
882877

883878
let input_too_large = from_bech32("sqqqqqqqqqqqq".as_bytes());

0 commit comments

Comments
 (0)