use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
use prelude::*;
-use core::{cmp, fmt};
+use core::fmt;
use core::fmt::Debug;
use io::{self, Read};
use io_extras::read_to_end;
/// An error message to be sent or received from a peer
#[derive(Clone, Debug, PartialEq)]
pub struct ErrorMessage {
- /// The channel ID involved in the error
+ /// The channel ID involved in the error.
+ ///
+ /// All-0s indicates a general error unrelated to a specific channel, after which all channels
+ /// with the sending peer should be closed.
pub channel_id: [u8; 32],
/// A possibly human-readable error description.
- /// The string should be sanitized before it is used (e.g. emitted to logs
- /// or printed to stdout). Otherwise, a well crafted error message may trigger a security
- /// vulnerability in the terminal emulator or the logging subsystem.
+ /// The string should be sanitized before it is used (e.g. emitted to logs or printed to
+ /// stdout). Otherwise, a well crafted error message may trigger a security vulnerability in
+ /// the terminal emulator or the logging subsystem.
+ pub data: String,
+}
+
+/// A warning message to be sent or received from a peer
+#[derive(Clone, Debug, PartialEq)]
+pub struct WarningMessage {
+ /// The channel ID involved in the warning.
+ ///
+ /// All-0s indicates a warning unrelated to a specific channel.
+ pub channel_id: [u8; 32],
+ /// A possibly human-readable warning description.
+ /// The string should be sanitized before it is used (e.g. emitted to logs or printed to
+ /// stdout). Otherwise, a well crafted error message may trigger a security vulnerability in
+ /// the terminal emulator or the logging subsystem.
pub data: String,
}
port: u16,
},
/// An old-style Tor onion address/port on which the peer is listening.
- OnionV2 {
- /// The bytes (usually encoded in base32 with ".onion" appended)
- addr: [u8; 10],
- /// The port on which the node is listening
- port: u16,
- },
+ ///
+ /// This field is deprecated and the Tor network generally no longer supports V2 Onion
+ /// addresses. Thus, the details are not parsed here.
+ OnionV2([u8; 12]),
/// A new-style Tor onion address/port on which the peer is listening.
/// To create the human-readable "hostname", concatenate ed25519_pubkey, checksum, and version,
/// wrap as base32 and append ".onion".
match self {
&NetAddress::IPv4 {..} => { 1 },
&NetAddress::IPv6 {..} => { 2 },
- &NetAddress::OnionV2 {..} => { 3 },
+ &NetAddress::OnionV2(_) => { 3 },
&NetAddress::OnionV3 {..} => { 4 },
}
}
match self {
&NetAddress::IPv4 { .. } => { 6 },
&NetAddress::IPv6 { .. } => { 18 },
- &NetAddress::OnionV2 { .. } => { 12 },
+ &NetAddress::OnionV2(_) => { 12 },
&NetAddress::OnionV3 { .. } => { 37 },
}
}
addr.write(writer)?;
port.write(writer)?;
},
- &NetAddress::OnionV2 { ref addr, ref port } => {
+ &NetAddress::OnionV2(bytes) => {
3u8.write(writer)?;
- addr.write(writer)?;
- port.write(writer)?;
+ bytes.write(writer)?;
},
&NetAddress::OnionV3 { ref ed25519_pubkey, ref checksum, ref version, ref port } => {
4u8.write(writer)?;
port: Readable::read(reader)?,
}))
},
- 3 => {
- Ok(Ok(NetAddress::OnionV2 {
- addr: Readable::read(reader)?,
- port: Readable::read(reader)?,
- }))
- },
+ 3 => Ok(Ok(NetAddress::OnionV2(Readable::read(reader)?))),
4 => {
Ok(Ok(NetAddress::OnionV3 {
ed25519_pubkey: Readable::read(reader)?,
/// The peer did something harmless that we weren't able to meaningfully process.
/// If the error is logged, log it at the given level.
IgnoreAndLog(logger::Level),
+ /// The peer provided us with a gossip message which we'd already seen. In most cases this
+ /// should be ignored, but it may result in the message being forwarded if it is a duplicate of
+ /// our own channel announcements.
+ IgnoreDuplicateGossip,
/// The peer did something incorrect. Tell them.
SendErrorMessage {
/// The message to send.
- msg: ErrorMessage
+ msg: ErrorMessage,
+ },
+ /// The peer did something incorrect. Tell them without closing any channels.
+ SendWarningMessage {
+ /// The message to send.
+ msg: WarningMessage,
+ /// The peer may have done something harmless that we weren't able to meaningfully process,
+ /// though we should still tell them about it.
+ /// If this event is logged, log it at the given level.
+ log_level: logger::Level,
},
}
Ok(Self {
channel_id: Readable::read(r)?,
data: {
- let mut sz: usize = <u16 as Readable>::read(r)? as usize;
- let data = read_to_end(r)?;
- sz = cmp::min(data.len(), sz);
- match String::from_utf8(data[..sz as usize].to_vec()) {
+ let sz: usize = <u16 as Readable>::read(r)? as usize;
+ let mut data = Vec::with_capacity(sz);
+ data.resize(sz, 0);
+ r.read_exact(&mut data)?;
+ match String::from_utf8(data) {
+ Ok(s) => s,
+ Err(_) => return Err(DecodeError::InvalidValue),
+ }
+ }
+ })
+ }
+}
+
+impl Writeable for WarningMessage {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.channel_id.write(w)?;
+ (self.data.len() as u16).write(w)?;
+ w.write_all(self.data.as_bytes())?;
+ Ok(())
+ }
+}
+
+impl Readable for WarningMessage {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ Ok(Self {
+ channel_id: Readable::read(r)?,
+ data: {
+ let sz: usize = <u16 as Readable>::read(r)? as usize;
+ let mut data = Vec::with_capacity(sz);
+ data.resize(sz, 0);
+ r.read_exact(&mut data)?;
+ match String::from_utf8(data) {
Ok(s) => s,
Err(_) => return Err(DecodeError::InvalidValue),
}
});
}
if onionv2 {
- addresses.push(msgs::NetAddress::OnionV2 {
- addr: [255, 254, 253, 252, 251, 250, 249, 248, 247, 246],
- port: 9735
- });
+ addresses.push(msgs::NetAddress::OnionV2(
+ [255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 38, 7]
+ ));
}
if onionv3 {
addresses.push(msgs::NetAddress::OnionV3 {
assert_eq!(encoded_value, target_value);
}
+ #[test]
+ fn encoding_warning() {
+ let error = msgs::WarningMessage {
+ channel_id: [2; 32],
+ data: String::from("rust-lightning"),
+ };
+ let encoded_value = error.encode();
+ let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202000e727573742d6c696768746e696e67").unwrap();
+ assert_eq!(encoded_value, target_value);
+ }
+
#[test]
fn encoding_ping() {
let ping = msgs::Ping {