Skip to content

Commit

Permalink
Add support for network addresses
Browse files Browse the repository at this point in the history
  • Loading branch information
cndolo committed Jan 12, 2024
1 parent ad28a2e commit f0db4f4
Show file tree
Hide file tree
Showing 3 changed files with 202 additions and 22 deletions.
6 changes: 3 additions & 3 deletions network-parser/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
[package]
name = "network-parser"
version = "0.1.0"
version = "0.2.0"
#repository = ""
authors = ["Anonymous Author <>"]
authors = ["Charmaine Ndolo <charmaine.ndolo@tu-dresden.de>"]
description = "Read the LN's topology from a JSON file."
#keywords = []
keywords = ["lightning-network", "graph"]
license = "MIT"
readme = "./README.md"
edition = "2021"
Expand Down
186 changes: 174 additions & 12 deletions network-parser/src/helpers.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,41 @@
use serde::Deserialize;
use serde::{Deserialize, Deserializer};
use serde_aux::prelude::*;
use std::hash::{Hash, Hasher};
use std::str::FromStr;

use crate::*;

#[derive(Deserialize, Debug, Default)]
pub struct RawLnresearchGraph {
pub(crate) nodes: Vec<RawNode>,
pub(crate) nodes: Vec<RawLnresearchNode>,
#[serde(alias = "adjacency")]
pub(crate) edges: Vec<Vec<LnresearchRawEdge>>,
}
#[derive(Deserialize, Debug, Default)]
pub struct RawLndGraph {
pub(crate) nodes: Vec<RawNode>,
pub(crate) nodes: Vec<RawLndNode>,
#[serde(alias = "adjacency")]
pub(crate) edges: Vec<LndRawEdge>,
}

serde_aux::StringOrVecToVecParser!(parse_between_commas, |c| { c == ',' }, true);

#[derive(Deserialize, Debug, Clone, Default, Eq, PartialEq)]
pub struct RawLnresearchNode {
#[serde(alias = "pub_key")]
pub(crate) id: Option<String>,
pub(crate) alias: Option<String>,
#[serde(deserialize_with = "addr_lnr_deserialize")]
#[serde(default)]
pub(crate) addresses: Option<Vec<String>>,
}

#[derive(Deserialize, Debug, Clone, Default, Eq, PartialEq)]
pub struct RawNode {
pub struct RawLndNode {
#[serde(alias = "pub_key")]
pub(crate) id: Option<String>,
pub(crate) alias: Option<String>,
pub(crate) addresses: Option<Vec<Address>>,
}

#[derive(Deserialize, Debug, Clone, Default)]
Expand Down Expand Up @@ -69,15 +83,44 @@ pub struct NodePolicy {
pub htlc_maximum_msat: Option<u64>,
#[serde(alias = "time_lock_delta")]
pub cltv_expiry_delta: Option<u64>,
pub last_update: u32,
}

impl Node {
pub(crate) fn from_raw(raw_node: RawNode) -> Node {
pub(crate) fn from_raw_lnresearch(raw_node: RawLnresearchNode) -> Node {
let mut addresses = vec![];
if let Some(raw_addresses) = raw_node.addresses {
for raw_addr in raw_addresses {
let mut addr = Address::default();
for (i, part) in raw_addr.split("://").enumerate() {
if i == 0 {
// the network part which always seems to be tcp
println!("part {}", part);
match part {
"ipv4" | "ipv6" | "torv2" | "torv3" => addr.network = "tcp".to_owned(),
_ => {
break;
}
}
} else if i == 1 {
println!("part 1 {}", part);
// the addr part
addr.addr = part.to_owned();
}
}
addresses.push(addr);
}
}
Node {
id: raw_node.id.expect("Error in node ID"),
alias: raw_node.alias.unwrap_or_default(),
addresses,
}
}
pub(crate) fn from_raw_lnd(raw_node: RawLndNode) -> Node {
Node {
id: raw_node.id.expect("Error in node ID"),
alias: raw_node.alias.unwrap_or_default(),
last_update: Default::default(),
addresses: raw_node.addresses.unwrap_or_default(),
}
}
}
Expand Down Expand Up @@ -275,12 +318,31 @@ impl PartialEq for LndRawEdge {
self.channel_id == other.channel_id && self.source == other.source
}
}

fn addr_lnr_deserialize<'de, D>(deserializer: D) -> Result<Option<Vec<String>>, D::Error>
where
D: Deserializer<'de>,
{
let str_sequence = String::deserialize(deserializer)?;
println!("str_sequence {}", str_sequence);
if str_sequence.is_empty() {
Ok(None)
} else {
Ok(Some(
str_sequence
.split(',')
.map(|item| item.to_owned())
.collect(),
))
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn node_wo_id_is_ignored() {
fn lnr_node_wo_id_is_ignored() {
let json_str = r##"{
"nodes": [
{
Expand Down Expand Up @@ -310,10 +372,6 @@ mod tests {
let actual = graph.nodes.len();
let expected = 1;
assert_eq!(actual, expected);
let graph = Graph::from_lnd_json_str(json_str).unwrap();
let actual = graph.nodes.len();
let expected = 1;
assert_eq!(actual, expected);
}

#[test]
Expand Down Expand Up @@ -526,4 +584,108 @@ mod tests {
assert_eq!(e.capacity, expected);
}
}

#[test]
fn lnd_addresses_works() {
let json_str = r##"{
"nodes": [
{
"id": "021fa5be893f5b3ec37cf5a0f4e984f35a32",
"addresses": [
{
"network": "tcp",
"addr": "159.69.16.168:9735"
},
{
"network": "tcp",
"addr": "[2a01:4f8:1c1e:abc1::1]:9735"
}
]
},
{
"id": "00e332bc1b7d8db0e705df3f087d285f9c06",
"addresses": [
]
},
{
"id": "026cf8782a7735ac62f0e71da85c93f1d864",
"addresses": [
{
"network": "tcp",
"addr": "br4uj734xva77u7yt6oevyp2ropqjl7nw2jyzeejwmd7dzlouenkfmid.onion:9735"
}
]
}
],
"edges": []
}"##;
let graph = Graph::from_lnd_json_str(&json_str).unwrap();
assert_eq!(graph.nodes.len(), 3);
let expected: HashMap<ID, Vec<Address>> = HashMap::from([
(
"021fa5be893f5b3ec37cf5a0f4e984f35a32".to_owned(),
vec![
Address {
network: "tcp".to_owned(),
addr: "159.69.16.168:9735".to_owned(),
},
Address {
network: "tcp".to_owned(),
addr: "[2a01:4f8:1c1e:abc1::1]:9735".to_owned(),
},
],
),
("00e332bc1b7d8db0e705df3f087d285f9c06".to_owned(), vec![]),
(
"026cf8782a7735ac62f0e71da85c93f1d864".to_owned(),
vec![Address {
network: "tcp".to_owned(),
addr: "br4uj734xva77u7yt6oevyp2ropqjl7nw2jyzeejwmd7dzlouenkfmid.onion:9735"
.to_owned(),
}],
),
]);
for node in graph.nodes {
assert_eq!(*expected.get(&node.id).unwrap(), node.addresses);
}
}

#[test]
fn lnr_addresses_works() {
let path_to_file = Path::new("../test_data/trivial_connected.json");
let graph = Graph::from_json_file(path_to_file, GraphSource::Lnresearch).unwrap();
let expected: HashMap<ID, Vec<Address>> = HashMap::from([
(
"034".to_owned(),
vec![Address {
network: "tcp".to_owned(),
addr: "212.108.220.135:9735".to_owned(),
}],
),
(
"025".to_owned(),
vec![Address {
network: "tcp".to_owned(),
addr: "104.236.54.112:9735".to_owned(),
}],
),
(
"036".to_owned(),
vec![
Address {
network: "tcp".to_owned(),
addr: "218.250.157.241:9735".to_owned(),
},
Address {
network: "tcp".to_string(),
addr: "wu5mkpokybtbf6dwdaepnujbzxpm6mqqqm2hwob6ndt5k74iujd2pdyd.onion:9735"
.to_owned(),
},
],
),
]);
for node in graph.nodes {
assert_eq!(*expected.get(&node.id).unwrap(), node.addresses);
}
}
}
32 changes: 25 additions & 7 deletions network-parser/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,13 @@ pub struct Graph {
pub struct Node {
pub id: ID,
pub alias: String,
pub last_update: usize,
pub addresses: Vec<Address>,
}

#[derive(Deserialize, Clone, Debug, Default, PartialEq, Eq)]
pub struct Address {
pub network: String,
pub addr: String,
}

#[derive(Deserialize, Clone, Debug, Default)]
Expand Down Expand Up @@ -79,19 +85,28 @@ impl Graph {
Self::from_json_str(&json_str, graph_source)
}

fn nodes_from_raw_graph(nodes: &[RawNode]) -> HashSet<Node> {
fn nodes_from_raw_lnd_graph(nodes: &[RawLndNode]) -> HashSet<Node> {
// discard nodes without ID
nodes
.iter()
.filter(|raw_node| raw_node.id.clone().unwrap_or_default() != ID::default())
.map(|raw_node| Node::from_raw_lnd(raw_node.clone()))
.collect()
}

fn nodes_from_raw_lnresearch_graph(nodes: &[RawLnresearchNode]) -> HashSet<Node> {
// discard nodes without ID
nodes
.iter()
.filter(|raw_node| raw_node.id.clone().unwrap_or_default() != ID::default())
.map(|raw_node| Node::from_raw(raw_node.clone()))
.map(|raw_node| Node::from_raw_lnresearch(raw_node.clone()))
.collect()
}

pub fn from_lnresearch_json_str(json_str: &str) -> Result<Graph, serde_json::Error> {
let raw_graph: RawLnresearchGraph =
serde_json::from_str(json_str).expect("Error deserialising JSON str!");
let nodes = Self::nodes_from_raw_graph(&raw_graph.nodes);
let nodes = Self::nodes_from_raw_lnresearch_graph(&raw_graph.nodes);
let mut edges: HashMap<ID, HashSet<Edge>> = HashMap::with_capacity(raw_graph.edges.len());
// discard edges with unknown IDs
let edges_vec: Vec<HashSet<Edge>> = raw_graph
Expand Down Expand Up @@ -132,7 +147,7 @@ impl Graph {
pub fn from_lnd_json_str(json_str: &str) -> Result<Graph, serde_json::Error> {
let raw_graph: RawLndGraph =
serde_json::from_str(json_str).expect("Error deserialising JSON str!");
let nodes = Self::nodes_from_raw_graph(&raw_graph.nodes);
let nodes = Self::nodes_from_raw_lnd_graph(&raw_graph.nodes);
let mut edges: HashMap<ID, HashSet<Edge>> = HashMap::with_capacity(raw_graph.edges.len());
// discard edges with unknown IDs
let mut edges_vec = vec![];
Expand Down Expand Up @@ -279,7 +294,10 @@ mod tests {
let expected = Node {
id: "021f0f2a5b46871b23f690a5be893f5b3ec37cf5a0fd8b89872234e984df35ea32".to_string(),
alias: "MilliBit".to_string(),
last_update: 54321,
addresses: vec![Address {
network: "tcp".to_string(),
addr: "80.115.186.52:9735".to_string(),
}],
};
assert_eq!(*actual, expected);
}
Expand Down Expand Up @@ -395,7 +413,7 @@ mod tests {
let expected = Node {
id: "021f0f2a5b46871b23f690a5be893f5b3ec37cf5a0fd8b89872234e984df35ea32".to_string(),
alias: String::default(),
last_update: 54321,
addresses: vec![],
};
assert_eq!(*actual, expected);
}
Expand Down

0 comments on commit f0db4f4

Please sign in to comment.