//! 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::secp256k1::key::PublicKey;
-use bitcoin::secp256k1::Signature;
+use bitcoin::secp256k1::PublicKey;
+use bitcoin::secp256k1::ecdsa::Signature;
use bitcoin::secp256k1;
use bitcoin::blockdata::script::Script;
use bitcoin::hash_types::{Txid, BlockHash};
use ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
+use ln::onion_utils;
use prelude::*;
use core::fmt;
use util::events::MessageSendEventsProvider;
use util::logger;
-use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt};
+use util::ser::{Readable, Writeable, Writer, FixedLengthReader, HighZeroBytesDroppedVarInt, Hostname};
use ln::{PaymentPreimage, PaymentHash, PaymentSecret};
pub struct Init {
/// The relevant features which the sender supports
pub features: InitFeatures,
- /// The receipient's network address. This adds the option to report a remote IP address
+ /// The receipient's network address. This adds the option to report a remote IP address
/// back to a connecting peer using the init message. A node can decide to use that information
/// to discover a potential update to its public IPv4 address (NAT) and use
- /// that for a node_announcement update message containg the new address.
+ /// that for a node_announcement update message containing the new address.
pub remote_network_address: Option<NetAddress>,
}
pub signature: Signature,
}
-/// A funding_locked message to be sent or received from a peer
+/// A channel_ready message to be sent or received from a peer
#[derive(Clone, Debug, PartialEq)]
-pub struct FundingLocked {
+pub struct ChannelReady {
/// The channel ID
pub channel_id: [u8; 32],
/// The per-commitment point of the second commitment transaction
/// 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 fee_base_msat: u32,
/// The amount to fee multiplier, in micro-satoshi
pub fee_proportional_millionths: u32,
- pub(crate) excess_data: Vec<u8>,
+ /// 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
+ pub excess_data: Vec<u8>,
}
/// A channel_update message to be sent or received from a peer
#[derive(Clone, Debug, PartialEq)]
fn handle_funding_created(&self, their_node_id: &PublicKey, msg: &FundingCreated);
/// Handle an incoming funding_signed message from the given peer.
fn handle_funding_signed(&self, their_node_id: &PublicKey, msg: &FundingSigned);
- /// Handle an incoming funding_locked message from the given peer.
- fn handle_funding_locked(&self, their_node_id: &PublicKey, msg: &FundingLocked);
+ /// Handle an incoming channel_ready message from the given peer.
+ fn handle_channel_ready(&self, their_node_id: &PublicKey, msg: &ChannelReady);
// Channl close:
/// Handle an incoming shutdown message from the given peer.
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()) {
signature
}, {});
-impl_writeable_msg!(FundingLocked, {
+impl_writeable_msg!(ChannelReady, {
channel_id,
next_per_commitment_point,
}, {
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 bitcoin::blockdata::opcodes;
use bitcoin::hash_types::{Txid, BlockHash};
- use bitcoin::secp256k1::key::{PublicKey,SecretKey};
+ use bitcoin::secp256k1::{PublicKey,SecretKey};
use bitcoin::secp256k1::{Secp256k1, Message};
use io::Cursor;
use prelude::*;
+ use core::convert::TryFrom;
#[test]
fn encoding_channel_reestablish_no_secret() {
($privkey: expr, $ctx: expr, $string: expr) => {
{
let sighash = Message::from_slice(&$string.into_bytes()[..]).unwrap();
- $ctx.sign(&sighash, &$privkey)
+ $ctx.sign_ecdsa(&sighash, &$privkey)
}
}
}
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);
+ 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, htlc_maximum_msat: bool, excess_data: bool) {
htlc_basepoint: pubkey_5,
first_per_commitment_point: pubkey_6,
channel_flags: if random_bit { 1 << 5 } else { 0 },
- shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent },
+ shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent },
channel_type: if incl_chan_type { Some(ChannelTypeFeatures::empty()) } else { None },
};
let encoded_value = open_channel.encode();
delayed_payment_basepoint: pubkey_4,
htlc_basepoint: pubkey_5,
first_per_commitment_point: pubkey_6,
- shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent },
+ shutdown_scriptpubkey: if shutdown { OptionalField::Present(Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey()) } else { OptionalField::Absent },
channel_type: None,
};
let encoded_value = accept_channel.encode();
}
#[test]
- fn encoding_funding_locked() {
+ fn encoding_channel_ready() {
let secp_ctx = Secp256k1::new();
let (_, pubkey_1,) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
- let funding_locked = msgs::FundingLocked {
+ let channel_ready = msgs::ChannelReady {
channel_id: [2; 32],
next_per_commitment_point: pubkey_1,
short_channel_id_alias: None,
};
- let encoded_value = funding_locked.encode();
+ let encoded_value = channel_ready.encode();
let target_value = hex::decode("0202020202020202020202020202020202020202020202020202020202020202031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f").unwrap();
assert_eq!(encoded_value, target_value);
}
let shutdown = msgs::Shutdown {
channel_id: [2; 32],
scriptpubkey:
- if script_type == 1 { Address::p2pkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).script_pubkey() }
- else if script_type == 2 { Address::p2sh(&script, Network::Testnet).script_pubkey() }
- else if script_type == 3 { Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, key: pubkey_1}, Network::Testnet).unwrap().script_pubkey() }
+ if script_type == 1 { Address::p2pkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).script_pubkey() }
+ else if script_type == 2 { Address::p2sh(&script, Network::Testnet).unwrap().script_pubkey() }
+ else if script_type == 3 { Address::p2wpkh(&::bitcoin::PublicKey{compressed: true, inner: pubkey_1}, Network::Testnet).unwrap().script_pubkey() }
else { Address::p2wsh(&script, Network::Testnet).script_pubkey() },
};
let encoded_value = shutdown.encode();
}),
};
let encoded_value = init_msg.encode();
- let target_value = hex::decode("000000000307017f00000103e8").unwrap();
+ let target_value = hex::decode("000000000307017f00000103e8").unwrap();
assert_eq!(encoded_value, target_value);
- assert_eq!(msgs::Init::read(&mut Cursor::new(&target_value)).unwrap(),init_msg);
+ assert_eq!(msgs::Init::read(&mut Cursor::new(&target_value)).unwrap(), init_msg);
}
#[test]