+// This file is Copyright its original authors, visible in version control
+// history.
+//
+// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
+// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
+// You may not use this file except in accordance with one or both of these
+// licenses.
+
//! Wire encoding/decoding for Lightning messages according to [BOLT #1].
//!
-//! Messages known by this module can be read from the wire using [`read`].
-//! The [`Message`] enum returned by [`read`] wraps the decoded message or the message type (if
+//! Messages known by this module can be read from the wire using [`read()`].
+//! The [`Message`] enum returned by [`read()`] wraps the decoded message or the message type (if
//! unknown) to use with pattern matching.
//!
//! Messages implementing the [`Encode`] trait define a message type and can be sent over the wire
-//! using [`write`].
+//! using [`write()`].
//!
//! [BOLT #1]: https://github.com/lightningnetwork/lightning-rfc/blob/master/01-messaging.md
-//! [`read`]: fn.read.html
-//! [`write`]: fn.write.html
-//! [`Encode`]: trait.Encode.html
-//! [`Message`]: enum.Message.html
use ln::msgs;
use util::ser::{Readable, Writeable, Writer};
-/// Maximum Lightning message data length according to
-/// [BOLT-8](https://github.com/lightningnetwork/lightning-rfc/blob/v1.0/08-transport.md#lightning-message-specification):
-/// "The maximum size of any Lightning message MUST NOT exceed 65535 bytes.
-/// A maximum size of 65535 simplifies testing, makes memory management easier,
-/// and helps mitigate memory-exhaustion attacks."
-pub const LN_MAX_MSG_LEN: usize = std::u16::MAX as usize; // Must be equal to 65535
-
-/// A Lightning message returned by [`read`] when decoding bytes received over the wire. Each
-/// variant contains a message from [`ln::msgs`] or otherwise the message type if unknown.
-///
-/// [`read`]: fn.read.html
-/// [`ln::msgs`]: ../msgs/index.html
+/// A Lightning message returned by [`read()`] when decoding bytes received over the wire. Each
+/// variant contains a message from [`msgs`] or otherwise the message type if unknown.
#[allow(missing_docs)]
+#[derive(Debug)]
pub enum Message {
Init(msgs::Init),
Error(msgs::ErrorMessage),
ChannelAnnouncement(msgs::ChannelAnnouncement),
NodeAnnouncement(msgs::NodeAnnouncement),
ChannelUpdate(msgs::ChannelUpdate),
+ QueryShortChannelIds(msgs::QueryShortChannelIds),
+ ReplyShortChannelIdsEnd(msgs::ReplyShortChannelIdsEnd),
+ QueryChannelRange(msgs::QueryChannelRange),
+ ReplyChannelRange(msgs::ReplyChannelRange),
+ GossipTimestampFilter(msgs::GossipTimestampFilter),
/// A message that could not be decoded because its type is unknown.
Unknown(MessageType),
}
/// A number identifying a message to determine how it is encoded on the wire.
-#[derive(Clone, Copy)]
+#[derive(Clone, Copy, Debug)]
pub struct MessageType(u16);
impl Message {
+ #[allow(dead_code)] // This method is only used in tests
/// Returns the type that was used to decode the message payload.
pub fn type_id(&self) -> MessageType {
match self {
&Message::ChannelAnnouncement(ref msg) => msg.type_id(),
&Message::NodeAnnouncement(ref msg) => msg.type_id(),
&Message::ChannelUpdate(ref msg) => msg.type_id(),
+ &Message::QueryShortChannelIds(ref msg) => msg.type_id(),
+ &Message::ReplyShortChannelIdsEnd(ref msg) => msg.type_id(),
+ &Message::QueryChannelRange(ref msg) => msg.type_id(),
+ &Message::ReplyChannelRange(ref msg) => msg.type_id(),
+ &Message::GossipTimestampFilter(ref msg) => msg.type_id(),
&Message::Unknown(type_id) => type_id,
}
}
}
}
-impl ::std::fmt::Display for MessageType {
- fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
+impl ::core::fmt::Display for MessageType {
+ fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
write!(f, "{}", self.0)
}
}
msgs::ChannelUpdate::TYPE => {
Ok(Message::ChannelUpdate(Readable::read(buffer)?))
},
+ msgs::QueryShortChannelIds::TYPE => {
+ Ok(Message::QueryShortChannelIds(Readable::read(buffer)?))
+ },
+ msgs::ReplyShortChannelIdsEnd::TYPE => {
+ Ok(Message::ReplyShortChannelIdsEnd(Readable::read(buffer)?))
+ },
+ msgs::QueryChannelRange::TYPE => {
+ Ok(Message::QueryChannelRange(Readable::read(buffer)?))
+ },
+ msgs::ReplyChannelRange::TYPE => {
+ Ok(Message::ReplyChannelRange(Readable::read(buffer)?))
+ }
+ msgs::GossipTimestampFilter::TYPE => {
+ Ok(Message::GossipTimestampFilter(Readable::read(buffer)?))
+ },
_ => {
Ok(Message::Unknown(MessageType(message_type)))
},
/// Defines a type-identified encoding for sending messages over the wire.
///
-/// Messages implementing this trait specify a type and must be [`Writeable`] to use with [`write`].
-///
-/// [`Writeable`]: ../../util/ser/trait.Writeable.html
-/// [`write`]: fn.write.html
+/// Messages implementing this trait specify a type and must be [`Writeable`] to use with [`write()`].
pub trait Encode {
/// The type identifying the message payload.
const TYPE: u16;
/// Returns the type identifying the message payload. Convenience method for accessing
- /// [`TYPE`](TYPE).
+ /// [`Self::TYPE`].
fn type_id(&self) -> MessageType {
MessageType(Self::TYPE)
}
const TYPE: u16 = 258;
}
+impl Encode for msgs::QueryShortChannelIds {
+ const TYPE: u16 = 261;
+}
+
+impl Encode for msgs::ReplyShortChannelIdsEnd {
+ const TYPE: u16 = 262;
+}
+
+impl Encode for msgs::QueryChannelRange {
+ const TYPE: u16 = 263;
+}
+
+impl Encode for msgs::ReplyChannelRange {
+ const TYPE: u16 = 264;
+}
+
+impl Encode for msgs::GossipTimestampFilter {
+ const TYPE: u16 = 265;
+}
+
#[cfg(test)]
mod tests {
use super::*;
- use util::byte_utils;
+ use prelude::*;
+ use core::convert::TryInto;
// Big-endian wire encoding of Pong message (type = 19, byteslen = 2).
const ENCODED_PONG: [u8; 6] = [0u8, 19u8, 0u8, 2u8, 0u8, 0u8];
- #[test]
- fn max_msg_len() {
- assert_eq!(LN_MAX_MSG_LEN, 65535);
- assert_eq!(LN_MAX_MSG_LEN, std::u16::MAX as usize);
- }
-
#[test]
fn read_empty_buffer() {
let buffer = [];
#[test]
fn read_unknown_message() {
- let buffer = &byte_utils::be16_to_array(::std::u16::MAX);
+ let buffer = &::core::u16::MAX.to_be_bytes();
let mut reader = ::std::io::Cursor::new(buffer);
let message = read(&mut reader).unwrap();
match message {
- Message::Unknown(MessageType(::std::u16::MAX)) => (),
- _ => panic!("Expected message type {}; found: {}", ::std::u16::MAX, message.type_id()),
+ Message::Unknown(MessageType(::core::u16::MAX)) => (),
+ _ => panic!("Expected message type {}; found: {}", ::core::u16::MAX, message.type_id()),
}
}
let mut buffer = Vec::new();
assert!(write(&message, &mut buffer).is_ok());
- let type_length = ::std::mem::size_of::<u16>();
+ let type_length = ::core::mem::size_of::<u16>();
let (type_bytes, payload_bytes) = buffer.split_at(type_length);
- assert_eq!(byte_utils::slice_to_be16(type_bytes), msgs::Pong::TYPE);
+ assert_eq!(u16::from_be_bytes(type_bytes.try_into().unwrap()), msgs::Pong::TYPE);
assert_eq!(payload_bytes, &ENCODED_PONG[type_length..]);
}
fn read_lnd_init_msg() {
// Taken from lnd v0.9.0-beta.
let buffer = vec![0, 16, 0, 2, 34, 0, 0, 3, 2, 162, 161];
- check_init_msg(buffer);
+ check_init_msg(buffer, false);
}
#[test]
fn read_clightning_init_msg() {
// Taken from c-lightning v0.8.0.
let buffer = vec![0, 16, 0, 2, 34, 0, 0, 3, 2, 170, 162, 1, 32, 6, 34, 110, 70, 17, 26, 11, 89, 202, 175, 18, 96, 67, 235, 91, 191, 40, 195, 79, 58, 94, 51, 42, 31, 199, 178, 183, 60, 241, 136, 145, 15];
- check_init_msg(buffer);
+ check_init_msg(buffer, true);
}
- fn check_init_msg(buffer: Vec<u8>) {
+ fn check_init_msg(buffer: Vec<u8>, expect_unknown: bool) {
let mut reader = ::std::io::Cursor::new(buffer);
let decoded_msg = read(&mut reader).unwrap();
match decoded_msg {
Message::Init(msgs::Init { features }) => {
assert!(features.supports_variable_length_onion());
assert!(features.supports_upfront_shutdown_script());
- assert!(features.supports_unknown_bits());
+ assert!(features.supports_gossip_queries());
+ assert_eq!(expect_unknown, features.supports_unknown_bits());
assert!(!features.requires_unknown_bits());
assert!(!features.initial_routing_sync());
},
Message::NodeAnnouncement(msgs::NodeAnnouncement { contents: msgs::UnsignedNodeAnnouncement { features, ..}, ..}) => {
assert!(features.supports_variable_length_onion());
assert!(features.supports_upfront_shutdown_script());
- assert!(features.supports_unknown_bits());
+ assert!(features.supports_gossip_queries());
assert!(!features.requires_unknown_bits());
},
_ => panic!("Expected node announcement, found message type: {}", decoded_msg.type_id())