use bitcoin::secp256k1::ecdsa::Signature;
use bitcoin::{secp256k1, Witness};
use bitcoin::blockdata::script::Script;
-use bitcoin::hash_types::{Txid, BlockHash};
+use bitcoin::hash_types::Txid;
+use crate::blinded_path::payment::ReceiveTlvs;
use crate::ln::{ChannelId, PaymentPreimage, PaymentHash, PaymentSecret};
use crate::ln::features::{ChannelFeatures, ChannelTypeFeatures, InitFeatures, NodeFeatures};
use crate::ln::onion_utils;
use crate::onion_message;
+use crate::sign::{NodeSigner, Recipient};
use crate::prelude::*;
+#[cfg(feature = "std")]
use core::convert::TryFrom;
use core::fmt;
use core::fmt::Debug;
+use core::ops::Deref;
+#[cfg(feature = "std")]
use core::str::FromStr;
-use crate::io::{self, Read};
+use crate::io::{self, Cursor, Read};
use crate::io_extras::read_to_end;
-use crate::events::{MessageSendEventsProvider, OnionMessageProvider};
+use crate::events::MessageSendEventsProvider;
+use crate::util::chacha20poly1305rfc::ChaChaPolyReadAdapter;
use crate::util::logger;
-use crate::util::ser::{LengthReadable, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
+use crate::util::ser::{LengthReadable, LengthReadableArgs, Readable, ReadableArgs, Writeable, Writer, WithoutLength, FixedLengthReader, HighZeroBytesDroppedBigSize, Hostname, TransactionU16LenLimited, BigSize};
use crate::util::base32;
use crate::routing::gossip::{NodeAlias, NodeId};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct OpenChannel {
/// The genesis hash of the blockchain where the channel is to be opened
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// A temporary channel ID, until the funding outpoint is announced
pub temporary_channel_id: ChannelId,
/// The channel value
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct OpenChannelV2 {
/// The genesis hash of the blockchain where the channel is to be opened
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// A temporary channel ID derived using a zeroed out value for the channel acceptor's revocation basepoint
pub temporary_channel_id: ChannelId,
/// The feerate for the funding transaction set by the channel initiator
pub struct OnionMessage {
/// Used in decrypting the onion packet's payload.
pub blinding_point: PublicKey,
- pub(crate) onion_routing_packet: onion_message::Packet,
+ /// The full onion packet including hop data, pubkey, and hmac
+ pub onion_routing_packet: onion_message::Packet,
}
/// An [`update_fulfill_htlc`] message to be sent to or received from a peer.
}
}
-fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, SocketAddressParseError> {
+/// Parses an OnionV3 host and port into a [`SocketAddress::OnionV3`].
+///
+/// The host part must end with ".onion".
+pub fn parse_onion_address(host: &str, port: u16) -> Result<SocketAddress, SocketAddressParseError> {
if host.ends_with(".onion") {
let domain = &host[..host.len() - ".onion".len()];
if domain.len() != 56 {
/// The advertised channel features
pub features: ChannelFeatures,
/// The genesis hash of the blockchain where the channel is to be opened
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// The short channel ID
pub short_channel_id: u64,
/// One of the two `node_id`s which are endpoints of this channel
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct UnsignedChannelUpdate {
/// The genesis hash of the blockchain where the channel is to be opened
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// The short channel ID
pub short_channel_id: u64,
/// A strictly monotonic announcement counter, with gaps allowed, specific to this channel
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct QueryChannelRange {
/// The genesis hash of the blockchain being queried
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// The height of the first block for the channel UTXOs being queried
pub first_blocknum: u32,
/// The number of blocks to include in the query results
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ReplyChannelRange {
/// The genesis hash of the blockchain being queried
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// The height of the first block in the range of the reply
pub first_blocknum: u32,
/// The number of blocks included in the range of the reply
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct QueryShortChannelIds {
/// The genesis hash of the blockchain being queried
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// The short_channel_ids that are being queried
pub short_channel_ids: Vec<u64>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ReplyShortChannelIdsEnd {
/// The genesis hash of the blockchain that was queried
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// Indicates if the query recipient maintains up-to-date channel
/// information for the `chain_hash`
pub full_information: bool,
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct GossipTimestampFilter {
/// The genesis hash of the blockchain for channel and node information
- pub chain_hash: BlockHash,
+ pub chain_hash: ChainHash,
/// The starting unix timestamp
pub first_timestamp: u32,
/// The range of information in seconds
/// 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.
+ /// Gets the chain 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<Vec<ChainHash>>;
+ fn get_chain_hashes(&self) -> Option<Vec<ChainHash>>;
}
/// A trait to describe an object which can receive routing messages.
fn provided_init_features(&self, their_node_id: &PublicKey) -> InitFeatures;
}
-/// A trait to describe an object that can receive onion messages.
-pub trait OnionMessageHandler : OnionMessageProvider {
+/// A handler for received [`OnionMessage`]s and for providing generated ones to send.
+pub trait OnionMessageHandler {
/// Handle an incoming `onion_message` message from the given peer.
fn handle_onion_message(&self, peer_node_id: &PublicKey, msg: &OnionMessage);
+
+ /// Returns the next pending onion message for the peer with the given node id.
+ fn next_onion_message_for_peer(&self, peer_node_id: PublicKey) -> Option<OnionMessage>;
+
/// Called when a connection is established with a peer. Can be used to track which peers
/// advertise onion message support and are online.
///
/// with us. Implementors should be somewhat conservative about doing so, however, as other
/// message handlers may still wish to communicate with this peer.
fn peer_connected(&self, their_node_id: &PublicKey, init: &Init, inbound: bool) -> Result<(), ()>;
+
/// Indicates a connection to the peer failed/an existing connection was lost. Allows handlers to
/// drop and refuse to forward onion messages to this peer.
fn peer_disconnected(&self, their_node_id: &PublicKey);
mod fuzzy_internal_msgs {
use bitcoin::secp256k1::PublicKey;
+ use crate::blinded_path::payment::PaymentConstraints;
use crate::prelude::*;
use crate::ln::{PaymentPreimage, PaymentSecret};
amt_msat: u64,
outgoing_cltv_value: u32,
},
+ BlindedReceive {
+ amt_msat: u64,
+ total_msat: u64,
+ outgoing_cltv_value: u32,
+ payment_secret: PaymentSecret,
+ payment_constraints: PaymentConstraints,
+ intro_node_blinding_point: PublicKey,
+ }
}
pub(crate) enum OutboundOnionPayload {
}
}
-impl Readable for InboundOnionPayload {
- fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let mut amt = HighZeroBytesDroppedBigSize(0u64);
- let mut cltv_value = HighZeroBytesDroppedBigSize(0u32);
+impl<NS: Deref> ReadableArgs<&NS> for InboundOnionPayload where NS::Target: NodeSigner {
+ fn read<R: Read>(r: &mut R, node_signer: &NS) -> Result<Self, DecodeError> {
+ let mut amt = None;
+ let mut cltv_value = None;
let mut short_id: Option<u64> = None;
let mut payment_data: Option<FinalOnionHopData> = None;
+ let mut encrypted_tlvs_opt: Option<WithoutLength<Vec<u8>>> = None;
+ let mut intro_node_blinding_point = None;
let mut payment_metadata: Option<WithoutLength<Vec<u8>>> = None;
+ let mut total_msat = None;
let mut keysend_preimage: Option<PaymentPreimage> = None;
let mut custom_tlvs = Vec::new();
let tlv_len = BigSize::read(r)?;
let rd = FixedLengthReader::new(r, tlv_len.0);
decode_tlv_stream_with_custom_tlv_decode!(rd, {
- (2, amt, required),
- (4, cltv_value, required),
+ (2, amt, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
+ (4, cltv_value, (option, encoding: (u32, HighZeroBytesDroppedBigSize))),
(6, short_id, option),
(8, payment_data, option),
+ (10, encrypted_tlvs_opt, option),
+ (12, intro_node_blinding_point, option),
(16, payment_metadata, option),
+ (18, total_msat, (option, encoding: (u64, HighZeroBytesDroppedBigSize))),
// See https://github.com/lightning/blips/blob/master/blip-0003.md
(5482373484, keysend_preimage, option)
}, |msg_type: u64, msg_reader: &mut FixedLengthReader<_>| -> Result<bool, DecodeError> {
Ok(true)
});
- if amt.0 > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
- if let Some(short_channel_id) = short_id {
- if payment_data.is_some() { return Err(DecodeError::InvalidValue) }
- if payment_metadata.is_some() { return Err(DecodeError::InvalidValue); }
+ if amt.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
+
+ if let Some(blinding_point) = intro_node_blinding_point {
+ if short_id.is_some() || payment_data.is_some() || payment_metadata.is_some() {
+ return Err(DecodeError::InvalidValue)
+ }
+ let enc_tlvs = encrypted_tlvs_opt.ok_or(DecodeError::InvalidValue)?.0;
+ let enc_tlvs_ss = node_signer.ecdh(Recipient::Node, &blinding_point, None)
+ .map_err(|_| DecodeError::InvalidValue)?;
+ let rho = onion_utils::gen_rho_from_shared_secret(&enc_tlvs_ss.secret_bytes());
+ let mut s = Cursor::new(&enc_tlvs);
+ let mut reader = FixedLengthReader::new(&mut s, enc_tlvs.len() as u64);
+ match ChaChaPolyReadAdapter::read(&mut reader, rho)? {
+ ChaChaPolyReadAdapter { readable: ReceiveTlvs { payment_secret, payment_constraints }} => {
+ if total_msat.unwrap_or(0) > MAX_VALUE_MSAT { return Err(DecodeError::InvalidValue) }
+ Ok(Self::BlindedReceive {
+ amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+ total_msat: total_msat.ok_or(DecodeError::InvalidValue)?,
+ outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
+ payment_secret,
+ payment_constraints,
+ intro_node_blinding_point: blinding_point,
+ })
+ },
+ }
+ } else if let Some(short_channel_id) = short_id {
+ if payment_data.is_some() || payment_metadata.is_some() || encrypted_tlvs_opt.is_some() ||
+ total_msat.is_some()
+ { return Err(DecodeError::InvalidValue) }
Ok(Self::Forward {
short_channel_id,
- amt_to_forward: amt.0,
- outgoing_cltv_value: cltv_value.0,
+ amt_to_forward: amt.ok_or(DecodeError::InvalidValue)?,
+ outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
})
} else {
+ if encrypted_tlvs_opt.is_some() || total_msat.is_some() {
+ return Err(DecodeError::InvalidValue)
+ }
if let Some(data) = &payment_data {
if data.total_msat > MAX_VALUE_MSAT {
return Err(DecodeError::InvalidValue);
payment_data,
payment_metadata: payment_metadata.map(|w| w.0),
keysend_preimage,
- amt_msat: amt.0,
- outgoing_cltv_value: cltv_value.0,
+ amt_msat: amt.ok_or(DecodeError::InvalidValue)?,
+ outgoing_cltv_value: cltv_value.ok_or(DecodeError::InvalidValue)?,
custom_tlvs,
})
}
}
}
-// ReadableArgs because we need onion_utils::decode_next_hop to accommodate payment packets and
-// onion message packets.
-impl ReadableArgs<()> for InboundOnionPayload {
- fn read<R: Read>(r: &mut R, _arg: ()) -> Result<Self, DecodeError> {
- <Self as Readable>::read(r)
- }
-}
-
impl Writeable for Ping {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
self.ponglen.write(w)?;
impl Readable for QueryShortChannelIds {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let chain_hash: BlockHash = Readable::read(r)?;
+ let chain_hash: ChainHash = Readable::read(r)?;
let encoding_len: u16 = Readable::read(r)?;
let encoding_type: u8 = Readable::read(r)?;
impl Readable for ReplyChannelRange {
fn read<R: Read>(r: &mut R) -> Result<Self, DecodeError> {
- let chain_hash: BlockHash = Readable::read(r)?;
+ let chain_hash: ChainHash = Readable::read(r)?;
let first_blocknum: u32 = Readable::read(r)?;
let number_of_blocks: u32 = Readable::read(r)?;
let sync_complete: bool = Readable::read(r)?;
#[cfg(test)]
mod tests {
use std::convert::TryFrom;
- 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::msgs::{self, FinalOnionHopData, OnionErrorPacket};
use crate::ln::msgs::SocketAddress;
use crate::routing::gossip::{NodeAlias, NodeId};
- use crate::util::ser::{Writeable, Readable, Hostname, TransactionU16LenLimited};
+ use crate::util::ser::{Writeable, Readable, ReadableArgs, Hostname, TransactionU16LenLimited};
+ use crate::util::test_utils;
use bitcoin::hashes::hex::FromHex;
use bitcoin::util::address::Address;
use bitcoin::network::constants::Network;
+ use bitcoin::blockdata::constants::ChainHash;
use bitcoin::blockdata::script::Builder;
use bitcoin::blockdata::opcodes;
- use bitcoin::hash_types::{Txid, BlockHash};
+ use bitcoin::hash_types::Txid;
use bitcoin::secp256k1::{PublicKey,SecretKey};
use bitcoin::secp256k1::{Secp256k1, Message};
}
let unsigned_channel_announcement = msgs::UnsignedChannelAnnouncement {
features,
- chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+ chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
short_channel_id: 2316138423780173,
node_id_1: NodeId::from_pubkey(&pubkey_1),
node_id_2: NodeId::from_pubkey(&pubkey_2),
} else {
target_value.append(&mut hex::decode("0000").unwrap());
}
- target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+ target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
target_value.append(&mut hex::decode("00083a840000034d031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b").unwrap());
if excess_data {
target_value.append(&mut hex::decode("0a00001400001e000028").unwrap());
let (privkey_1, _) = get_keys_from!("0101010101010101010101010101010101010101010101010101010101010101", secp_ctx);
let sig_1 = get_sig_on!(privkey_1, secp_ctx, String::from("01010101010101010101010101010101"));
let unsigned_channel_update = msgs::UnsignedChannelUpdate {
- chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+ chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
short_channel_id: 2316138423780173,
timestamp: 20190119,
flags: if direction { 1 } else { 0 } | if disable { 1 << 1 } else { 0 },
};
let encoded_value = channel_update.encode();
let mut target_value = hex::decode("d977cb9b53d93a6ff64bb5f1e158b4094b66e798fb12911168a3ccdf80a83096340a6a95da0ae8d9f776528eecdbb747eb6b545495a4319ed5378e35b21e073a").unwrap();
- target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+ target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
target_value.append(&mut hex::decode("00083a840000034d013413a7").unwrap());
target_value.append(&mut hex::decode("01").unwrap());
target_value.append(&mut hex::decode("00").unwrap());
let (_, pubkey_5) = get_keys_from!("0505050505050505050505050505050505050505050505050505050505050505", secp_ctx);
let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
let open_channel = msgs::OpenChannel {
- chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+ chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
temporary_channel_id: ChannelId::from_bytes([2; 32]),
funding_satoshis: 1311768467284833366,
push_msat: 2536655962884945560,
};
let encoded_value = open_channel.encode();
let mut target_value = Vec::new();
- target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+ target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
target_value.append(&mut hex::decode("02020202020202020202020202020202020202020202020202020202020202021234567890123456233403289122369832144668701144767633030896203198784335490624111800083a840000034d000c89d4c0bcc0bc031b84c5567b126440995d3ed5aaba0565d71e1834604819ff9c17f5e9d5dd078f024d4b6cd1361032ca9bd2aeb9d900aa4d45d9ead80ac9423374c451a7254d076602531fe6068134503d2723133227c867ac8fa6c83c537e9a44c3c5bdbdcb1fe33703462779ad4aad39514614751a71085f2f10e1c7a593e4e030efb5b8721ce55b0b0362c0a046dacce86ddd0343c6d3c7c79c2208ba0d9c9cf24a6d046d21d21f90f703f006a18d5653c4edf5391ff23a61f03ff83d237e880ee61187fa9f379a028e0a").unwrap());
if random_bit {
target_value.append(&mut hex::decode("20").unwrap());
let (_, pubkey_6) = get_keys_from!("0606060606060606060606060606060606060606060606060606060606060606", secp_ctx);
let (_, pubkey_7) = get_keys_from!("0707070707070707070707070707070707070707070707070707070707070707", secp_ctx);
let open_channelv2 = msgs::OpenChannelV2 {
- chain_hash: BlockHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap(),
+ chain_hash: ChainHash::using_genesis_block(Network::Bitcoin),
temporary_channel_id: ChannelId::from_bytes([2; 32]),
funding_feerate_sat_per_1000_weight: 821716,
commitment_feerate_sat_per_1000_weight: 821716,
};
let encoded_value = open_channelv2.encode();
let mut target_value = Vec::new();
- target_value.append(&mut hex::decode("000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f").unwrap());
+ target_value.append(&mut hex::decode("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap());
target_value.append(&mut hex::decode("0202020202020202020202020202020202020202020202020202020202020202").unwrap());
target_value.append(&mut hex::decode("000c89d4").unwrap());
target_value.append(&mut hex::decode("000c89d4").unwrap());
#[test]
fn encoding_init() {
- let mainnet_hash = ChainHash::from_hex("6fe28c0ab6f1b372c1a6a246ae63f74f931e8365e15a089c68d6190000000000").unwrap();
+ let mainnet_hash = ChainHash::using_genesis_block(Network::Bitcoin);
assert_eq!(msgs::Init {
features: InitFeatures::from_le_bytes(vec![0xFF, 0xFF, 0xFF]),
networks: Some(vec![mainnet_hash]),
let target_value = hex::decode("1a02080badf00d010203040404ffffffff0608deadbeef1bad1dea").unwrap();
assert_eq!(encoded_value, target_value);
- let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
- if let msgs::InboundOnionPayload::Forward { short_channel_id, amt_to_forward, outgoing_cltv_value } = inbound_msg {
+ let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+ let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
+ if let msgs::InboundOnionPayload::Forward {
+ short_channel_id, amt_to_forward, outgoing_cltv_value
+ } = inbound_msg {
assert_eq!(short_channel_id, 0xdeadbeef1bad1dea);
assert_eq!(amt_to_forward, 0x0badf00d01020304);
assert_eq!(outgoing_cltv_value, 0xffffffff);
let target_value = hex::decode("1002080badf00d010203040404ffffffff").unwrap();
assert_eq!(encoded_value, target_value);
- let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
- if let msgs::InboundOnionPayload::Receive { payment_data: None, amt_msat, outgoing_cltv_value, .. } = inbound_msg {
+ let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+ let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
+ if let msgs::InboundOnionPayload::Receive {
+ payment_data: None, amt_msat, outgoing_cltv_value, ..
+ } = inbound_msg {
assert_eq!(amt_msat, 0x0badf00d01020304);
assert_eq!(outgoing_cltv_value, 0xffffffff);
} else { panic!(); }
let target_value = hex::decode("3602080badf00d010203040404ffffffff082442424242424242424242424242424242424242424242424242424242424242421badca1f").unwrap();
assert_eq!(encoded_value, target_value);
- let inbound_msg = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+ let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+ let inbound_msg = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
if let msgs::InboundOnionPayload::Receive {
payment_data: Some(FinalOnionHopData {
payment_secret,
outgoing_cltv_value: 0xffffffff,
};
let encoded_value = msg.encode();
- assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..])).is_err());
+ let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+ assert!(msgs::InboundOnionPayload::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).is_err());
let good_type_range_tlvs = vec![
((1 << 16) - 3, vec![42]),
((1 << 16) - 1, vec![42; 32]),
*custom_tlvs = good_type_range_tlvs.clone();
}
let encoded_value = msg.encode();
- let inbound_msg = Readable::read(&mut Cursor::new(&encoded_value[..])).unwrap();
+ let inbound_msg = ReadableArgs::read(&mut Cursor::new(&encoded_value[..]), &&node_signer).unwrap();
match inbound_msg {
msgs::InboundOnionPayload::Receive { custom_tlvs, .. } => assert!(custom_tlvs.is_empty()),
_ => panic!(),
let encoded_value = msg.encode();
let target_value = hex::decode("2e02080badf00d010203040404ffffffffff0000000146c6616b021234ff0000000146c6616f084242424242424242").unwrap();
assert_eq!(encoded_value, target_value);
- let inbound_msg: msgs::InboundOnionPayload = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
+ let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+ let inbound_msg: msgs::InboundOnionPayload = ReadableArgs::read(&mut Cursor::new(&target_value[..]), &&node_signer).unwrap();
if let msgs::InboundOnionPayload::Receive {
payment_data: None,
payment_metadata: None,
for (first_blocknum, number_of_blocks, expected) in tests.into_iter() {
let sut = msgs::QueryChannelRange {
- chain_hash: BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap(),
+ chain_hash: ChainHash::using_genesis_block(Network::Regtest),
first_blocknum,
number_of_blocks,
};
#[test]
fn encoding_query_channel_range() {
let mut query_channel_range = msgs::QueryChannelRange {
- chain_hash: BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap(),
+ chain_hash: ChainHash::using_genesis_block(Network::Regtest),
first_blocknum: 100000,
number_of_blocks: 1500,
};
let encoded_value = query_channel_range.encode();
- let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206000186a0000005dc").unwrap();
+ let target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000186a0000005dc").unwrap();
assert_eq!(encoded_value, target_value);
query_channel_range = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
}
fn do_encoding_reply_channel_range(encoding_type: u8) {
- let mut target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206000b8a06000005dc01").unwrap();
- let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+ let mut target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f000b8a06000005dc01").unwrap();
+ let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
let mut reply_channel_range = msgs::ReplyChannelRange {
chain_hash: expected_chain_hash,
first_blocknum: 756230,
}
fn do_encoding_query_short_channel_ids(encoding_type: u8) {
- let mut target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e2206").unwrap();
- let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+ let mut target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+ let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
let mut query_short_channel_ids = msgs::QueryShortChannelIds {
chain_hash: expected_chain_hash,
short_channel_ids: vec![0x0000000000008e, 0x0000000000003c69, 0x000000000045a6c4],
#[test]
fn encoding_reply_short_channel_ids_end() {
- let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+ let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
let mut reply_short_channel_ids_end = msgs::ReplyShortChannelIdsEnd {
chain_hash: expected_chain_hash,
full_information: true,
};
let encoded_value = reply_short_channel_ids_end.encode();
- let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e220601").unwrap();
+ let target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f01").unwrap();
assert_eq!(encoded_value, target_value);
reply_short_channel_ids_end = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
#[test]
fn encoding_gossip_timestamp_filter(){
- let expected_chain_hash = BlockHash::from_hex("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f").unwrap();
+ let expected_chain_hash = ChainHash::using_genesis_block(Network::Regtest);
let mut gossip_timestamp_filter = msgs::GossipTimestampFilter {
chain_hash: expected_chain_hash,
first_timestamp: 1590000000,
timestamp_range: 0xffff_ffff,
};
let encoded_value = gossip_timestamp_filter.encode();
- let target_value = hex::decode("0f9188f13cb7b2c71f2a335e3a4fc328bf5beb436012afca590b1a11466e22065ec57980ffffffff").unwrap();
+ let target_value = hex::decode("06226e46111a0b59caaf126043eb5bbf28c34f3a5e332a1fc7b2b73cf188910f5ec57980ffffffff").unwrap();
assert_eq!(encoded_value, target_value);
gossip_timestamp_filter = Readable::read(&mut Cursor::new(&target_value[..])).unwrap();
// payload length to be encoded over multiple bytes rather than a single u8.
let big_payload = encode_big_payload().unwrap();
let mut rd = Cursor::new(&big_payload[..]);
- <msgs::InboundOnionPayload as Readable>::read(&mut rd).unwrap();
+
+ let node_signer = test_utils::TestKeysInterface::new(&[42; 32], Network::Testnet);
+ <msgs::InboundOnionPayload as ReadableArgs<&&test_utils::TestKeysInterface>>
+ ::read(&mut rd, &&node_signer).unwrap();
}
// see above test, needs to be a separate method for use of the serialization macros.
fn encode_big_payload() -> Result<Vec<u8>, io::Error> {