pub mod message;
pub mod payment;
pub(crate) mod utils;
use bitcoin::secp256k1::PublicKey;
use core::ops::Deref;
use crate::ln::msgs::DecodeError;
use crate::routing::gossip::{NodeId, ReadOnlyNetworkGraph};
use crate::util::ser::{Readable, Writeable, Writer};
use crate::io;
use crate::prelude::*;
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub(crate) struct BlindedPath {
pub introduction_node: IntroductionNode,
pub blinding_point: PublicKey,
pub blinded_hops: Vec<BlindedHop>,
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub enum IntroductionNode {
NodeId(PublicKey),
DirectedShortChannelId(Direction, u64),
}
#[derive(Clone, Copy, Debug, Hash, PartialEq, Eq)]
pub enum Direction {
NodeOne,
NodeTwo,
}
pub trait NodeIdLookUp {
fn next_node_id(&self, short_channel_id: u64) -> Option<PublicKey>;
}
pub struct EmptyNodeIdLookUp {}
impl NodeIdLookUp for EmptyNodeIdLookUp {
fn next_node_id(&self, _short_channel_id: u64) -> Option<PublicKey> {
None
}
}
impl Deref for EmptyNodeIdLookUp {
type Target = EmptyNodeIdLookUp;
fn deref(&self) -> &Self {
self
}
}
#[derive(Clone, Debug, Hash, PartialEq, Eq)]
pub struct BlindedHop {
pub blinded_node_id: PublicKey,
pub encrypted_payload: Vec<u8>,
}
impl BlindedPath {
pub(super) fn public_introduction_node_id<'a>(
&self, network_graph: &'a ReadOnlyNetworkGraph,
) -> Option<&'a NodeId> {
match &self.introduction_node {
IntroductionNode::NodeId(pubkey) => {
let node_id = NodeId::from_pubkey(pubkey);
network_graph.nodes().get_key_value(&node_id).map(|(key, _)| key)
},
IntroductionNode::DirectedShortChannelId(direction, scid) => {
network_graph.channel(*scid).map(|c| match direction {
Direction::NodeOne => &c.node_one,
Direction::NodeTwo => &c.node_two,
})
},
}
}
}
impl Writeable for BlindedPath {
fn write<W: Writer>(&self, w: &mut W) -> Result<(), io::Error> {
match &self.introduction_node {
IntroductionNode::NodeId(pubkey) => pubkey.write(w)?,
IntroductionNode::DirectedShortChannelId(direction, scid) => {
match direction {
Direction::NodeOne => 0u8.write(w)?,
Direction::NodeTwo => 1u8.write(w)?,
}
scid.write(w)?;
},
}
self.blinding_point.write(w)?;
(self.blinded_hops.len() as u8).write(w)?;
for hop in &self.blinded_hops {
hop.write(w)?;
}
Ok(())
}
}
impl Readable for BlindedPath {
fn read<R: io::Read>(r: &mut R) -> Result<Self, DecodeError> {
let first_byte: u8 = Readable::read(r)?;
let introduction_node = match first_byte {
0 => IntroductionNode::DirectedShortChannelId(Direction::NodeOne, Readable::read(r)?),
1 => IntroductionNode::DirectedShortChannelId(Direction::NodeTwo, Readable::read(r)?),
2 | 3 => {
let mut bytes = [0; 33];
bytes[0] = first_byte;
r.read_exact(&mut bytes[1..])?;
IntroductionNode::NodeId(Readable::read(&mut &bytes[..])?)
},
_ => return Err(DecodeError::InvalidValue),
};
let blinding_point = Readable::read(r)?;
let num_hops: u8 = Readable::read(r)?;
if num_hops == 0 {
return Err(DecodeError::InvalidValue);
}
let mut blinded_hops: Vec<BlindedHop> = Vec::with_capacity(num_hops.into());
for _ in 0..num_hops {
blinded_hops.push(Readable::read(r)?);
}
Ok(BlindedPath { introduction_node, blinding_point, blinded_hops })
}
}
impl_writeable!(BlindedHop, {
blinded_node_id,
encrypted_payload
});
impl Direction {
pub fn select_node_id(&self, node_a: NodeId, node_b: NodeId) -> NodeId {
match self {
Direction::NodeOne => core::cmp::min(node_a, node_b),
Direction::NodeTwo => core::cmp::max(node_a, node_b),
}
}
pub fn select_pubkey<'a>(&self, node_a: &'a PublicKey, node_b: &'a PublicKey) -> &'a PublicKey {
let (node_one, node_two) = if NodeId::from_pubkey(node_a) < NodeId::from_pubkey(node_b) {
(node_a, node_b)
} else {
(node_b, node_a)
};
match self {
Direction::NodeOne => node_one,
Direction::NodeTwo => node_two,
}
}
}