Skip to content

Commit aff3ea1

Browse files
committedJan 29, 2025·
Merge tag 'v0.1.1' into 2024-12-0.1-bindings
v0.1.1 - Jan 28, 2025 - "Onchain Matters" API Updates =========== * A `ChannelManager::send_payment_with_route` was (re-)added, with semantics similar to `ChannelManager::send_payment` (rather than like the pre-0.1 `send_payent_with_route`, lightningdevkit#3534). * `RawBolt11Invoice::{to,from}_raw` were added (lightningdevkit#3549). Bug Fixes ========= * HTLCs which were forwarded where the inbound edge times out within the next three blocks will have the inbound HTLC failed backwards irrespective of the status of the outbound HTLC. This avoids the peer force-closing the channel (and claiming the inbound edge HTLC on-chain) even if we have not yet managed to claim the outbound edge on chain (lightningdevkit#3556). * On restart, replay of `Event::SpendableOutput`s could have caused `OutputSweeper` to generate double-spending transactions, making it unable to claim any delayed claims. This was resolved by retaining old claims for more than four weeks after they are claimed on-chain to detect replays (lightningdevkit#3559). * Fixed the additional feerate we will pay each time we RBF on-chain claims to match the Bitcoin Core policy (1 sat/vB) instead of 16 sats/vB (lightningdevkit#3457). * Fixed a cased where a custom `Router` which returns an invalid `Route`, provided to `ChannelManager`, can result in an outbound payment remaining pending forever despite no HTLCs being pending (lightningdevkit#3531). Security ======== 0.1.1 fixes a denial-of-service vulnerability allowing channel counterparties to cause force-closure of unrelated channels. * If a malicious channel counterparty force-closes a channel, broadcasting a revoked commitment transaction while the channel at closure time included multiple non-dust forwarded outbound HTLCs with identical payment hashes and amounts, failure to fail the HTLCs backwards could cause the channels on which we recieved the corresponding inbound HTLCs to be force-closed. Note that we'll receive, at a minimum, the malicious counterparty's reserve value when they broadcast the stale commitment (lightningdevkit#3556). Thanks to Matt Morehouse for reporting this issue.
2 parents 7e2c5ef + 940ca49 commit aff3ea1

23 files changed

+846
-353
lines changed
 

‎CHANGELOG.md

+36
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,39 @@
1+
# 0.1.1 - Jan 28, 2025 - "Onchain Matters"
2+
3+
## API Updates
4+
* A `ChannelManager::send_payment_with_route` was (re-)added, with semantics
5+
similar to `ChannelManager::send_payment` (rather than like the pre-0.1
6+
`send_payent_with_route`, #3534).
7+
* `RawBolt11Invoice::{to,from}_raw` were added (#3549).
8+
9+
## Bug Fixes
10+
* HTLCs which were forwarded where the inbound edge times out within the next
11+
three blocks will have the inbound HTLC failed backwards irrespective of the
12+
status of the outbound HTLC. This avoids the peer force-closing the channel
13+
(and claiming the inbound edge HTLC on-chain) even if we have not yet managed
14+
to claim the outbound edge on chain (#3556).
15+
* On restart, replay of `Event::SpendableOutput`s could have caused
16+
`OutputSweeper` to generate double-spending transactions, making it unable to
17+
claim any delayed claims. This was resolved by retaining old claims for more
18+
than four weeks after they are claimed on-chain to detect replays (#3559).
19+
* Fixed the additional feerate we will pay each time we RBF on-chain claims to
20+
match the Bitcoin Core policy (1 sat/vB) instead of 16 sats/vB (#3457).
21+
* Fixed a cased where a custom `Router` which returns an invalid `Route`,
22+
provided to `ChannelManager`, can result in an outbound payment remaining
23+
pending forever despite no HTLCs being pending (#3531).
24+
25+
## Security
26+
0.1.1 fixes a denial-of-service vulnerability allowing channel counterparties to
27+
cause force-closure of unrelated channels.
28+
* If a malicious channel counterparty force-closes a channel, broadcasting a
29+
revoked commitment transaction while the channel at closure time included
30+
multiple non-dust forwarded outbound HTLCs with identical payment hashes and
31+
amounts, failure to fail the HTLCs backwards could cause the channels on
32+
which we recieved the corresponding inbound HTLCs to be force-closed. Note
33+
that we'll receive, at a minimum, the malicious counterparty's reserve value
34+
when they broadcast the stale commitment (#3556). Thanks to Matt Morehouse for
35+
reporting this issue.
36+
137
# 0.1 - Jan 15, 2025 - "Human Readable Version Numbers"
238

339
The LDK 0.1 release represents an important milestone for the LDK project. While

‎fuzz/src/chanmon_consistency.rs

+10-20
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use lightning::ln::channel::FEE_SPIKE_BUFFER_FEE_INCREASE_MULTIPLE;
4848
use lightning::ln::channel_state::ChannelDetails;
4949
use lightning::ln::channelmanager::{
5050
ChainParameters, ChannelManager, ChannelManagerReadArgs, PaymentId, RecentPaymentDetails,
51+
RecipientOnionFields,
5152
};
5253
use lightning::ln::functional_test_utils::*;
5354
use lightning::ln::inbound_payment::ExpandedKey;
@@ -82,7 +83,6 @@ use bitcoin::secp256k1::{self, Message, PublicKey, Scalar, Secp256k1, SecretKey}
8283

8384
use lightning::io::Cursor;
8485
use std::cmp::{self, Ordering};
85-
use std::collections::VecDeque;
8686
use std::mem;
8787
use std::sync::atomic;
8888
use std::sync::{Arc, Mutex};
@@ -113,22 +113,14 @@ impl FeeEstimator for FuzzEstimator {
113113
}
114114
}
115115

116-
struct FuzzRouter {
117-
pub next_routes: Mutex<VecDeque<Route>>,
118-
}
116+
struct FuzzRouter {}
119117

120118
impl Router for FuzzRouter {
121119
fn find_route(
122120
&self, _payer: &PublicKey, _params: &RouteParameters,
123121
_first_hops: Option<&[&ChannelDetails]>, _inflight_htlcs: InFlightHtlcs,
124122
) -> Result<Route, msgs::LightningError> {
125-
if let Some(route) = self.next_routes.lock().unwrap().pop_front() {
126-
return Ok(route);
127-
}
128-
Err(msgs::LightningError {
129-
err: String::from("Not implemented"),
130-
action: msgs::ErrorAction::IgnoreError,
131-
})
123+
unreachable!()
132124
}
133125

134126
fn create_blinded_payment_paths<T: secp256k1::Signing + secp256k1::Verification>(
@@ -518,7 +510,7 @@ fn send_payment(
518510
PaymentParameters::from_node_id(source.get_our_node_id(), TEST_FINAL_CLTV),
519511
amt,
520512
);
521-
source.router.next_routes.lock().unwrap().push_back(Route {
513+
let route = Route {
522514
paths: vec![Path {
523515
hops: vec![RouteHop {
524516
pubkey: dest.get_our_node_id(),
@@ -532,11 +524,10 @@ fn send_payment(
532524
blinded_tail: None,
533525
}],
534526
route_params: Some(route_params.clone()),
535-
});
527+
};
536528
let onion = RecipientOnionFields::secret_only(payment_secret);
537529
let payment_id = PaymentId(payment_id);
538-
let res =
539-
source.send_payment(payment_hash, onion, payment_id, route_params, Retry::Attempts(0));
530+
let res = source.send_payment_with_route(route, payment_hash, onion, payment_id);
540531
match res {
541532
Err(err) => {
542533
panic!("Errored with {:?} on initial payment send", err);
@@ -592,7 +583,7 @@ fn send_hop_payment(
592583
PaymentParameters::from_node_id(source.get_our_node_id(), TEST_FINAL_CLTV),
593584
amt,
594585
);
595-
source.router.next_routes.lock().unwrap().push_back(Route {
586+
let route = Route {
596587
paths: vec![Path {
597588
hops: vec![
598589
RouteHop {
@@ -617,11 +608,10 @@ fn send_hop_payment(
617608
blinded_tail: None,
618609
}],
619610
route_params: Some(route_params.clone()),
620-
});
611+
};
621612
let onion = RecipientOnionFields::secret_only(payment_secret);
622613
let payment_id = PaymentId(payment_id);
623-
let res =
624-
source.send_payment(payment_hash, onion, payment_id, route_params, Retry::Attempts(0));
614+
let res = source.send_payment_with_route(route, payment_hash, onion, payment_id);
625615
match res {
626616
Err(err) => {
627617
panic!("Errored with {:?} on initial payment send", err);
@@ -640,7 +630,7 @@ fn send_hop_payment(
640630
pub fn do_test<Out: Output>(data: &[u8], underlying_out: Out, anchors: bool) {
641631
let out = SearchingOutput::new(underlying_out);
642632
let broadcast = Arc::new(TestBroadcaster {});
643-
let router = FuzzRouter { next_routes: Mutex::new(VecDeque::new()) };
633+
let router = FuzzRouter {};
644634

645635
macro_rules! make_node {
646636
($node_id: expr, $fee_estimator: expr) => {{

‎lightning-background-processor/src/lib.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -1092,7 +1092,7 @@ mod tests {
10921092
SCORER_PERSISTENCE_SECONDARY_NAMESPACE,
10931093
};
10941094
use lightning::util::ser::Writeable;
1095-
use lightning::util::sweep::{OutputSpendStatus, OutputSweeper};
1095+
use lightning::util::sweep::{OutputSpendStatus, OutputSweeper, PRUNE_DELAY_BLOCKS};
10961096
use lightning::util::test_utils;
10971097
use lightning::{get_event, get_event_msg};
10981098
use lightning_persister::fs_store::FilesystemStore;
@@ -2274,8 +2274,8 @@ mod tests {
22742274
}
22752275

22762276
// Check we stop tracking the spendable outputs when one of the txs reaches
2277-
// ANTI_REORG_DELAY confirmations.
2278-
confirm_transaction_depth(&mut nodes[0], &sweep_tx_0, ANTI_REORG_DELAY);
2277+
// PRUNE_DELAY_BLOCKS confirmations.
2278+
confirm_transaction_depth(&mut nodes[0], &sweep_tx_0, PRUNE_DELAY_BLOCKS);
22792279
assert_eq!(nodes[0].sweeper.tracked_spendable_outputs().len(), 0);
22802280

22812281
if !std::thread::panicking() {

‎lightning-invoice/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
[package]
22
name = "lightning-invoice"
33
description = "Data structures to parse and serialize BOLT11 lightning invoices"
4-
version = "0.33.0"
4+
version = "0.33.1"
55
authors = ["Sebastian Geisler <sgeisler@wh2.tu-dresden.de>"]
66
documentation = "https://docs.rs/lightning-invoice/"
77
license = "MIT OR Apache-2.0"

‎lightning-invoice/src/lib.rs

+20-3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ use core::iter::FilterMap;
4848
use core::num::ParseIntError;
4949
use core::ops::Deref;
5050
use core::slice::Iter;
51+
use core::str::FromStr;
5152
use core::time::Duration;
5253

5354
#[cfg(feature = "serde")]
@@ -78,8 +79,12 @@ use crate::prelude::*;
7879
/// Re-export serialization traits
7980
#[cfg(fuzzing)]
8081
pub use crate::de::FromBase32;
82+
#[cfg(not(fuzzing))]
83+
use crate::de::FromBase32;
8184
#[cfg(fuzzing)]
8285
pub use crate::ser::Base32Iterable;
86+
#[cfg(not(fuzzing))]
87+
use crate::ser::Base32Iterable;
8388

8489
/// Errors that indicate what is wrong with the invoice. They have some granularity for debug
8590
/// reasons, but should generally result in an "invalid BOLT11 invoice" message for the user.
@@ -1088,9 +1093,6 @@ impl RawBolt11Invoice {
10881093

10891094
/// Calculate the hash of the encoded `RawBolt11Invoice` which should be signed.
10901095
pub fn signable_hash(&self) -> [u8; 32] {
1091-
#[cfg(not(fuzzing))]
1092-
use crate::ser::Base32Iterable;
1093-
10941096
Self::hash_from_parts(self.hrp.to_string().as_bytes(), self.data.fe_iter())
10951097
}
10961098

@@ -1191,6 +1193,21 @@ impl RawBolt11Invoice {
11911193
pub fn currency(&self) -> Currency {
11921194
self.hrp.currency.clone()
11931195
}
1196+
1197+
/// Convert to HRP prefix and Fe32 encoded data part.
1198+
/// Can be used to transmit unsigned invoices for remote signing.
1199+
pub fn to_raw(&self) -> (String, Vec<Fe32>) {
1200+
(self.hrp.to_string(), self.data.fe_iter().collect())
1201+
}
1202+
1203+
/// Convert from HRP prefix and Fe32 encoded data part.
1204+
/// Can be used to receive unsigned invoices for remote signing.
1205+
pub fn from_raw(hrp: &str, data: &[Fe32]) -> Result<Self, Bolt11ParseError> {
1206+
let raw_hrp: RawHrp = RawHrp::from_str(hrp)?;
1207+
let data_part = RawDataPart::from_base32(data)?;
1208+
1209+
Ok(Self { hrp: raw_hrp, data: data_part })
1210+
}
11941211
}
11951212

11961213
impl PositiveTimestamp {

‎lightning/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "lightning"
3-
version = "0.1.0"
3+
version = "0.1.1"
44
authors = ["Matt Corallo"]
55
license = "MIT OR Apache-2.0"
66
repository = "https://github.com/lightningdevkit/rust-lightning/"

‎lightning/src/chain/chaininterface.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ pub trait FeeEstimator {
176176
}
177177

178178
/// Minimum relay fee as required by bitcoin network mempool policy.
179-
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 4000;
179+
pub const MIN_RELAY_FEE_SAT_PER_1000_WEIGHT: u64 = 253;
180180
/// Minimum feerate that takes a sane approach to bitcoind weight-to-vbytes rounding.
181181
/// See the following Core Lightning commit for an explanation:
182182
/// <https://github.com/ElementsProject/lightning/commit/2e687b9b352c9092b5e8bd4a688916ac50b44af0>

0 commit comments

Comments
 (0)