use bitcoin::hash_types::{Txid, BlockHash};
use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
+use ln::onion_utils;
+use onion_message;
use prelude::*;
use core::fmt;
use util::events::MessageSendEventsProvider;
use util::logger;
-use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt};
+use util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, Hostname};
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
pub(crate) onion_routing_packet: OnionPacket,
}
+ /// An onion message to be sent or received from a peer
+#[derive(Clone, Debug, PartialEq)]
+pub struct OnionMessage {
+ /// Used in decrypting the onion packet's payload.
+ pub blinding_point: PublicKey,
+ pub(crate) onion_routing_packet: onion_message::Packet,
+}
+
/// An update_fulfill_htlc message to be sent or received from a peer
#[derive(Clone, Debug, PartialEq)]
pub struct UpdateFulfillHTLC {
/// The port on which the node is listening
port: u16,
},
+ /// A hostname/port on which the peer is listening.
+ Hostname {
+ /// The hostname on which the node is listening.
+ hostname: Hostname,
+ /// The port on which the node is listening.
+ port: u16,
+ },
}
impl NetAddress {
/// Gets the ID of this address type. Addresses in node_announcement messages should be sorted
&NetAddress::IPv6 {..} => { 2 },
&NetAddress::OnionV2(_) => { 3 },
&NetAddress::OnionV3 {..} => { 4 },
+ &NetAddress::Hostname {..} => { 5 },
}
}
&NetAddress::IPv6 { .. } => { 18 },
&NetAddress::OnionV2(_) => { 12 },
&NetAddress::OnionV3 { .. } => { 37 },
+ // Consists of 1-byte hostname length, hostname bytes, and 2-byte port.
+ &NetAddress::Hostname { ref hostname, .. } => { u16::from(hostname.len()) + 3 },
}
}
- /// The maximum length of any address descriptor, not including the 1-byte type
- pub(crate) const MAX_LEN: u16 = 37;
+ /// The maximum length of any address descriptor, not including the 1-byte type.
+ /// This maximum length is reached by a hostname address descriptor:
+ /// a hostname with a maximum length of 255, its 1-byte length and a 2-byte port.
+ pub(crate) const MAX_LEN: u16 = 258;
}
impl Writeable for NetAddress {
checksum.write(writer)?;
version.write(writer)?;
port.write(writer)?;
- }
+ },
+ &NetAddress::Hostname { ref hostname, ref port } => {
+ 5u8.write(writer)?;
+ hostname.write(writer)?;
+ port.write(writer)?;
+ },
}
Ok(())
}
port: Readable::read(reader)?,
}))
},
+ 5 => {
+ Ok(Ok(NetAddress::Hostname {
+ hostname: Readable::read(reader)?,
+ port: Readable::read(reader)?,
+ }))
+ },
_ => return Ok(Err(byte)),
}
}
pub cltv_expiry_delta: u16,
/// The minimum HTLC size incoming to sender, in milli-satoshi
pub htlc_minimum_msat: u64,
- /// Optionally, the maximum HTLC value incoming to sender, in milli-satoshi
- pub htlc_maximum_msat: OptionalField<u64>,
+ /// The maximum HTLC value incoming to sender, in milli-satoshi. Used to be optional.
+ pub htlc_maximum_msat: u64,
/// The base HTLC fee charged by sender, in milli-satoshi
pub fee_base_msat: u32,
/// The amount to fee multiplier, in micro-satoshi
pub(crate) hmac: [u8; 32],
}
+impl onion_utils::Packet for OnionPacket {
+ type Data = onion_utils::FixedSizeOnionPacket;
+ fn new(pubkey: PublicKey, hop_data: onion_utils::FixedSizeOnionPacket, hmac: [u8; 32]) -> Self {
+ Self {
+ version: 0,
+ public_key: Ok(pubkey),
+ hop_data: hop_data.0,
+ hmac,
+ }
+ }
+}
+
impl PartialEq for OnionPacket {
fn eq(&self, other: &OnionPacket) -> bool {
for (i, j) in self.hop_data.iter().zip(other.hop_data.iter()) {
onion_routing_packet
}, {});
+impl Readable for OnionMessage {
+ fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
+ let blinding_point: PublicKey = Readable::read(r)?;
+ let len: u16 = Readable::read(r)?;
+ let mut packet_reader = FixedLengthReader::new(r, len as u64);
+ let onion_routing_packet: onion_message::Packet = <onion_message::Packet as LengthReadable>::read(&mut packet_reader)?;
+ Ok(Self {
+ blinding_point,
+ onion_routing_packet,
+ })
+ }
+}
+
+impl Writeable for OnionMessage {
+ fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
+ self.blinding_point.write(w)?;
+ let onion_packet_len = self.onion_routing_packet.serialized_length();
+ (onion_packet_len as u16).write(w)?;
+ self.onion_routing_packet.write(w)?;
+ Ok(())
+ }
+}
+
impl Writeable for FinalOnionHopData {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.payment_secret.0.write(w)?;
}
}
+// ReadableArgs because we need onion_utils::decode_next_hop to accommodate payment packets and
+// onion message packets.
+impl ReadableArgs<()> for OnionHopData {
+ fn read<R: Read>(r: &mut R, _arg: ()) -> Result<Self, DecodeError> {
+ <Self as Readable>::read(r)
+ }
+}
+
impl Readable for OnionHopData {
fn read<R: Read>(mut r: &mut R) -> Result<Self, DecodeError> {
use bitcoin::consensus::encode::{Decodable, Error, VarInt};
impl Writeable for UnsignedChannelUpdate {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
- let mut message_flags: u8 = 0;
- if let OptionalField::Present(_) = self.htlc_maximum_msat {
- message_flags = 1;
- }
+ // `message_flags` used to indicate presence of `htlc_maximum_msat`, but was deprecated in the spec.
+ const MESSAGE_FLAGS: u8 = 1;
self.chain_hash.write(w)?;
self.short_channel_id.write(w)?;
self.timestamp.write(w)?;
- let all_flags = self.flags as u16 | ((message_flags as u16) << 8);
+ let all_flags = self.flags as u16 | ((MESSAGE_FLAGS as u16) << 8);
all_flags.write(w)?;
self.cltv_expiry_delta.write(w)?;
self.htlc_minimum_msat.write(w)?;
impl Readable for UnsignedChannelUpdate {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let has_htlc_maximum_msat;
Ok(Self {
chain_hash: Readable::read(r)?,
short_channel_id: Readable::read(r)?,
timestamp: Readable::read(r)?,
flags: {
let flags: u16 = Readable::read(r)?;
- let message_flags = flags >> 8;
- has_htlc_maximum_msat = (message_flags as i32 & 1) == 1;
+ // Note: we ignore the `message_flags` for now, since it was deprecated by the spec.
flags as u8
},
cltv_expiry_delta: Readable::read(r)?,
htlc_minimum_msat: Readable::read(r)?,
fee_base_msat: Readable::read(r)?,
fee_proportional_millionths: Readable::read(r)?,
- htlc_maximum_msat: if has_htlc_maximum_msat { Readable::read(r)? } else { OptionalField::Absent },
+ htlc_maximum_msat: Readable::read(r)?,
excess_data: read_to_end(r)?,
})
}
use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
use ln::msgs;
use ln::msgs::{FinalOnionHopData, OptionalField, OnionErrorPacket, OnionHopDataFormat};
- use util::ser::{Writeable, Readable};
+ use util::ser::{Writeable, Readable, Hostname};
use bitcoin::hashes::hex::FromHex;
use bitcoin::util::address::Address;
use io::Cursor;
use prelude::*;
+ use core::convert::TryFrom;
#[test]
fn encoding_channel_reestablish_no_secret() {
do_encoding_channel_announcement(true, true);
}
- fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, excess_address_data: bool, excess_data: bool) {
+ fn do_encoding_node_announcement(unknown_features_bits: bool, ipv4: bool, ipv6: bool, onionv2: bool, onionv3: bool, hostname: bool, excess_address_data: bool, excess_data: bool) {
let secp_ctx = Secp256k1::new();
let (privkey_1, pubkey_1) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
port: 9735
});
}
+ if hostname {
+ addresses.push(msgs::NetAddress::Hostname {
+ hostname: Hostname::try_from(String::from("host")).unwrap(),
+ port: 9735,
+ });
+ }
let mut addr_len = 0;
for addr in &addresses {
addr_len += addr.len() + 1;
if onionv3 {
target_value.append(&mut hex::decode("04fffefdfcfbfaf9f8f7f6f5f4f3f2f1f0efeeedecebeae9e8e7e6e5e4e3e2e1e00020102607").unwrap());
}
+ if hostname {
+ target_value.append(&mut hex::decode("0504686f73742607").unwrap());
+ }
if excess_address_data {
target_value.append(&mut hex::decode("216c280b5395a2546e7e4b2663e04f811622f15a4f92e83aa2e92ba2a573c139142c54ae63072a1ec1ee7dc0c04bde5c847806172aa05c92c22ae8e308d1d269").unwrap());
}
#[test]
fn encoding_node_announcement() {
- do_encoding_node_announcement(true, true, true, true, true, true, true);
- do_encoding_node_announcement(false, false, false, false, false, false, false);
- do_encoding_node_announcement(false, true, false, false, false, false, false);
- do_encoding_node_announcement(false, false, true, false, false, false, false);
- do_encoding_node_announcement(false, false, false, true, false, false, false);
- do_encoding_node_announcement(false, false, false, false, true, false, false);
- do_encoding_node_announcement(false, false, false, false, false, true, false);
- do_encoding_node_announcement(false, true, false, true, false, true, false);
- do_encoding_node_announcement(false, false, true, false, true, false, false);
- }
-
- fn do_encoding_channel_update(direction: bool, disable: bool, htlc_maximum_msat: bool, excess_data: bool) {
+ do_encoding_node_announcement(true, true, true, true, true, true, true, true);
+ do_encoding_node_announcement(false, false, false, false, false, false, false, false);
+ do_encoding_node_announcement(false, true, false, false, false, false, false, false);
+ do_encoding_node_announcement(false, false, true, false, false, false, false, false);
+ do_encoding_node_announcement(false, false, false, true, false, false, false, false);
+ do_encoding_node_announcement(false, false, false, false, true, false, false, false);
+ do_encoding_node_announcement(false, false, false, false, false, true, false, false);
+ do_encoding_node_announcement(false, false, false, false, false, false, true, false);
+ do_encoding_node_announcement(false, true, false, true, false, false, true, false);
+ do_encoding_node_announcement(false, false, true, false, true, false, false, false);
+ }
+
+ fn do_encoding_channel_update(direction: bool, disable: bool, excess_data: bool) {
let secp_ctx = Secp256k1::new();
let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 },
cltv_expiry_delta: 144,
htlc_minimum_msat: 1000000,
- htlc_maximum_msat: if htlc_maximum_msat { OptionalField::Present(131355275467161) } else { OptionalField::Absent },
+ htlc_maximum_msat: 131355275467161,
fee_base_msat: 10000,
fee_proportional_millionths: 20,
excess_data: if excess_data { vec![0, 0, 0, 0, 59, 154, 202, 0] } else { Vec::new() }
let mut target_value = hex::decode("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
target_value.append(&mut hex::decode("00083a840000034d013413a7").unwrap());
- if htlc_maximum_msat {
- target_value.append(&mut hex::decode("01").unwrap());
- } else {
- target_value.append(&mut hex::decode("00").unwrap());
- }
+ target_value.append(&mut hex::decode("01").unwrap());
target_value.append(&mut hex::decode("00").unwrap());
if direction {
let flag = target_value.last_mut().unwrap();
*flag = *flag | 1 << 1;
}
target_value.append(&mut hex::decode("009000000000000f42400000271000000014").unwrap());
- if htlc_maximum_msat {
- target_value.append(&mut hex::decode("0000777788889999").unwrap());
- }
+ target_value.append(&mut hex::decode("0000777788889999").unwrap());
if excess_data {
target_value.append(&mut hex::decode("000000003b9aca00").unwrap());
}
#[test]
fn encoding_channel_update() {
- do_encoding_channel_update(false, false, false, false);
- do_encoding_channel_update(false, false, false, true);
- do_encoding_channel_update(true, false, false, false);
- do_encoding_channel_update(true, false, false, true);
- do_encoding_channel_update(false, true, false, false);
- do_encoding_channel_update(false, true, false, true);
- do_encoding_channel_update(false, false, true, false);
- do_encoding_channel_update(false, false, true, true);
- do_encoding_channel_update(true, true, true, false);
- do_encoding_channel_update(true, true, true, true);
+ do_encoding_channel_update(false, false, false);
+ do_encoding_channel_update(false, false, true);
+ do_encoding_channel_update(true, false, false);
+ do_encoding_channel_update(true, false, true);
+ do_encoding_channel_update(false, true, false);
+ do_encoding_channel_update(false, true, true);
+ do_encoding_channel_update(true, true, false);
+ do_encoding_channel_update(true, true, true);
}
fn do_encoding_open_channel(random_bit: bool, shutdown: bool, incl_chan_type: bool) {