X-Git-Url: http://git.bitcoin.ninja/index.cgi?a=blobdiff_plain;f=lightning%2Fsrc%2Fln%2Fmsgs.rs;h=0c23d4425f8663ebe6fce310692b2dc11bc89e08;hb=c383f06538ac664fe3312daf765595ba106d5b98;hp=27f8544e3b52021345f66ccd9c434beea2876bf2;hpb=7884bc43a3df76f8f6b0ef241a5c9dcd85ebd312;p=rust-lightning diff --git a/lightning/src/ln/msgs.rs b/lightning/src/ln/msgs.rs index 27f8544e..0c23d442 100644 --- a/lightning/src/ln/msgs.rs +++ b/lightning/src/ln/msgs.rs @@ -24,9 +24,10 @@ //! raw socket events into your non-internet-facing system and then send routing events back to //! track the network on the less-secure system. +use bitcoin::blockdata::constants::ChainHash; use bitcoin::secp256k1::PublicKey; use bitcoin::secp256k1::ecdsa::Signature; -use bitcoin::{secp256k1, Witness, Transaction}; +use bitcoin::{secp256k1, Witness}; use bitcoin::blockdata::script::Script; use bitcoin::hash_types::{Txid, BlockHash}; @@ -42,7 +43,7 @@ use crate::io_extras::read_to_end; use crate::events::{MessageSendEventsProvider, OnionMessageProvider}; use crate::util::logger; -use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname}; +use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited}; use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; @@ -88,6 +89,10 @@ pub enum DecodeError { pub struct Init { /// The relevant features which the sender supports. pub features: InitFeatures, + /// Indicates chains the sender is interested in. + /// + /// If there are no common chains, the connection will be closed. + pub networks: Option>, /// The receipient's network address. /// /// This adds the option to report a remote IP address back to a connecting peer using the init @@ -425,45 +430,6 @@ pub struct ChannelReady { pub short_channel_id_alias: Option, } -/// A wrapper for a `Transaction` which can only be constructed with [`TransactionU16LenLimited::new`] -/// if the `Transaction`'s consensus-serialized length is <= u16::MAX. -/// -/// Use [`TransactionU16LenLimited::into_transaction`] to convert into the contained `Transaction`. -#[derive(Clone, Debug, PartialEq, Eq)] -pub struct TransactionU16LenLimited(Transaction); - -impl TransactionU16LenLimited { - /// Constructs a new `TransactionU16LenLimited` from a `Transaction` only if it's consensus- - /// serialized length is <= u16::MAX. - pub fn new(transaction: Transaction) -> Result { - if transaction.serialized_length() > (u16::MAX as usize) { - Err(()) - } else { - Ok(Self(transaction)) - } - } - - /// Consumes this `TransactionU16LenLimited` and returns its contained `Transaction`. - pub fn into_transaction(self) -> Transaction { - self.0 - } -} - -impl Writeable for TransactionU16LenLimited { - fn write(&self, w: &mut W) -> Result<(), io::Error> { - (self.0.serialized_length() as u16).write(w)?; - self.0.write(w) - } -} - -impl Readable for TransactionU16LenLimited { - fn read(r: &mut R) -> Result { - let len = ::read(r)?; - let mut tx_reader = FixedLengthReader::new(r, len as u64); - Ok(Self(Readable::read(&mut tx_reader)?)) - } -} - /// A tx_add_input message for adding an input during interactive transaction construction /// // TODO(dual_funding): Add spec link for `tx_add_input`. @@ -644,6 +610,11 @@ pub struct UpdateAddHTLC { pub payment_hash: PaymentHash, /// The expiry height of the HTLC pub cltv_expiry: u32, + /// The extra fee skimmed by the sender of this message. See + /// [`ChannelConfig::accept_underpaying_htlcs`]. + /// + /// [`ChannelConfig::accept_underpaying_htlcs`]: crate::util::config::ChannelConfig::accept_underpaying_htlcs + pub skimmed_fee_msat: Option, pub(crate) onion_routing_packet: OnionPacket, } @@ -850,7 +821,7 @@ impl NetAddress { } impl Writeable for NetAddress { -fn write(&self, writer: &mut W) -> Result<(), io::Error> { + fn write(&self, writer: &mut W) -> Result<(), io::Error> { match self { &NetAddress::IPv4 { ref addr, ref port } => { 1u8.write(writer)?; @@ -1002,7 +973,11 @@ pub struct UnsignedChannelAnnouncement { pub bitcoin_key_1: NodeId, /// The funding key for the second node pub bitcoin_key_2: NodeId, - pub(crate) excess_data: Vec, + /// Excess data which was signed as a part of the message which we do not (yet) understand how + /// to decode. + /// + /// This is stored to ensure forward-compatibility as new fields are added to the lightning gossip protocol. + pub excess_data: Vec, } /// A [`channel_announcement`] message to be sent to or received from a peer. /// @@ -1176,6 +1151,11 @@ pub enum ErrorAction { /// An error message which we should make an effort to send before we disconnect. msg: Option }, + /// The peer did something incorrect. Tell them without closing any channels and disconnect them. + DisconnectPeerWithWarning { + /// A warning message which we should make an effort to send before we disconnect. + msg: WarningMessage, + }, /// 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, @@ -1329,6 +1309,12 @@ pub trait ChannelMessageHandler : MessageSendEventsProvider { /// /// Note that this method is called before [`Self::peer_connected`]. fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures; + + /// Gets the genesis hashes for this `ChannelMessageHandler` indicating which chains it supports. + /// + /// If it's `None`, then no particular network chain hash compatibility will be enforced when + /// connecting to peers. + fn get_genesis_hashes(&self) -> Option>; } /// A trait to describe an object which can receive routing messages. @@ -1762,7 +1748,8 @@ impl Writeable for Init { self.features.write_up_to_13(w)?; self.features.write(w)?; encode_tlv_stream!(w, { - (3, self.remote_network_address, option) + (1, self.networks.as_ref().map(|n| WithoutLength(n)), option), + (3, self.remote_network_address, option), }); Ok(()) } @@ -1773,11 +1760,14 @@ impl Readable for Init { let global_features: InitFeatures = Readable::read(r)?; let features: InitFeatures = Readable::read(r)?; let mut remote_network_address: Option = None; + let mut networks: Option>> = None; decode_tlv_stream!(r, { + (1, networks, option), (3, remote_network_address, option) }); Ok(Init { - features: features.or(global_features), + features: features | global_features, + networks: networks.map(|n| n.0), remote_network_address, }) } @@ -1922,8 +1912,10 @@ impl_writeable_msg!(UpdateAddHTLC, { amount_msat, payment_hash, cltv_expiry, - onion_routing_packet -}, {}); + onion_routing_packet, +}, { + (65537, skimmed_fee_msat, option) +}); impl Readable for OnionMessage { fn read(r: &mut R) -> Result { @@ -2450,14 +2442,14 @@ impl_writeable_msg!(GossipTimestampFilter, { #[cfg(test)] mod tests { + use bitcoin::blockdata::constants::ChainHash; use bitcoin::{Transaction, PackedLockTime, TxIn, Script, Sequence, Witness, TxOut}; use hex; use crate::ln::{PaymentPreimage, PaymentHash, PaymentSecret}; use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures}; - use crate::ln::msgs::{self, TransactionU16LenLimited}; - use crate::ln::msgs::{FinalOnionHopData, OnionErrorPacket, OnionHopDataFormat}; + use crate::ln::msgs::{self, FinalOnionHopData, OnionErrorPacket, OnionHopDataFormat}; use crate::routing::gossip::{NodeAlias, NodeId}; - use crate::util::ser::{Writeable, Readable, Hostname}; + use crate::util::ser::{Writeable, Readable, Hostname, TransactionU16LenLimited}; use bitcoin::hashes::hex::FromHex; use bitcoin::util::address::Address; @@ -3349,7 +3341,8 @@ mod tests { amount_msat: 3608586615801332854, payment_hash: PaymentHash([1; 32]), cltv_expiry: 821716, - onion_routing_packet + onion_routing_packet, + skimmed_fee_msat: None, }; let encoded_value = update_add_htlc.encode(); let target_value = hex::decode("020202020202020202020202020202020202020202020202020202020202020200083a840000034d32144668701144760101010101010101010101010101010101010101010101010101010101010101000c89d4ff031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010202020202020202020202020202020202020202020202020202020202020202").unwrap(); @@ -3458,27 +3451,36 @@ mod tests { #[test] fn encoding_init() { + let mainnet_hash = ChainHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(); assert_eq!(msgs::Init { features: InitFeatures::from_le_bytes(vec![0xFF, 0xFF, 0xFF]), + networks: Some(vec![mainnet_hash]), remote_network_address: None, - }.encode(), hex::decode("00023fff0003ffffff").unwrap()); + }.encode(), hex::decode("00023fff0003ffffff01206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); assert_eq!(msgs::Init { features: InitFeatures::from_le_bytes(vec![0xFF]), + networks: None, remote_network_address: None, }.encode(), hex::decode("0001ff0001ff").unwrap()); assert_eq!(msgs::Init { features: InitFeatures::from_le_bytes(vec![]), + networks: Some(vec![mainnet_hash]), remote_network_address: None, - }.encode(), hex::decode("00000000").unwrap()); - + }.encode(), hex::decode("0000000001206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap()); + assert_eq!(msgs::Init { + features: InitFeatures::from_le_bytes(vec![]), + networks: Some(vec![ChainHash::from(&[1; 32][..]), ChainHash::from(&[2; 32][..])]), + remote_network_address: None, + }.encode(), hex::decode("00000000014001010101010101010101010101010101010101010101010101010101010101010202020202020202020202020202020202020202020202020202020202020202").unwrap()); let init_msg = msgs::Init { features: InitFeatures::from_le_bytes(vec![]), + networks: Some(vec![mainnet_hash]), remote_network_address: Some(msgs::NetAddress::IPv4 { addr: [127, 0, 0, 1], port: 1000, }), }; let encoded_value = init_msg.encode(); - let target_value = hex::decode("000000000307017f00000103e8").unwrap(); + let target_value = hex::decode("0000000001206fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d61900000000000307017f00000103e8").unwrap(); assert_eq!(encoded_value, target_value); assert_eq!(msgs::Init::read(&mut Cursor::new(&target_value)).unwrap(), init_msg); } @@ -3762,7 +3764,7 @@ mod tests { let test_bytes = vec![42u8; 1000]; if let OnionHopDataFormat::NonFinalNode { short_channel_id } = payload.format { _encode_varint_length_prefixed_tlv!(&mut encoded_payload, { - (1, test_bytes, vec_type), + (1, test_bytes, required_vec), (2, HighZeroBytesDroppedBigSize(payload.amt_to_forward), required), (4, HighZeroBytesDroppedBigSize(payload.outgoing_cltv_value), required), (6, short_channel_id, required)