Add htlc_maximum_msat field
authorGleb Naumenko <naumenko.gs@gmail.com>
Sun, 28 Jun 2020 11:43:10 +0000 (14:43 +0300)
committerGleb Naumenko <naumenko.gs@gmail.com>
Mon, 27 Jul 2020 11:06:16 +0000 (14:06 +0300)
13 files changed:
fuzz/src/bin/gen_target.sh
fuzz/src/msg_targets/gen_target.sh
fuzz/src/msg_targets/mod.rs
fuzz/src/msg_targets/msg_channel_update.rs
fuzz/src/router.rs
fuzz/targets.h
lightning/src/ln/channel.rs
lightning/src/ln/channelmanager.rs
lightning/src/ln/functional_tests.rs
lightning/src/ln/msgs.rs
lightning/src/routing/network_graph.rs
lightning/src/routing/router.rs
lightning/src/util/test_utils.rs

index 9b5629e7ce7f8b2425e40ced5e29a7f4d882a407..fb1f839a53f8f371458d35be2e56468b51447770 100755 (executable)
@@ -31,12 +31,12 @@ GEN_TEST msg_update_fee msg_targets::
 GEN_TEST msg_update_fulfill_htlc msg_targets::
 
 GEN_TEST msg_channel_announcement msg_targets::
-GEN_TEST msg_channel_update msg_targets::
 GEN_TEST msg_node_announcement msg_targets::
 
 GEN_TEST msg_update_add_htlc msg_targets::
 GEN_TEST msg_error_message msg_targets::
-GEN_TEST msg_onion_hop_data msg_targets::
+GEN_TEST msg_channel_update msg_targets::
 
+GEN_TEST msg_onion_hop_data msg_targets::
 GEN_TEST msg_ping msg_targets::
 GEN_TEST msg_pong msg_targets::
index 0121e4eb821990ef5c104d95f15fe1f13ae212a8..b9381fc3a9a8df4f1ecc8407487dd35f2fe1480d 100755 (executable)
@@ -29,11 +29,11 @@ GEN_TEST UpdateFee test_msg ""
 GEN_TEST UpdateFulfillHTLC test_msg ""
 
 GEN_TEST ChannelAnnouncement test_msg_exact ""
-GEN_TEST ChannelUpdate test_msg_exact ""
 GEN_TEST NodeAnnouncement test_msg_exact ""
 
 GEN_TEST UpdateAddHTLC test_msg_hole ", 85, 33"
 GEN_TEST ErrorMessage test_msg_hole ", 32, 2"
+GEN_TEST ChannelUpdate test_msg_hole ", 108, 1"
 
 GEN_TEST Init test_msg_simple ""
 GEN_TEST OnionHopData test_msg_simple ""
index 69fc4e74219b8cf20e81e5cb49937918c596ccf5..8c5dd6971712703d13f60c9133b5324aa957310d 100644 (file)
@@ -16,10 +16,10 @@ pub mod msg_update_fail_malformed_htlc;
 pub mod msg_update_fee;
 pub mod msg_update_fulfill_htlc;
 pub mod msg_channel_announcement;
-pub mod msg_channel_update;
 pub mod msg_node_announcement;
 pub mod msg_update_add_htlc;
 pub mod msg_error_message;
+pub mod msg_channel_update;
 pub mod msg_init;
 pub mod msg_onion_hop_data;
 pub mod msg_ping;
index d0326bfa4316aa74136c7d110fc9fcb3ad922258..c428c1c76c3188341aecde4bb8ac20254bb038ed 100644 (file)
@@ -8,11 +8,11 @@ use utils::test_logger;
 
 #[inline]
 pub fn msg_channel_update_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
-       test_msg_exact!(msgs::ChannelUpdate, data);
+       test_msg_hole!(msgs::ChannelUpdate, data, 108, 1);
 }
 
 #[no_mangle]
 pub extern "C" fn msg_channel_update_run(data: *const u8, datalen: usize) {
        let data = unsafe { std::slice::from_raw_parts(data, datalen) };
-       test_msg_exact!(msgs::ChannelUpdate, data);
+       test_msg_hole!(msgs::ChannelUpdate, data, 108, 1);
 }
index 3a6b5bdf40cd9af51eb0335de6fbdfd521abe9f9..31e552f5906a518d883d877dc7dcec86e87de1f3 100644 (file)
@@ -172,12 +172,12 @@ pub fn do_test<Out: test_logger::Output>(data: &[u8], out: Out) {
                                let _ = net_graph_msg_handler.handle_channel_announcement(&decode_msg_with_len16!(msgs::ChannelAnnouncement, 64*4, 32+8+33*4));
                        },
                        2 => {
-                               let _ = net_graph_msg_handler.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 128));
+                               let _ = net_graph_msg_handler.handle_channel_update(&decode_msg!(msgs::ChannelUpdate, 136));
                        },
                        3 => {
                                match get_slice!(1)[0] {
                                        0 => {
-                                               net_graph_msg_handler.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {msg: decode_msg!(msgs::ChannelUpdate, 128)});
+                                               net_graph_msg_handler.handle_htlc_fail_channel_update(&msgs::HTLCFailChannelUpdate::ChannelUpdateMessage {msg: decode_msg!(msgs::ChannelUpdate, 136)});
                                        },
                                        1 => {
                                                let short_channel_id = slice_to_be64(get_slice!(8));
index 430f614fb09154bc72d19428e7503022d2df7d73..fe94a3913b6dc855ba43dd8e983a44cd46c18cbc 100644 (file)
@@ -22,10 +22,10 @@ void msg_update_fail_malformed_htlc_run(const unsigned char* data, size_t data_l
 void msg_update_fee_run(const unsigned char* data, size_t data_len);
 void msg_update_fulfill_htlc_run(const unsigned char* data, size_t data_len);
 void msg_channel_announcement_run(const unsigned char* data, size_t data_len);
-void msg_channel_update_run(const unsigned char* data, size_t data_len);
 void msg_node_announcement_run(const unsigned char* data, size_t data_len);
 void msg_update_add_htlc_run(const unsigned char* data, size_t data_len);
 void msg_error_message_run(const unsigned char* data, size_t data_len);
+void msg_channel_update_run(const unsigned char* data, size_t data_len);
 void msg_onion_hop_data_run(const unsigned char* data, size_t data_len);
 void msg_ping_run(const unsigned char* data, size_t data_len);
 void msg_pong_run(const unsigned char* data, size_t data_len);
index a0879d4e7a554895a5636d57a4e6485bcc1bb086..7a4c76e282b06cdc201cb82b24db970fa55efbf5 100644 (file)
@@ -3135,6 +3135,18 @@ impl<ChanSigner: ChannelKeys> Channel<ChanSigner> {
                self.our_htlc_minimum_msat
        }
 
+       /// Allowed in any state (including after shutdown)
+       pub fn get_announced_htlc_max_msat(&self) -> u64 {
+               return cmp::min(
+                       // Upper bound by capacity. We make it a bit less than full capacity to prevent attempts
+                       // to use full capacity. This is an effort to reduce routing failures, because in many cases
+                       // channel might have been used to route very small values (either by honest users or as DoS).
+                       self.channel_value_satoshis * 9 / 10,
+
+                       Channel::<ChanSigner>::get_our_max_htlc_value_in_flight_msat(self.channel_value_satoshis)
+               );
+       }
+
        /// Allowed in any state (including after shutdown)
        pub fn get_their_htlc_minimum_msat(&self) -> u64 {
                self.our_htlc_minimum_msat
index d591515c467ab34658fef44d4e97303f91c38a19..5466b3d23c8c96dafd651003ce85c268964d632a 100644 (file)
@@ -34,7 +34,7 @@ use ln::features::{InitFeatures, NodeFeatures};
 use routing::router::{Route, RouteHop};
 use ln::msgs;
 use ln::onion_utils;
-use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError};
+use ln::msgs::{ChannelMessageHandler, DecodeError, LightningError, OptionalField};
 use chain::keysinterface::{ChannelKeys, KeysInterface, KeysManager, InMemoryChannelKeys};
 use util::config::UserConfig;
 use util::{byte_utils, events};
@@ -1186,7 +1186,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                                        res.extend_from_slice(&byte_utils::be32_to_array(msg.cltv_expiry));
                                                }
                                                else if code == 0x1000 | 20 {
-                                                       res.extend_from_slice(&byte_utils::be16_to_array(chan_update.contents.flags));
+                                                       // TODO: underspecified, follow https://github.com/lightningnetwork/lightning-rfc/issues/791
+                                                       res.extend_from_slice(&byte_utils::be16_to_array(0));
                                                }
                                                res.extend_from_slice(&chan_update.encode_with_len()[..]);
                                        }
@@ -1212,9 +1213,10 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                        chain_hash: self.genesis_hash,
                        short_channel_id: short_channel_id,
                        timestamp: chan.get_update_time_counter(),
-                       flags: (!were_node_one) as u16 | ((!chan.is_live() as u16) << 1),
+                       flags: (!were_node_one) as u8 | ((!chan.is_live() as u8) << 1),
                        cltv_expiry_delta: CLTV_EXPIRY_DELTA,
                        htlc_minimum_msat: chan.get_our_htlc_minimum_msat(),
+                       htlc_maximum_msat: OptionalField::Present(chan.get_announced_htlc_max_msat()),
                        fee_base_msat: chan.get_our_fee_base_msat(&self.fee_estimator),
                        fee_proportional_millionths: chan.get_fee_proportional_millionths(),
                        excess_data: Vec::new(),
@@ -2494,7 +2496,8 @@ impl<ChanSigner: ChannelKeys, M: Deref, T: Deref, K: Deref, F: Deref, L: Deref>
                                                        let reason = if let Ok(upd) = self.get_channel_update(chan) {
                                                                onion_utils::build_first_hop_failure_packet(incoming_shared_secret, error_code, &{
                                                                        let mut res = Vec::with_capacity(8 + 128);
-                                                                       res.extend_from_slice(&byte_utils::be16_to_array(upd.contents.flags));
+                                                                       // TODO: underspecified, follow https://github.com/lightningnetwork/lightning-rfc/issues/791
+                                                                       res.extend_from_slice(&byte_utils::be16_to_array(0));
                                                                        res.extend_from_slice(&upd.encode_with_len()[..]);
                                                                        res
                                                                }[..])
index 4d2b155ce30b1ff4e1085e62df26e0debc1e6b72..9526189e7791947c073743fa876f52c8a23901d9 100644 (file)
@@ -15,7 +15,7 @@ use ln::{chan_utils, onion_utils};
 use routing::router::{Route, RouteHop, get_route};
 use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
 use ln::msgs;
-use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction};
+use ln::msgs::{ChannelMessageHandler,RoutingMessageHandler,HTLCFailChannelUpdate, ErrorAction, OptionalField};
 use util::enforcing_trait_impls::EnforcingChannelKeys;
 use util::{byte_utils, test_utils};
 use util::events::{Event, EventsProvider, MessageSendEvent, MessageSendEventsProvider};
@@ -6058,6 +6058,7 @@ impl msgs::ChannelUpdate {
                                flags: 0,
                                cltv_expiry_delta: 0,
                                htlc_minimum_msat: 0,
+                               htlc_maximum_msat: OptionalField::Absent,
                                fee_base_msat: 0,
                                fee_proportional_millionths: 0,
                                excess_data: vec![],
index bd5d23504b19961b63224c301853ce26971fd68e..554cf7290721951fd3f8eaf00d820e723c48da81 100644 (file)
@@ -427,9 +427,10 @@ pub(crate) struct UnsignedChannelUpdate {
        pub(crate) chain_hash: BlockHash,
        pub(crate) short_channel_id: u64,
        pub(crate) timestamp: u32,
-       pub(crate) flags: u16,
+       pub(crate) flags: u8,
        pub(crate) cltv_expiry_delta: u16,
        pub(crate) htlc_minimum_msat: u64,
+       pub(crate) htlc_maximum_msat: OptionalField<u64>,
        pub(crate) fee_base_msat: u32,
        pub(crate) fee_proportional_millionths: u32,
        pub(crate) excess_data: Vec<u8>,
@@ -517,7 +518,7 @@ pub enum HTLCFailChannelUpdate {
 /// As we wish to serialize these differently from Option<T>s (Options get a tag byte, but
 /// OptionalFeild simply gets Present if there are enough bytes to read into it), we have a
 /// separate enum type for them.
-#[derive(Clone, PartialEq)]
+#[derive(Clone, PartialEq, Debug)]
 pub enum OptionalField<T> {
        /// Optional field is included in message
        Present(T),
@@ -742,6 +743,26 @@ impl Readable for OptionalField<Script> {
        }
 }
 
+impl Writeable for OptionalField<u64> {
+       fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
+               match *self {
+                       OptionalField::Present(ref value) => {
+                               value.write(w)?;
+                       },
+                       OptionalField::Absent => {}
+               }
+               Ok(())
+       }
+}
+
+impl Readable for OptionalField<u64> {
+       fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let value: u64 = Readable::read(r)?;
+               Ok(OptionalField::Present(value))
+       }
+}
+
+
 impl_writeable_len_match!(AcceptChannel, {
                {AcceptChannel{ shutdown_scriptpubkey: OptionalField::Present(ref script), .. }, 270 + 2 + script.len()},
                {_, 270}
@@ -1180,15 +1201,23 @@ impl_writeable_len_match!(ChannelAnnouncement, {
 
 impl Writeable for UnsignedChannelUpdate {
        fn write<W: Writer>(&self, w: &mut W) -> Result<(), ::std::io::Error> {
-               w.size_hint(64 + self.excess_data.len());
+               let mut size = 64 + self.excess_data.len();
+               let mut message_flags: u8 = 0;
+               if let OptionalField::Present(_) = self.htlc_maximum_msat {
+                       size += 8;
+                       message_flags = 1;
+               }
+               w.size_hint(size);
                self.chain_hash.write(w)?;
                self.short_channel_id.write(w)?;
                self.timestamp.write(w)?;
-               self.flags.write(w)?;
+               let all_flags = self.flags as u16 | ((message_flags as u16) << 8);
+               all_flags.write(w)?;
                self.cltv_expiry_delta.write(w)?;
                self.htlc_minimum_msat.write(w)?;
                self.fee_base_msat.write(w)?;
                self.fee_proportional_millionths.write(w)?;
+               self.htlc_maximum_msat.write(w)?;
                w.write_all(&self.excess_data[..])?;
                Ok(())
        }
@@ -1196,15 +1225,22 @@ impl Writeable for UnsignedChannelUpdate {
 
 impl Readable for UnsignedChannelUpdate {
        fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+               let has_htlc_maximum_msat;
                Ok(Self {
                        chain_hash: Readable::read(r)?,
                        short_channel_id: Readable::read(r)?,
                        timestamp: Readable::read(r)?,
-                       flags: Readable::read(r)?,
+                       flags: {
+                               let flags: u16 = Readable::read(r)?;
+                               let message_flags = flags >> 8;
+                               has_htlc_maximum_msat = (message_flags as i32 & 1) == 1;
+                               flags as u8
+                       },
                        cltv_expiry_delta: Readable::read(r)?,
                        htlc_minimum_msat: Readable::read(r)?,
                        fee_base_msat: Readable::read(r)?,
                        fee_proportional_millionths: Readable::read(r)?,
+                       htlc_maximum_msat: if has_htlc_maximum_msat { Readable::read(r)? } else { OptionalField::Absent },
                        excess_data: {
                                let mut excess_data = vec![];
                                r.read_to_end(&mut excess_data)?;
@@ -1597,7 +1633,7 @@ mod tests {
                do_encoding_node_announcement(false, false, true, false, true, false, false);
        }
 
-       fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool) {
+       fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool, excess_data: bool) {
                let secp_ctx = Secp256k1::new();
                let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
                let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
@@ -1605,12 +1641,13 @@ mod tests {
                        chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
                        short_channel_id: 2316138423780173,
                        timestamp: 20190119,
-                       flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 } | if htlc_maximum_msat { 1 << 8 } else { 0 },
+                       flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 },
                        cltv_expiry_delta: 144,
                        htlc_minimum_msat: 1000000,
+                       htlc_maximum_msat: if htlc_maximum_msat { OptionalField::Present(131355275467161) } else { OptionalField::Absent },
                        fee_base_msat: 10000,
                        fee_proportional_millionths: 20,
-                       excess_data: if htlc_maximum_msat { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }
+                       excess_data: if excess_data { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }
                };
                let channel_update = msgs::ChannelUpdate {
                        signature: sig_1,
@@ -1636,6 +1673,9 @@ mod tests {
                }
                target_value.append(&mut hex::decode("009000000000000f42400000271000000014").unwrap());
                if htlc_maximum_msat {
+                       target_value.append(&mut hex::decode("0000777788889999").unwrap());
+               }
+               if excess_data {
                        target_value.append(&mut hex::decode("000000003b9aca00").unwrap());
                }
                assert_eq!(encoded_value, target_value);
@@ -1643,11 +1683,16 @@ mod tests {
 
        #[test]
        fn encoding_channel_update() {
-               do_encoding_channel_update(false, false, false);
-               do_encoding_channel_update(true, false, false);
-               do_encoding_channel_update(false, true, false);
-               do_encoding_channel_update(false, false, true);
-               do_encoding_channel_update(true, true, true);
+               do_encoding_channel_update(false, false, false, false);
+               do_encoding_channel_update(false, false, false, true);
+               do_encoding_channel_update(true, false, false, false);
+               do_encoding_channel_update(true, false, false, true);
+               do_encoding_channel_update(false, true, false, false);
+               do_encoding_channel_update(false, true, false, true);
+               do_encoding_channel_update(false, false, true, false);
+               do_encoding_channel_update(false, false, true, true);
+               do_encoding_channel_update(true, true, true, false);
+               do_encoding_channel_update(true, true, true, true);
        }
 
        fn do_encoding_open_channel(random_bit: bool, shutdown: bool) {
index e9b4fdbf7375a8cf17e67a9e8beb23b8e8681711..4110d52201352fe55882ec5e36a85f4018f541cb 100644 (file)
@@ -11,7 +11,7 @@ use bitcoin::blockdata::opcodes;
 
 use chain::chaininterface::{ChainError, ChainWatchInterface};
 use ln::features::{ChannelFeatures, NodeFeatures};
-use ln::msgs::{DecodeError,ErrorAction,LightningError,RoutingMessageHandler,NetAddress};
+use ln::msgs::{DecodeError, ErrorAction, LightningError, RoutingMessageHandler, NetAddress, OptionalField};
 use ln::msgs;
 use util::ser::{Writeable, Readable, Writer};
 use util::logger::Logger;
@@ -215,6 +215,8 @@ pub struct DirectionalChannelInfo {
        pub cltv_expiry_delta: u16,
        /// The minimum value, which must be relayed to the next hop via the channel
        pub htlc_minimum_msat: u64,
+       /// The maximum value which may be relayed to the next hop via the channel.
+       pub htlc_maximum_msat: Option<u64>,
        /// Fees charged when the channel is used for routing
        pub fees: RoutingFees,
        /// Most recent update for the channel received from the network
@@ -236,6 +238,7 @@ impl_writeable!(DirectionalChannelInfo, 0, {
        enabled,
        cltv_expiry_delta,
        htlc_minimum_msat,
+       htlc_maximum_msat,
        fees,
        last_update_message
 });
@@ -681,6 +684,7 @@ impl NetworkGraph {
                                                        last_update: msg.contents.timestamp,
                                                        cltv_expiry_delta: msg.contents.cltv_expiry_delta,
                                                        htlc_minimum_msat: msg.contents.htlc_minimum_msat,
+                                                       htlc_maximum_msat: if let OptionalField::Present(max_value) = msg.contents.htlc_maximum_msat { Some(max_value) } else { None },
                                                        fees: RoutingFees {
                                                                base_msat: msg.contents.fee_base_msat,
                                                                proportional_millionths: msg.contents.fee_proportional_millionths,
@@ -774,7 +778,7 @@ mod tests {
        use chain::chaininterface;
        use ln::features::{ChannelFeatures, NodeFeatures};
        use routing::network_graph::{NetGraphMsgHandler, NetworkGraph};
-       use ln::msgs::{RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
+       use ln::msgs::{OptionalField, RoutingMessageHandler, UnsignedNodeAnnouncement, NodeAnnouncement,
                UnsignedChannelAnnouncement, ChannelAnnouncement, UnsignedChannelUpdate, ChannelUpdate, HTLCFailChannelUpdate};
        use util::test_utils;
        use util::logger::Logger;
@@ -1156,6 +1160,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: 144,
                        htlc_minimum_msat: 1000000,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 10000,
                        fee_proportional_millionths: 20,
                        excess_data: Vec::new()
@@ -1290,6 +1295,7 @@ mod tests {
                                flags: 0,
                                cltv_expiry_delta: 144,
                                htlc_minimum_msat: 1000000,
+                               htlc_maximum_msat: OptionalField::Absent,
                                fee_base_msat: 10000,
                                fee_proportional_millionths: 20,
                                excess_data: Vec::new()
@@ -1417,6 +1423,7 @@ mod tests {
                                flags: 0,
                                cltv_expiry_delta: 144,
                                htlc_minimum_msat: 1000000,
+                               htlc_maximum_msat: OptionalField::Absent,
                                fee_base_msat: 10000,
                                fee_proportional_millionths: 20,
                                excess_data: Vec::new()
@@ -1453,6 +1460,7 @@ mod tests {
                                flags: 0,
                                cltv_expiry_delta: 144,
                                htlc_minimum_msat: 1000000,
+                               htlc_maximum_msat: OptionalField::Absent,
                                fee_base_msat: 10000,
                                fee_proportional_millionths: 20,
                                excess_data: [1; 3].to_vec()
index dad04a131f59e702976a2d183cc9e10f5c757fe2..f0fa9ccc40595bd79487b998f26213b8b6692693 100644 (file)
@@ -405,7 +405,7 @@ mod tests {
        use routing::router::{get_route, RouteHint, RoutingFees};
        use routing::network_graph::NetGraphMsgHandler;
        use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures};
-       use ln::msgs::{ErrorAction, LightningError, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
+       use ln::msgs::{ErrorAction, LightningError, OptionalField, UnsignedChannelAnnouncement, ChannelAnnouncement, RoutingMessageHandler,
           NodeAnnouncement, UnsignedNodeAnnouncement, ChannelUpdate, UnsignedChannelUpdate};
        use ln::channelmanager;
        use util::test_utils;
@@ -604,6 +604,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: 0,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -618,6 +619,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: u16::max_value(),
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: u32::max_value(),
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
@@ -629,6 +631,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: 0,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -644,6 +647,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: u16::max_value(),
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: u32::max_value(),
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
@@ -655,6 +659,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: 0,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -671,6 +676,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: (3 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -682,6 +688,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: (3 << 8) | 2,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 100,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -696,6 +703,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: (4 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 1000000,
                        excess_data: Vec::new()
@@ -707,6 +715,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: (4 << 8) | 2,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -720,6 +729,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: (13 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 2000000,
                        excess_data: Vec::new()
@@ -731,6 +741,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: (13 << 8) | 2,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -745,6 +756,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: (6 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -756,6 +768,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: (6 << 8) | 2,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -769,6 +782,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: (11 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -780,6 +794,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: (11 << 8) | 2,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -796,6 +811,7 @@ mod tests {
                        flags: 0,
                        cltv_expiry_delta: (7 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 1000000,
                        excess_data: Vec::new()
@@ -807,6 +823,7 @@ mod tests {
                        flags: 1,
                        cltv_expiry_delta: (7 << 8) | 2,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -841,6 +858,7 @@ mod tests {
                        flags: 2, // to disable
                        cltv_expiry_delta: 0,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -852,6 +870,7 @@ mod tests {
                        flags: 2, // to disable
                        cltv_expiry_delta: 0,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: Vec::new()
@@ -899,6 +918,7 @@ mod tests {
                        flags: 0, // to enable
                        cltv_expiry_delta: (4 << 8) | 1,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 1000000,
                        excess_data: Vec::new()
@@ -910,6 +930,7 @@ mod tests {
                        flags: 0, // to enable
                        cltv_expiry_delta: u16::max_value(),
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: u32::max_value(),
                        fee_proportional_millionths: u32::max_value(),
                        excess_data: Vec::new()
index deaa4680cd18e13ea95d085b049226c920c29790..33b070ee89d60e3b880147d1ce6535707ab6d615 100644 (file)
@@ -5,6 +5,7 @@ use chain::keysinterface;
 use ln::channelmonitor;
 use ln::features::{ChannelFeatures, InitFeatures};
 use ln::msgs;
+use ln::msgs::OptionalField;
 use ln::channelmonitor::HTLCUpdate;
 use util::enforcing_trait_impls::EnforcingChannelKeys;
 use util::events;
@@ -216,6 +217,7 @@ fn get_dummy_channel_update(short_chan_id: u64) -> msgs::ChannelUpdate {
                        flags: 0,
                        cltv_expiry_delta: 0,
                        htlc_minimum_msat: 0,
+                       htlc_maximum_msat: OptionalField::Absent,
                        fee_base_msat: 0,
                        fee_proportional_millionths: 0,
                        excess_data: vec![],