X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fmsgs.rs;h=122dd7737b996507e2d8fb5135af443172fb65f8;hb=843d25d750c3408d3f8f917764b8a58019a9dd81;hp=2c3e7df717bb09d744abbdf9da86893ed4159a28;hpb=ee68ffa5fdfcfa8ee7fe70512d9e079d621083bc;p=rust-lightning diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 2c3e7df7..122dd773 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -32,20 +32,23 @@ use bitcoin::hash_types::{Txid, BlockHash}; use ln::features::{ChannelFeatures, InitFeatures, NodeFeatures}; -use std::{cmp, fmt}; -use std::fmt::Debug; -use std::io::Read; +use prelude::*; +use core::{cmp, fmt}; +use core::fmt::Debug; +use io::{self, Read}; +use io_extras::read_to_end; use util::events::MessageSendEventsProvider; +use util::logger; use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt}; -use ln::channelmanager::{PaymentPreimage, PaymentHash, PaymentSecret}; +use ln::{PaymentPreimage, PaymentHash, PaymentSecret}; /// 21 million * 10^8 * 1000 pub(crate) const MAX_VALUE_MSAT: u64 = 21_000_000_0000_0000_000; /// An error in decoding a message or struct. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum DecodeError { /// A version byte specified something we don't know how to handle. /// Includes unknown realm byte in an OnionHopData packet @@ -62,20 +65,20 @@ pub enum DecodeError { BadLengthDescriptor, /// Error from std::io Io(/// (C-not exported) as ErrorKind doesn't have a reasonable mapping - ::std::io::ErrorKind), + io::ErrorKind), + /// The message included zlib-compressed values, which we don't support. + UnsupportedCompression, } /// An init message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct Init { - #[cfg(not(feature = "fuzztarget"))] - pub(crate) features: InitFeatures, - #[cfg(feature = "fuzztarget")] + /// The relevant features which the sender supports pub features: InitFeatures, } /// An error message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct ErrorMessage { /// The channel ID involved in the error pub channel_id: [u8; 32], @@ -87,7 +90,7 @@ pub struct ErrorMessage { } /// A ping message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct Ping { /// The desired response length pub ponglen: u16, @@ -97,7 +100,7 @@ pub struct Ping { } /// A pong message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct Pong { /// The pong packet size. /// This field is not sent on the wire. byteslen zeros are sent. @@ -105,7 +108,7 @@ pub struct Pong { } /// An open_channel message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct OpenChannel { /// The genesis hash of the blockchain where the channel is to be opened pub chain_hash: BlockHash, @@ -148,7 +151,7 @@ pub struct OpenChannel { } /// An accept_channel message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct AcceptChannel { /// A temporary channel ID, until the funding outpoint is announced pub temporary_channel_id: [u8; 32], @@ -183,7 +186,7 @@ pub struct AcceptChannel { } /// A funding_created message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct FundingCreated { /// A temporary channel ID, until the funding is established pub temporary_channel_id: [u8; 32], @@ -191,21 +194,21 @@ pub struct FundingCreated { pub funding_txid: Txid, /// The specific output index funding this channel pub funding_output_index: u16, - /// The signature of the channel initiator (funder) on the funding transaction + /// The signature of the channel initiator (funder) on the initial commitment transaction pub signature: Signature, } /// A funding_signed message to be sent or received from a peer -#[derive(Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct FundingSigned { /// The channel ID pub channel_id: [u8; 32], - /// The signature of the channel acceptor (fundee) on the funding transaction + /// The signature of the channel acceptor (fundee) on the initial commitment transaction pub signature: Signature, } /// A funding_locked message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct FundingLocked { /// The channel ID pub channel_id: [u8; 32], @@ -214,7 +217,7 @@ pub struct FundingLocked { } /// A shutdown message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct Shutdown { /// The channel ID pub channel_id: [u8; 32], @@ -223,8 +226,21 @@ pub struct Shutdown { pub scriptpubkey: Script, } +/// The minimum and maximum fees which the sender is willing to place on the closing transaction. +/// This is provided in [`ClosingSigned`] by both sides to indicate the fee range they are willing +/// to use. +#[derive(Clone, Debug, PartialEq)] +pub struct ClosingSignedFeeRange { + /// The minimum absolute fee, in satoshis, which the sender is willing to place on the closing + /// transaction. + pub min_fee_satoshis: u64, + /// The maximum absolute fee, in satoshis, which the sender is willing to place on the closing + /// transaction. + pub max_fee_satoshis: u64, +} + /// A closing_signed message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct ClosingSigned { /// The channel ID pub channel_id: [u8; 32], @@ -232,10 +248,13 @@ pub struct ClosingSigned { pub fee_satoshis: u64, /// A signature on the closing transaction pub signature: Signature, + /// The minimum and maximum fees which the sender is willing to accept, provided only by new + /// nodes. + pub fee_range: Option, } /// An update_add_htlc message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct UpdateAddHTLC { /// The channel ID pub channel_id: [u8; 32], @@ -251,7 +270,7 @@ pub struct UpdateAddHTLC { } /// An update_fulfill_htlc message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct UpdateFulfillHTLC { /// The channel ID pub channel_id: [u8; 32], @@ -262,7 +281,7 @@ pub struct UpdateFulfillHTLC { } /// An update_fail_htlc message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct UpdateFailHTLC { /// The channel ID pub channel_id: [u8; 32], @@ -272,7 +291,7 @@ pub struct UpdateFailHTLC { } /// An update_fail_malformed_htlc message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct UpdateFailMalformedHTLC { /// The channel ID pub channel_id: [u8; 32], @@ -284,7 +303,7 @@ pub struct UpdateFailMalformedHTLC { } /// A commitment_signed message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct CommitmentSigned { /// The channel ID pub channel_id: [u8; 32], @@ -295,7 +314,7 @@ pub struct CommitmentSigned { } /// A revoke_and_ack message to be sent or received from a peer -#[derive(Clone, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub struct RevokeAndACK { /// The channel ID pub channel_id: [u8; 32], @@ -306,7 +325,7 @@ pub struct RevokeAndACK { } /// An update_fee message to be sent or received from a peer -#[derive(PartialEq, Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct UpdateFee { /// The channel ID pub channel_id: [u8; 32], @@ -314,7 +333,7 @@ pub struct UpdateFee { pub feerate_per_kw: u32, } -#[derive(PartialEq, Clone)] +#[derive(Clone, Debug, PartialEq)] /// Proof that the sender knows the per-commitment secret of the previous commitment transaction. /// This is used to convince the recipient that the channel is at a certain commitment /// number even if they lost that data due to a local failure. Of course, the peer may lie @@ -328,7 +347,7 @@ pub struct DataLossProtect { } /// A channel_reestablish message to be sent or received from a peer -#[derive(PartialEq, Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct ChannelReestablish { /// The channel ID pub channel_id: [u8; 32], @@ -341,7 +360,7 @@ pub struct ChannelReestablish { } /// An announcement_signatures message to be sent or received from a peer -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct AnnouncementSignatures { /// The channel ID pub channel_id: [u8; 32], @@ -354,7 +373,7 @@ pub struct AnnouncementSignatures { } /// An address which can be used to connect to a remote peer -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum NetAddress { /// An IPv4 address/port on which the peer is listening. IPv4 { @@ -392,6 +411,17 @@ pub enum NetAddress { }, } impl NetAddress { + /// Gets the ID of this address type. Addresses in node_announcement messages should be sorted + /// by this. + pub(crate) fn get_id(&self) -> u8 { + match self { + &NetAddress::IPv4 {..} => { 1 }, + &NetAddress::IPv6 {..} => { 2 }, + &NetAddress::OnionV2 {..} => { 3 }, + &NetAddress::OnionV3 {..} => { 4 }, + } + } + /// Strict byte-length of address descriptor, 1-byte type not recorded fn len(&self) -> u16 { match self { @@ -407,7 +437,7 @@ impl NetAddress { } impl Writeable for NetAddress { - fn write(&self, writer: &mut W) -> Result<(), ::std::io::Error> { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { match self { &NetAddress::IPv4 { ref addr, ref port } => { 1u8.write(writer)?; @@ -471,8 +501,19 @@ impl Readable for Result { } } +impl Readable for NetAddress { + fn read(reader: &mut R) -> Result { + match Readable::read(reader) { + Ok(Ok(res)) => Ok(res), + Ok(Err(_)) => Err(DecodeError::UnknownVersion), + Err(e) => Err(e), + } + } +} + + /// The unsigned part of a node_announcement -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedNodeAnnouncement { /// The advertised features pub features: NodeFeatures, @@ -491,7 +532,7 @@ pub struct UnsignedNodeAnnouncement { pub(crate) excess_address_data: Vec, pub(crate) excess_data: Vec, } -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] /// A node_announcement message to be sent or received from a peer pub struct NodeAnnouncement { /// The signature by the node key @@ -501,7 +542,7 @@ pub struct NodeAnnouncement { } /// The unsigned part of a channel_announcement -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedChannelAnnouncement { /// The advertised channel features pub features: ChannelFeatures, @@ -520,7 +561,7 @@ pub struct UnsignedChannelAnnouncement { pub(crate) excess_data: Vec, } /// A channel_announcement message to be sent or received from a peer -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct ChannelAnnouncement { /// Authentication of the announcement by the first public node pub node_signature_1: Signature, @@ -535,7 +576,7 @@ pub struct ChannelAnnouncement { } /// The unsigned part of a channel_update -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct UnsignedChannelUpdate { /// The genesis hash of the blockchain where the channel is to be opened pub chain_hash: BlockHash, @@ -545,7 +586,14 @@ pub struct UnsignedChannelUpdate { pub timestamp: u32, /// Channel flags pub flags: u8, - /// The number of blocks to subtract from incoming HTLC cltv_expiry values + /// The number of blocks such that if: + /// `incoming_htlc.cltv_expiry < outgoing_htlc.cltv_expiry + cltv_expiry_delta` + /// then we need to fail the HTLC backwards. When forwarding an HTLC, cltv_expiry_delta determines + /// the outgoing HTLC's minimum cltv_expiry value -- so, if an incoming HTLC comes in with a + /// cltv_expiry of 100000, and the node we're forwarding to has a cltv_expiry_delta value of 10, + /// then we'll check that the outgoing HTLC's cltv_expiry value is at least 100010 before + /// forwarding. Note that the HTLC sender is the one who originally sets this value when + /// constructing the route. pub cltv_expiry_delta: u16, /// The minimum HTLC size incoming to sender, in milli-satoshi pub htlc_minimum_msat: u64, @@ -558,7 +606,7 @@ pub struct UnsignedChannelUpdate { pub(crate) excess_data: Vec, } /// A channel_update message to be sent or received from a peer -#[derive(PartialEq, Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct ChannelUpdate { /// A signature of the channel update pub signature: Signature, @@ -570,7 +618,7 @@ pub struct ChannelUpdate { /// UTXOs in a range of blocks. The recipient of a query makes a best /// effort to reply to the query using one or more reply_channel_range /// messages. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct QueryChannelRange { /// The genesis hash of the blockchain being queried pub chain_hash: BlockHash, @@ -587,7 +635,7 @@ pub struct QueryChannelRange { /// not be a perfect view of the network. The short_channel_ids in the /// reply are encoded. We only support encoding_type=0 uncompressed /// serialization and do not support encoding_type=1 zlib serialization. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct ReplyChannelRange { /// The genesis hash of the blockchain being queried pub chain_hash: BlockHash, @@ -609,7 +657,7 @@ pub struct ReplyChannelRange { /// reply_short_channel_ids_end message. The short_channel_ids sent in /// this query are encoded. We only support encoding_type=0 uncompressed /// serialization and do not support encoding_type=1 zlib serialization. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct QueryShortChannelIds { /// The genesis hash of the blockchain being queried pub chain_hash: BlockHash, @@ -621,7 +669,7 @@ pub struct QueryShortChannelIds { /// query_short_channel_ids message. The query recipient makes a best /// effort to respond based on their local network view which may not be /// a perfect view of the network. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct ReplyShortChannelIdsEnd { /// The genesis hash of the blockchain that was queried pub chain_hash: BlockHash, @@ -633,7 +681,7 @@ pub struct ReplyShortChannelIdsEnd { /// A gossip_timestamp_filter message is used by a node to request /// gossip relay for messages in the requested time range when the /// gossip_queries feature has been negotiated. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq)] pub struct GossipTimestampFilter { /// The genesis hash of the blockchain for channel and node information pub chain_hash: BlockHash, @@ -650,7 +698,7 @@ enum EncodingType { } /// Used to put an error message in a LightningError -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum ErrorAction { /// The peer took some action which made us think they were useless. Disconnect them. DisconnectPeer { @@ -658,7 +706,11 @@ pub enum ErrorAction { msg: Option }, /// The peer did something harmless that we weren't able to process, just log and ignore + // New code should *not* use this. New code must use IgnoreAndLog, below! IgnoreError, + /// 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 did something incorrect. Tell them. SendErrorMessage { /// The message to send. @@ -667,7 +719,7 @@ pub enum ErrorAction { } /// An Err type for failure to process messages. -#[derive(Clone)] +#[derive(Clone, Debug)] pub struct LightningError { /// A human-readable message describing the error pub err: String, @@ -677,7 +729,7 @@ pub struct LightningError { /// Struct used to return values from revoke_and_ack messages, containing a bunch of commitment /// transaction updates if they were pending. -#[derive(PartialEq, Clone)] +#[derive(Clone, Debug, PartialEq)] pub struct CommitmentUpdate { /// update_add_htlc messages which should be sent pub update_add_htlcs: Vec, @@ -693,41 +745,12 @@ pub struct CommitmentUpdate { pub commitment_signed: CommitmentSigned, } -/// The information we received from a peer along the route of a payment we originated. This is -/// returned by ChannelMessageHandler::handle_update_fail_htlc to be passed into -/// RoutingMessageHandler::handle_htlc_fail_channel_update to update our network map. -#[derive(Clone)] -pub enum HTLCFailChannelUpdate { - /// We received an error which included a full ChannelUpdate message. - ChannelUpdateMessage { - /// The unwrapped message we received - msg: ChannelUpdate, - }, - /// We received an error which indicated only that a channel has been closed - ChannelClosed { - /// The short_channel_id which has now closed. - short_channel_id: u64, - /// when this true, this channel should be permanently removed from the - /// consideration. Otherwise, this channel can be restored as new channel_update is received - is_permanent: bool, - }, - /// We received an error which indicated only that a node has failed - NodeFailure { - /// The node_id that has failed. - node_id: PublicKey, - /// when this true, node should be permanently removed from the - /// consideration. Otherwise, the channels connected to this node can be - /// restored as new channel_update is received - is_permanent: bool, - } -} - /// Messages could have optional fields to use with extended features /// As we wish to serialize these differently from Options (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. /// (C-not exported) due to a free generic in T -#[derive(Clone, PartialEq, Debug)] +#[derive(Clone, Debug, PartialEq)] pub enum OptionalField { /// Optional field is included in message Present(T), @@ -739,7 +762,7 @@ pub enum OptionalField { /// /// Messages MAY be called in parallel when they originate from different their_node_ids, however /// they MUST NOT be called in parallel when the two calls have the same their_node_id. -pub trait ChannelMessageHandler : MessageSendEventsProvider + Send + Sync { +pub trait ChannelMessageHandler : MessageSendEventsProvider { //Channel init: /// Handle an incoming open_channel message from the given peer. fn handle_open_channel(&self, their_node_id: &PublicKey, their_features: InitFeatures, msg: &OpenChannel); @@ -754,7 +777,7 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider + Send + Sync { // Channl close: /// Handle an incoming shutdown message from the given peer. - fn handle_shutdown(&self, their_node_id: &PublicKey, msg: &Shutdown); + fn handle_shutdown(&self, their_node_id: &PublicKey, their_features: &InitFeatures, msg: &Shutdown); /// Handle an incoming closing_signed message from the given peer. fn handle_closing_signed(&self, their_node_id: &PublicKey, msg: &ClosingSigned); @@ -791,6 +814,9 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider + Send + Sync { /// Handle an incoming channel_reestablish message from the given peer. fn handle_channel_reestablish(&self, their_node_id: &PublicKey, msg: &ChannelReestablish); + /// Handle an incoming channel update from the given peer. + fn handle_channel_update(&self, their_node_id: &PublicKey, msg: &ChannelUpdate); + // Error: /// Handle an incoming error message from the given peer. fn handle_error(&self, their_node_id: &PublicKey, msg: &ErrorMessage); @@ -803,7 +829,7 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider + Send + Sync { /// For `gossip_queries` messages there are potential DoS vectors when handling /// inbound queries. Implementors using an on-disk network graph should be aware of /// repeated disk I/O for queries accessing different parts of the network graph. -pub trait RoutingMessageHandler : Send + Sync + MessageSendEventsProvider { +pub trait RoutingMessageHandler : MessageSendEventsProvider { /// Handle an incoming node_announcement message, returning true if it should be forwarded on, /// false or returning an Err otherwise. fn handle_node_announcement(&self, msg: &NodeAnnouncement) -> Result; @@ -813,8 +839,6 @@ pub trait RoutingMessageHandler : Send + Sync + MessageSendEventsProvider { /// Handle an incoming channel_update message, returning true if it should be forwarded on, /// false or returning an Err otherwise. fn handle_channel_update(&self, msg: &ChannelUpdate) -> Result; - /// Handle some updates to the route graph that we learned due to an outbound failed payment. - fn handle_htlc_fail_channel_update(&self, update: &HTLCFailChannelUpdate); /// Gets a subset of the channel announcements and updates required to dump our routing table /// to a remote node, starting at the short_channel_id indicated by starting_point and /// including the batch_amount entries immediately higher in numerical value than starting_point. @@ -846,7 +870,8 @@ pub trait RoutingMessageHandler : Send + Sync + MessageSendEventsProvider { } mod fuzzy_internal_msgs { - use ln::channelmanager::PaymentSecret; + use prelude::*; + use ln::{PaymentPreimage, PaymentSecret}; // These types aren't intended to be pub, but are exposed for direct fuzzing (as we deserialize // them from untrusted input): @@ -867,6 +892,7 @@ mod fuzzy_internal_msgs { }, FinalNode { payment_data: Option, + keysend_preimage: Option, }, } @@ -912,7 +938,13 @@ impl PartialEq for OnionPacket { } } -#[derive(Clone, PartialEq)] +impl fmt::Debug for OnionPacket { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + f.write_fmt(format_args!("OnionPacket version {} with hmac {:?}", self.version, &self.hmac[..])) + } +} + +#[derive(Clone, Debug, PartialEq)] pub(crate) struct OnionErrorPacket { // This really should be a constant size slice, but the spec lets these things be up to 128KB? // (TODO) We limit it in decode to much lower... @@ -928,19 +960,14 @@ impl fmt::Display for DecodeError { DecodeError::ShortRead => f.write_str("Packet extended beyond the provided bytes"), DecodeError::BadLengthDescriptor => f.write_str("A length descriptor in the packet didn't describe the later data correctly"), DecodeError::Io(ref e) => e.fmt(f), + DecodeError::UnsupportedCompression => f.write_str("We don't support receiving messages with zlib-compressed fields"), } } } -impl fmt::Debug for LightningError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str(self.err.as_str()) - } -} - -impl From<::std::io::Error> for DecodeError { - fn from(e: ::std::io::Error) -> Self { - if e.kind() == ::std::io::ErrorKind::UnexpectedEof { +impl From for DecodeError { + fn from(e: io::Error) -> Self { + if e.kind() == io::ErrorKind::UnexpectedEof { DecodeError::ShortRead } else { DecodeError::Io(e.kind()) @@ -949,7 +976,7 @@ impl From<::std::io::Error> for DecodeError { } impl Writeable for OptionalField