Skip to content

Commit bf8307a

Browse files
committed
Add htlc_maximum_msat field
1 parent a66b801 commit bf8307a

File tree

10 files changed

+120
-26
lines changed

10 files changed

+120
-26
lines changed

fuzz/src/bin/gen_target.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ GEN_TEST msg_update_fee msg_targets::
3131
GEN_TEST msg_update_fulfill_htlc msg_targets::
3232

3333
GEN_TEST msg_channel_announcement msg_targets::
34-
GEN_TEST msg_channel_update msg_targets::
3534
GEN_TEST msg_node_announcement msg_targets::
3635

3736
GEN_TEST msg_update_add_htlc msg_targets::
3837
GEN_TEST msg_error_message msg_targets::
39-
GEN_TEST msg_onion_hop_data msg_targets::
38+
GEN_TEST msg_channel_update msg_targets::
4039

40+
GEN_TEST msg_onion_hop_data msg_targets::
4141
GEN_TEST msg_ping msg_targets::
4242
GEN_TEST msg_pong msg_targets::

fuzz/src/msg_targets/gen_target.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ GEN_TEST UpdateFee test_msg ""
2929
GEN_TEST UpdateFulfillHTLC test_msg ""
3030

3131
GEN_TEST ChannelAnnouncement test_msg_exact ""
32-
GEN_TEST ChannelUpdate test_msg_exact ""
3332
GEN_TEST NodeAnnouncement test_msg_exact ""
3433

3534
GEN_TEST UpdateAddHTLC test_msg_hole ", 85, 33"
3635
GEN_TEST ErrorMessage test_msg_hole ", 32, 2"
36+
GEN_TEST ChannelUpdate test_msg_hole ", 108, 1"
3737

3838
GEN_TEST Init test_msg_simple ""
3939
GEN_TEST OnionHopData test_msg_simple ""

fuzz/src/router.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,12 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
172172
let _ = net_graph_msg_handler.handle_channel_announcement(&decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4));
173173
},
174174
2 => {
175-
let _ = net_graph_msg_handler.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 128));
175+
let _ = net_graph_msg_handler.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 136));
176176
},
177177
3 => {
178178
match get_slice!(1)[0] {
179179
0 => {
180-
net_graph_msg_handler.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {msg: decode_msg!(msgs::ChannelUpdate, 128)});
180+
net_graph_msg_handler.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {msg: decode_msg!(msgs::ChannelUpdate, 136)});
181181
},
182182
1 => {
183183
let short_channel_id = slice_to_be64(get_slice!(8));

lightning/src/ln/channel.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3135,6 +3135,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
31353135
self.our_htlc_minimum_msat
31363136
}
31373137

3138+
/// Allowed in any state (including after shutdown)
3139+
pub fn get_announced_htlc_max_msat(&self) -> u64 {
3140+
return cmp::min(
3141+
// Upper bound by capacity. We make it a bit less than full capacity to prevent attempts
3142+
// to use full capacity. This is an effort to reduce routing failures, because in many cases
3143+
// channel might have been used to route very small values (either by honest users or as DoS).
3144+
self.channel_value_satoshis * 9 / 10,
3145+
3146+
Channel::<ChanSigner>::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis)
3147+
);
3148+
}
3149+
31383150
/// Allowed in any state (including after shutdown)
31393151
pub fn get_their_htlc_minimum_msat(&self) -> u64 {
31403152
self.our_htlc_minimum_msat

lightning/src/ln/channelmanager.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use ln::features::{InitFeatures, NodeFeatures};
3434
use routing::router::{Route, RouteHop};
3535
use ln::msgs;
3636
use ln::onion_utils;
37-
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
37+
use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, OptionalField};
3838
use chain::keysinterface::{ChannelKeys, KeysInterface, KeysManager, InMemoryChannelKeys};
3939
use util::config::UserConfig;
4040
use util::{byte_utils, events};
@@ -1186,7 +1186,9 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
11861186
res.extend_from_slice(&byte_utils::be32_to_array(msg.cltv_expiry));
11871187
}
11881188
else if code == 0x1000 | 20 {
1189-
res.extend_from_slice(&byte_utils::be16_to_array(chan_update.contents.flags));
1189+
let mut flags = chan_update.contents.flags as u16;
1190+
if let OptionalField::Present(_) = chan_update.contents.htlc_maximum_msat {flags |= 1 << 8};
1191+
res.extend_from_slice(&byte_utils::be16_to_array(flags));
11901192
}
11911193
res.extend_from_slice(&chan_update.encode_with_len()[..]);
11921194
}
@@ -1212,9 +1214,10 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
12121214
chain_hash: self.genesis_hash,
12131215
short_channel_id: short_channel_id,
12141216
timestamp: chan.get_update_time_counter(),
1215-
flags: (!were_node_one) as u16 | ((!chan.is_live() as u16) << 1),
1217+
flags: (!were_node_one) as u8 | ((!chan.is_live() as u8) << 1),
12161218
cltv_expiry_delta: CLTV_EXPIRY_DELTA,
12171219
htlc_minimum_msat: chan.get_our_htlc_minimum_msat(),
1220+
htlc_maximum_msat: OptionalField::Present(chan.get_announced_htlc_max_msat()),
12181221
fee_base_msat: chan.get_our_fee_base_msat(&self.fee_estimator),
12191222
fee_proportional_millionths: chan.get_fee_proportional_millionths(),
12201223
excess_data: Vec::new(),
@@ -2494,7 +2497,9 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
24942497
let reason = if let Ok(upd) = self.get_channel_update(chan) {
24952498
onion_utils::build_first_hop_failure_packet(incoming_shared_secret, error_code, &{
24962499
let mut res = Vec::with_capacity(8 + 128);
2497-
res.extend_from_slice(&byte_utils::be16_to_array(upd.contents.flags));
2500+
let mut flags = upd.contents.flags as u16;
2501+
if let OptionalField::Present(_) = upd.contents.htlc_maximum_msat {flags |= 1 << 8};
2502+
res.extend_from_slice(&byte_utils::be16_to_array(flags));
24982503
res.extend_from_slice(&upd.encode_with_len()[..]);
24992504
res
25002505
}[..])

lightning/src/ln/functional_tests.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use ln::{chan_utils, onion_utils};
1515
use routing::router::{Route, RouteHop, get_route};
1616
use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
1717
use ln::msgs;
18-
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction};
18+
use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction, OptionalField};
1919
use util::enforcing_trait_impls::EnforcingChannelKeys;
2020
use util::{byte_utils, test_utils};
2121
use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
@@ -6058,6 +6058,7 @@ impl msgs::ChannelUpdate {
60586058
flags: 0,
60596059
cltv_expiry_delta: 0,
60606060
htlc_minimum_msat: 0,
6061+
htlc_maximum_msat: OptionalField::Absent,
60616062
fee_base_msat: 0,
60626063
fee_proportional_millionths: 0,
60636064
excess_data: vec![],

lightning/src/ln/msgs.rs

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -427,9 +427,10 @@ pub(crate) struct UnsignedChannelUpdate {
427427
pub(crate) chain_hash: BlockHash,
428428
pub(crate) short_channel_id: u64,
429429
pub(crate) timestamp: u32,
430-
pub(crate) flags: u16,
430+
pub(crate) flags: u8,
431431
pub(crate) cltv_expiry_delta: u16,
432432
pub(crate) htlc_minimum_msat: u64,
433+
pub(crate) htlc_maximum_msat: OptionalField<u64>,
433434
pub(crate) fee_base_msat: u32,
434435
pub(crate) fee_proportional_millionths: u32,
435436
pub(crate) excess_data: Vec<u8>,
@@ -517,7 +518,7 @@ pub enum HTLCFailChannelUpdate {
517518
/// As we wish to serialize these differently from Option<T>s (Options get a tag byte, but
518519
/// OptionalFeild simply gets Present if there are enough bytes to read into it), we have a
519520
/// separate enum type for them.
520-
#[derive(Clone, PartialEq)]
521+
#[derive(Clone, PartialEq, Debug)]
521522
pub enum OptionalField<T> {
522523
/// Optional field is included in message
523524
Present(T),
@@ -742,6 +743,26 @@ impl Readable for OptionalField<Script> {
742743
}
743744
}
744745

746+
impl Writeable for OptionalField<u64> {
747+
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
748+
match *self {
749+
OptionalField::Present(ref value) => {
750+
value.write(w)?;
751+
},
752+
OptionalField::Absent => {}
753+
}
754+
Ok(())
755+
}
756+
}
757+
758+
impl Readable for OptionalField<u64> {
759+
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
760+
let value: u64 = Readable::read(r)?;
761+
Ok(OptionalField::Present(value))
762+
}
763+
}
764+
765+
745766
impl_writeable_len_match!(AcceptChannel, {
746767
{AcceptChannel{ shutdown_scriptpubkey: OptionalField::Present(ref script), .. }, 270 + 2 + script.len()},
747768
{_, 270}
@@ -1180,31 +1201,46 @@ impl_writeable_len_match!(ChannelAnnouncement, {
11801201

11811202
impl Writeable for UnsignedChannelUpdate {
11821203
fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
1183-
w.size_hint(64 + self.excess_data.len());
1204+
let mut size = 64 + self.excess_data.len();
1205+
let mut message_flags: u8 = 0;
1206+
if let OptionalField::Present(_) = self.htlc_maximum_msat {
1207+
size += 8;
1208+
message_flags = 1;
1209+
}
1210+
w.size_hint(size);
11841211
self.chain_hash.write(w)?;
11851212
self.short_channel_id.write(w)?;
11861213
self.timestamp.write(w)?;
1187-
self.flags.write(w)?;
1214+
let all_flags = self.flags as u16 | ((message_flags as u16) << 8);
1215+
all_flags.write(w)?;
11881216
self.cltv_expiry_delta.write(w)?;
11891217
self.htlc_minimum_msat.write(w)?;
11901218
self.fee_base_msat.write(w)?;
11911219
self.fee_proportional_millionths.write(w)?;
1220+
self.htlc_maximum_msat.write(w)?;
11921221
w.write_all(&self.excess_data[..])?;
11931222
Ok(())
11941223
}
11951224
}
11961225

11971226
impl Readable for UnsignedChannelUpdate {
11981227
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
1228+
let has_htlc_maximum_msat;
11991229
Ok(Self {
12001230
chain_hash: Readable::read(r)?,
12011231
short_channel_id: Readable::read(r)?,
12021232
timestamp: Readable::read(r)?,
1203-
flags: Readable::read(r)?,
1233+
flags: {
1234+
let flags: u16 = Readable::read(r)?;
1235+
let message_flags = flags >> 8;
1236+
has_htlc_maximum_msat = (message_flags as i32 & 1) == 1;
1237+
flags as u8
1238+
},
12041239
cltv_expiry_delta: Readable::read(r)?,
12051240
htlc_minimum_msat: Readable::read(r)?,
12061241
fee_base_msat: Readable::read(r)?,
12071242
fee_proportional_millionths: Readable::read(r)?,
1243+
htlc_maximum_msat: if has_htlc_maximum_msat { Readable::read(r)? } else { OptionalField::Absent },
12081244
excess_data: {
12091245
let mut excess_data = vec![];
12101246
r.read_to_end(&mut excess_data)?;
@@ -1597,20 +1633,21 @@ mod tests {
15971633
do_encoding_node_announcement(false, false, true, false, true, false, false);
15981634
}
15991635

1600-
fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool) {
1636+
fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool, excess_data: bool) {
16011637
let secp_ctx = Secp256k1::new();
16021638
let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
16031639
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
16041640
let unsigned_channel_update = msgs::UnsignedChannelUpdate {
16051641
chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
16061642
short_channel_id: 2316138423780173,
16071643
timestamp: 20190119,
1608-
flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 } | if htlc_maximum_msat { 1 << 8 } else { 0 },
1644+
flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 },
16091645
cltv_expiry_delta: 144,
16101646
htlc_minimum_msat: 1000000,
1647+
htlc_maximum_msat: if htlc_maximum_msat { OptionalField::Present(131355275467161) } else { OptionalField::Absent },
16111648
fee_base_msat: 10000,
16121649
fee_proportional_millionths: 20,
1613-
excess_data: if htlc_maximum_msat { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }
1650+
excess_data: if excess_data { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }
16141651
};
16151652
let channel_update = msgs::ChannelUpdate {
16161653
signature: sig_1,
@@ -1636,18 +1673,26 @@ mod tests {
16361673
}
16371674
target_value.append(&mut hex::decode("009000000000000f42400000271000000014").unwrap());
16381675
if htlc_maximum_msat {
1676+
target_value.append(&mut hex::decode("0000777788889999").unwrap());
1677+
}
1678+
if excess_data {
16391679
target_value.append(&mut hex::decode("000000003b9aca00").unwrap());
16401680
}
16411681
assert_eq!(encoded_value, target_value);
16421682
}
16431683

16441684
#[test]
16451685
fn encoding_channel_update() {
1646-
do_encoding_channel_update(false, false, false);
1647-
do_encoding_channel_update(true, false, false);
1648-
do_encoding_channel_update(false, true, false);
1649-
do_encoding_channel_update(false, false, true);
1650-
do_encoding_channel_update(true, true, true);
1686+
do_encoding_channel_update(false, false, false, false);
1687+
do_encoding_channel_update(false, false, false, true);
1688+
do_encoding_channel_update(true, false, false, false);
1689+
do_encoding_channel_update(true, false, false, true);
1690+
do_encoding_channel_update(false, true, false, false);
1691+
do_encoding_channel_update(false, true, false, true);
1692+
do_encoding_channel_update(false, false, true, false);
1693+
do_encoding_channel_update(false, false, true, true);
1694+
do_encoding_channel_update(true, true, true, false);
1695+
do_encoding_channel_update(true, true, true, true);
16511696
}
16521697

16531698
fn do_encoding_open_channel(random_bit: bool, shutdown: bool) {

lightning/src/routing/network_graph.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ use bitcoin::blockdata::opcodes;
1111

1212
use chain::chaininterface::{ChainError, ChainWatchInterface};
1313
use ln::features::{ChannelFeatures, NodeFeatures};
14-
use ln::msgs::{DecodeError,ErrorAction,LightningError,RoutingMessageHandler,NetAddress};
14+
use ln::msgs::{DecodeError, ErrorAction, LightningError, RoutingMessageHandler, NetAddress, OptionalField};
1515
use ln::msgs;
1616
use util::ser::{Writeable, Readable, Writer};
1717
use util::logger::Logger;
@@ -215,6 +215,8 @@ pub struct DirectionalChannelInfo {
215215
pub cltv_expiry_delta: u16,
216216
/// The minimum value, which must be relayed to the next hop via the channel
217217
pub htlc_minimum_msat: u64,
218+
/// The maximum value which may be relayed to the next hop via the channel.
219+
pub htlc_maximum_msat: Option<u64>,
218220
/// Fees charged when the channel is used for routing
219221
pub fees: RoutingFees,
220222
/// Most recent update for the channel received from the network
@@ -236,6 +238,7 @@ impl_writeable!(DirectionalChannelInfo, 0, {
236238
enabled,
237239
cltv_expiry_delta,
238240
htlc_minimum_msat,
241+
htlc_maximum_msat,
239242
fees,
240243
last_update_message
241244
});
@@ -681,6 +684,7 @@ impl NetworkGraph {
681684
last_update: msg.contents.timestamp,
682685
cltv_expiry_delta: msg.contents.cltv_expiry_delta,
683686
htlc_minimum_msat: msg.contents.htlc_minimum_msat,
687+
htlc_maximum_msat: if let OptionalField::Present(max_value) = msg.contents.htlc_maximum_msat { Some(max_value) } else { None },
684688
fees: RoutingFees {
685689
base_msat: msg.contents.fee_base_msat,
686690
proportional_millionths: msg.contents.fee_proportional_millionths,
@@ -774,7 +778,7 @@ mod tests {
774778
use chain::chaininterface;
775779
use ln::features::{ChannelFeatures, NodeFeatures};
776780
use routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
777-
use ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
781+
use ln::msgs::{OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
778782
UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate, HTLCFailChannelUpdate};
779783
use util::test_utils;
780784
use util::logger::Logger;
@@ -1156,6 +1160,7 @@ mod tests {
11561160
flags: 0,
11571161
cltv_expiry_delta: 144,
11581162
htlc_minimum_msat: 1000000,
1163+
htlc_maximum_msat: OptionalField::Absent,
11591164
fee_base_msat: 10000,
11601165
fee_proportional_millionths: 20,
11611166
excess_data: Vec::new()
@@ -1290,6 +1295,7 @@ mod tests {
12901295
flags: 0,
12911296
cltv_expiry_delta: 144,
12921297
htlc_minimum_msat: 1000000,
1298+
htlc_maximum_msat: OptionalField::Absent,
12931299
fee_base_msat: 10000,
12941300
fee_proportional_millionths: 20,
12951301
excess_data: Vec::new()
@@ -1417,6 +1423,7 @@ mod tests {
14171423
flags: 0,
14181424
cltv_expiry_delta: 144,
14191425
htlc_minimum_msat: 1000000,
1426+
htlc_maximum_msat: OptionalField::Absent,
14201427
fee_base_msat: 10000,
14211428
fee_proportional_millionths: 20,
14221429
excess_data: Vec::new()
@@ -1453,6 +1460,7 @@ mod tests {
14531460
flags: 0,
14541461
cltv_expiry_delta: 144,
14551462
htlc_minimum_msat: 1000000,
1463+
htlc_maximum_msat: OptionalField::Absent,
14561464
fee_base_msat: 10000,
14571465
fee_proportional_millionths: 20,
14581466
excess_data: [1; 3].to_vec()

0 commit comments

Comments
 (0)