GEN_TEST ReplyChannelRange test_msg ""
GEN_TEST ErrorMessage test_msg_hole ", 32, 2"
+GEN_TEST WarningMessage test_msg_hole ", 32, 2"
GEN_TEST ChannelUpdate test_msg_hole ", 108, 1"
pub mod msg_query_short_channel_ids;
pub mod msg_reply_channel_range;
pub mod msg_error_message;
+pub mod msg_warning_message;
pub mod msg_channel_update;
--- /dev/null
+// 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.
+
+// This file is auto-generated by gen_target.sh based on msg_target_template.txt
+// To modify it, modify msg_target_template.txt and run gen_target.sh instead.
+
+use lightning::ln::msgs;
+
+use msg_targets::utils::VecWriter;
+use utils::test_logger;
+
+#[inline]
+pub fn msg_warning_message_test<Out: test_logger::Output>(data: &[u8], _out: Out) {
+ test_msg_hole!(msgs::WarningMessage, data, 32, 2);
+}
+
+#[no_mangle]
+pub extern "C" fn msg_warning_message_run(data: *const u8, datalen: usize) {
+ let data = unsafe { std::slice::from_raw_parts(data, datalen) };
+ test_msg_hole!(msgs::WarningMessage, data, 32, 2);
+}
assert_eq!(self.channel_state & ChannelState::ShutdownComplete as u32, 0);
if !script::is_bolt2_compliant(&msg.scriptpubkey, their_features) {
- return Err(ChannelError::Close(format!("Got a nonstandard scriptpubkey ({}) from remote peer", msg.scriptpubkey.to_bytes().to_hex())));
+ return Err(ChannelError::Warn(format!("Got a nonstandard scriptpubkey ({}) from remote peer", msg.scriptpubkey.to_bytes().to_hex())));
}
if self.counterparty_shutdown_scriptpubkey.is_some() {
if Some(&msg.scriptpubkey) != self.counterparty_shutdown_scriptpubkey.as_ref() {
- return Err(ChannelError::Close(format!("Got shutdown request with a scriptpubkey ({}) which did not match their previous scriptpubkey.", msg.scriptpubkey.to_bytes().to_hex())));
+ return Err(ChannelError::Warn(format!("Got shutdown request with a scriptpubkey ({}) which did not match their previous scriptpubkey.", msg.scriptpubkey.to_bytes().to_hex())));
}
} else {
self.counterparty_shutdown_scriptpubkey = Some(msg.scriptpubkey.clone());
Self {
err: match err {
ChannelError::Warn(msg) => LightningError {
- err: msg,
- action: msgs::ErrorAction::IgnoreError,
+ err: msg.clone(),
+ action: msgs::ErrorAction::SendWarningMessage {
+ msg: msgs::WarningMessage {
+ channel_id,
+ data: msg
+ },
+ log_level: Level::Warn,
+ },
},
ChannelError::Ignore(msg) => LightningError {
err: msg,
($self: ident, $err: expr, $short_to_id: expr, $channel: expr, $channel_id: expr) => {
match $err {
ChannelError::Warn(msg) => {
- //TODO: Once warning messages are merged, we should send a `warning` message to our
- //peer here.
- (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $channel_id.clone()))
+ (false, MsgHandleErrInternal::from_chan_no_close(ChannelError::Warn(msg), $channel_id.clone()))
},
ChannelError::Ignore(msg) => {
(false, MsgHandleErrInternal::from_chan_no_close(ChannelError::Ignore(msg), $channel_id.clone()))
}
}
+#[cfg(test)]
+macro_rules! check_warn_msg {
+ ($node: expr, $recipient_node_id: expr, $chan_id: expr) => {{
+ let msg_events = $node.node.get_and_clear_pending_msg_events();
+ assert_eq!(msg_events.len(), 1);
+ match msg_events[0] {
+ MessageSendEvent::HandleError { action: ErrorAction::SendWarningMessage { ref msg, log_level: _ }, node_id } => {
+ assert_eq!(node_id, $recipient_node_id);
+ assert_eq!(msg.channel_id, $chan_id);
+ msg.data.clone()
+ },
+ _ => panic!("Unexpected event"),
+ }
+ }}
+}
+
/// Check that a channel's closing channel update has been broadcasted, and optionally
/// check whether an error message event has occurred.
#[macro_export]
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,
}
/// 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),
}
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 {
self.enqueue_message(peer, &msg);
continue;
},
+ msgs::ErrorAction::SendWarningMessage { msg, log_level } => {
+ log_given_level!(self.logger, log_level, "Error handling message{}; sending warning message with: {}", OptionalFromDebugger(&peer.their_node_id), e.err);
+ self.enqueue_message(peer, &msg);
+ continue;
+ },
}
}
}
Ok(x) => x,
Err(e) => {
match e {
- msgs::DecodeError::UnknownVersion => return Err(PeerHandleError { no_connection_possible: false }),
- msgs::DecodeError::UnknownRequiredFeature => {
+ (msgs::DecodeError::UnknownRequiredFeature, _) => {
log_gossip!(self.logger, "Got a channel/node announcement with an unknown required feature flag, you may want to update!");
continue;
}
- msgs::DecodeError::InvalidValue => {
+ (msgs::DecodeError::UnsupportedCompression, _) => {
+ log_gossip!(self.logger, "We don't support zlib-compressed message fields, sending a warning and ignoring message");
+ self.enqueue_message(peer, &msgs::WarningMessage { channel_id: [0; 32], data: "Unsupported message compression: zlib".to_owned() });
+ continue;
+ }
+ (_, Some(ty)) if is_gossip_msg(ty) => {
+ log_gossip!(self.logger, "Got an invalid value while deserializing a gossip message");
+ self.enqueue_message(peer, &msgs::WarningMessage { channel_id: [0; 32], data: "Unreadable/bogus gossip message".to_owned() });
+ continue;
+ }
+ (msgs::DecodeError::UnknownVersion, _) => return Err(PeerHandleError { no_connection_possible: false }),
+ (msgs::DecodeError::InvalidValue, _) => {
log_debug!(self.logger, "Got an invalid value while deserializing message");
return Err(PeerHandleError { no_connection_possible: false });
}
- msgs::DecodeError::ShortRead => {
+ (msgs::DecodeError::ShortRead, _) => {
log_debug!(self.logger, "Deserialization failed due to shortness of message");
return Err(PeerHandleError { no_connection_possible: false });
}
- msgs::DecodeError::BadLengthDescriptor => return Err(PeerHandleError { no_connection_possible: false }),
- msgs::DecodeError::Io(_) => return Err(PeerHandleError { no_connection_possible: false }),
- msgs::DecodeError::UnsupportedCompression => {
- log_gossip!(self.logger, "We don't support zlib-compressed message fields, ignoring message");
- continue;
- }
+ (msgs::DecodeError::BadLengthDescriptor, _) => return Err(PeerHandleError { no_connection_possible: false }),
+ (msgs::DecodeError::Io(_), _) => return Err(PeerHandleError { no_connection_possible: false }),
}
}
};
return Err(PeerHandleError{ no_connection_possible: true }.into());
}
},
+ wire::Message::Warning(msg) => {
+ let mut data_is_printable = true;
+ for b in msg.data.bytes() {
+ if b < 32 || b > 126 {
+ data_is_printable = false;
+ break;
+ }
+ }
+
+ if data_is_printable {
+ log_debug!(self.logger, "Got warning message from {}: {}", log_pubkey!(peer.their_node_id.unwrap()), msg.data);
+ } else {
+ log_debug!(self.logger, "Got warning message from {} with non-ASCII error message", log_pubkey!(peer.their_node_id.unwrap()));
+ }
+ },
wire::Message::Ping(msg) => {
if msg.ponglen < 65532 {
msg.data);
self.enqueue_message(get_peer_for_forwarding!(node_id), msg);
},
+ msgs::ErrorAction::SendWarningMessage { ref msg, ref log_level } => {
+ log_given_level!(self.logger, *log_level, "Handling SendWarningMessage HandleError event in peer_handler for node {} with message {}",
+ log_pubkey!(node_id),
+ msg.data);
+ self.enqueue_message(get_peer_for_forwarding!(node_id), msg);
+ },
}
},
MessageSendEvent::SendChannelRangeQuery { ref node_id, ref msg } => {
let flags = InitFeatures::known();
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000, flags.clone(), flags.clone());
nodes[0].node.close_channel(&OutPoint { txid: chan.3.txid(), index: 0 }.to_channel_id()).unwrap();
- let mut node_0_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id());
+ let node_0_orig_shutdown = get_event_msg!(nodes[0], MessageSendEvent::SendShutdown, nodes[2].node.get_our_node_id());
+ let mut node_0_shutdown = node_0_orig_shutdown.clone();
node_0_shutdown.scriptpubkey = Builder::new().push_opcode(opcodes::all::OP_RETURN).into_script().to_p2sh();
- // Test we enforce upfront_scriptpbukey if by providing a diffrent one at closing that we disconnect peer
+ // Test we enforce upfront_scriptpbukey if by providing a different one at closing that we warn
+ // the peer and ignore the message.
nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
- assert!(regex::Regex::new(r"Got shutdown request with a scriptpubkey \([A-Fa-f0-9]+\) which did not match their previous scriptpubkey.").unwrap().is_match(check_closed_broadcast!(nodes[2], true).unwrap().data.as_str()));
- check_closed_event!(nodes[2], 1, ClosureReason::ProcessingError { err: "Got shutdown request with a scriptpubkey (a91441c98a140039816273e50db317422c11c2bfcc8887) which did not match their previous scriptpubkey.".to_string() });
- check_added_monitors!(nodes[2], 1);
+ assert!(regex::Regex::new(r"Got shutdown request with a scriptpubkey \([A-Fa-f0-9]+\) which did not match their previous scriptpubkey.")
+ .unwrap().is_match(&check_warn_msg!(nodes[2], nodes[0].node.get_our_node_id(), chan.2)));
+ // This allows nodes[2] to retry the shutdown message, which should get a response:
+ nodes[2].node.handle_shutdown(&nodes[0].node.get_our_node_id(), &InitFeatures::known(), &node_0_orig_shutdown);
+ get_event_msg!(nodes[2], MessageSendEvent::SendShutdown, nodes[0].node.get_our_node_id());
// We test that in case of peer committing upfront to a script, if it doesn't change at closing, we sign
let chan = create_announced_chan_between_nodes_with_value(&nodes, 0, 2, 1000000, 1000000, flags.clone(), flags.clone());
node_0_shutdown.scriptpubkey = unsupported_shutdown_script.into_inner();
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &node_cfgs[1].features, &node_0_shutdown);
- let events = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(events.len(), 2);
- match events[1] {
- MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => {
- assert_eq!(node_id, nodes[1].node.get_our_node_id());
- assert_eq!(msg.data, "Got a nonstandard scriptpubkey (60020028) from remote peer".to_owned());
- },
- _ => panic!("Unexpected event"),
- }
- check_added_monitors!(nodes[0], 1);
- check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: "Got a nonstandard scriptpubkey (60020028) from remote peer".to_string() });
+ assert_eq!(&check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2),
+ "Got a nonstandard scriptpubkey (60020028) from remote peer");
}
#[test]
.into_script();
nodes[0].node.handle_shutdown(&nodes[1].node.get_our_node_id(), &InitFeatures::known(), &node_0_shutdown);
- let events = nodes[0].node.get_and_clear_pending_msg_events();
- assert_eq!(events.len(), 2);
- match events[1] {
- MessageSendEvent::HandleError { action: ErrorAction::SendErrorMessage { ref msg }, node_id } => {
- assert_eq!(node_id, nodes[1].node.get_our_node_id());
- assert_eq!(msg.data, "Got a nonstandard scriptpubkey (00020000) from remote peer".to_owned())
- },
- _ => panic!("Unexpected event"),
- }
- check_added_monitors!(nodes[0], 1);
- check_closed_event!(nodes[0], 1, ClosureReason::ProcessingError { err: "Got a nonstandard scriptpubkey (00020000) from remote peer".to_string() });
+ assert_eq!(&check_warn_msg!(nodes[0], nodes[1].node.get_our_node_id(), chan.2),
+ "Got a nonstandard scriptpubkey (00020000) from remote peer");
}
#[derive(PartialEq)]
if timeout_step != TimeoutStep::AfterShutdown {
nodes[1].node.handle_closing_signed(&nodes[0].node.get_our_node_id(), &node_0_closing_signed);
- // At this point nodes[1] should send back a warning message indicating it disagrees with the
- // given channel-closing fee. Currently we do not implement warning messages so instead we
- // remain silent here.
- assert!(nodes[1].node.get_and_clear_pending_msg_events().is_empty());
+ assert!(check_warn_msg!(nodes[1], nodes[0].node.get_our_node_id(), chan_id)
+ .starts_with("Unable to come to consensus about closing feerate"));
// Now deliver a mutated closing_signed indicating a higher acceptable fee range, which
// nodes[1] should happily accept and respond to.
pub(crate) enum Message<T> where T: core::fmt::Debug + Type {
Init(msgs::Init),
Error(msgs::ErrorMessage),
+ Warning(msgs::WarningMessage),
Ping(msgs::Ping),
Pong(msgs::Pong),
OpenChannel(msgs::OpenChannel),
match self {
&Message::Init(ref msg) => msg.type_id(),
&Message::Error(ref msg) => msg.type_id(),
+ &Message::Warning(ref msg) => msg.type_id(),
&Message::Ping(ref msg) => msg.type_id(),
&Message::Pong(ref msg) => msg.type_id(),
&Message::OpenChannel(ref msg) => msg.type_id(),
/// # Errors
///
/// Returns an error if the message payload code not be decoded as the specified type.
-pub(crate) fn read<R: io::Read, T, H: core::ops::Deref>(
- buffer: &mut R,
- custom_reader: H,
-) -> Result<Message<T>, msgs::DecodeError>
-where
+pub(crate) fn read<R: io::Read, T, H: core::ops::Deref>(buffer: &mut R, custom_reader: H)
+-> Result<Message<T>, (msgs::DecodeError, Option<u16>)> where
+ T: core::fmt::Debug + Type + Writeable,
+ H::Target: CustomMessageReader<CustomMessage = T>,
+{
+ let message_type = <u16 as Readable>::read(buffer).map_err(|e| (e, None))?;
+ do_read(buffer, message_type, custom_reader).map_err(|e| (e, Some(message_type)))
+}
+
+fn do_read<R: io::Read, T, H: core::ops::Deref>(buffer: &mut R, message_type: u16, custom_reader: H)
+-> Result<Message<T>, msgs::DecodeError> where
T: core::fmt::Debug + Type + Writeable,
H::Target: CustomMessageReader<CustomMessage = T>,
{
- let message_type = <u16 as Readable>::read(buffer)?;
match message_type {
msgs::Init::TYPE => {
Ok(Message::Init(Readable::read(buffer)?))
msgs::ErrorMessage::TYPE => {
Ok(Message::Error(Readable::read(buffer)?))
},
+ msgs::WarningMessage::TYPE => {
+ Ok(Message::Warning(Readable::read(buffer)?))
+ },
msgs::Ping::TYPE => {
Ok(Message::Ping(Readable::read(buffer)?))
},
const TYPE: u16 = 17;
}
+impl Encode for msgs::WarningMessage {
+ const TYPE: u16 = 1;
+}
+
impl Encode for msgs::Ping {
const TYPE: u16 = 18;
}
}
macro_rules! secp_verify_sig {
- ( $secp_ctx: expr, $msg: expr, $sig: expr, $pubkey: expr ) => {
+ ( $secp_ctx: expr, $msg: expr, $sig: expr, $pubkey: expr, $msg_type: expr ) => {
match $secp_ctx.verify($msg, $sig, $pubkey) {
Ok(_) => {},
- Err(_) => return Err(LightningError{err: "Invalid signature from remote node".to_owned(), action: ErrorAction::IgnoreError}),
+ Err(_) => {
+ return Err(LightningError {
+ err: format!("Invalid signature on {} message", $msg_type),
+ action: ErrorAction::SendWarningMessage {
+ msg: msgs::WarningMessage {
+ channel_id: [0; 32],
+ data: format!("Invalid signature on {} message", $msg_type),
+ },
+ log_level: Level::Trace,
+ },
+ });
+ },
}
};
}
/// routing messages from a source using a protocol other than the lightning P2P protocol.
pub fn update_node_from_announcement<T: secp256k1::Verification>(&self, msg: &msgs::NodeAnnouncement, secp_ctx: &Secp256k1<T>) -> Result<(), LightningError> {
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id);
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.signature, &msg.contents.node_id, "node_announcement");
self.update_node_from_announcement_intern(&msg.contents, Some(&msg))
}
C::Target: chain::Access,
{
let msg_hash = hash_to_message!(&Sha256dHash::hash(&msg.contents.encode()[..])[..]);
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1);
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2);
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1);
- secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2);
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_1, &msg.contents.node_id_1, "channel_announcement");
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.node_signature_2, &msg.contents.node_id_2, "channel_announcement");
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_1, &msg.contents.bitcoin_key_1, "channel_announcement");
+ secp_verify_sig!(secp_ctx, &msg_hash, &msg.bitcoin_signature_2, &msg.contents.bitcoin_key_2, "channel_announcement");
self.update_channel_from_unsigned_announcement_intern(&msg.contents, Some(msg), chain_access)
}
secp_verify_sig!(ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_two.as_slice()).map_err(|_| LightningError{
err: "Couldn't parse source node pubkey".to_owned(),
action: ErrorAction::IgnoreAndLog(Level::Debug)
- })?);
+ })?, "channel_update");
}
maybe_update_channel_info!(channel.two_to_one, channel.node_two);
} else {
secp_verify_sig!(ctx, &msg_hash, &sig, &PublicKey::from_slice(channel.node_one.as_slice()).map_err(|_| LightningError{
err: "Couldn't parse destination node pubkey".to_owned(),
action: ErrorAction::IgnoreAndLog(Level::Debug)
- })?);
+ })?, "channel_update");
}
maybe_update_channel_info!(channel.one_to_two, channel.node_one);
}
contents: valid_announcement.contents.clone()
}) {
Ok(_) => panic!(),
- Err(e) => assert_eq!(e.err, "Invalid signature from remote node")
+ Err(e) => assert_eq!(e.err, "Invalid signature on node_announcement message")
};
let announcement_with_data = get_signed_node_announcement(|unsigned_announcement| {
invalid_sig_announcement.contents.excess_data = Vec::new();
match net_graph_msg_handler.handle_channel_announcement(&invalid_sig_announcement) {
Ok(_) => panic!(),
- Err(e) => assert_eq!(e.err, "Invalid signature from remote node")
+ Err(e) => assert_eq!(e.err, "Invalid signature on channel_announcement message")
};
let channel_to_itself_announcement = get_signed_channel_announcement(|_| {}, node_1_privkey, node_1_privkey, &secp_ctx);
invalid_sig_channel_update.signature = secp_ctx.sign(&fake_msghash, node_1_privkey);
match net_graph_msg_handler.handle_channel_update(&invalid_sig_channel_update) {
Ok(_) => panic!(),
- Err(e) => assert_eq!(e.err, "Invalid signature from remote node")
+ Err(e) => assert_eq!(e.err, "Invalid signature on channel_update message")
};
}