Skip to content

Commit

Permalink
gossip_map: impl the gossip map basic types
Browse files Browse the repository at this point in the history
Signed-off-by: Vincenzo Palazzo <[email protected]>
  • Loading branch information
vincenzopalazzo committed May 6, 2023
1 parent 9da1bbc commit a8c4382
Show file tree
Hide file tree
Showing 4 changed files with 218 additions and 18 deletions.
1 change: 1 addition & 0 deletions gossip_map/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@ version = "0.1.0"
edition = "2021"

[dependencies]
byteorder = "1.4.3"
21 changes: 21 additions & 0 deletions gossip_map/src/flags.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
//! Flag implementation for the gossip map types
pub static GOSSIP_STORE_MAJOR_VERSION: u16 = 0 << 5;
pub static GOSSIP_STORE_MAJOR_VERSION_MASK: u16 = 0xE0;

/// Deleted fields should be ignored: on restart, they will be removed as the gossip_store is rewritten.
pub static GOSSIP_STORE_LEN_DELETED_BIT: u32 = 0x80000000;
/// The push flag indicates gossip which is generated locally: this is important for gossip timestamp filtering,
/// where peers request gossip and we always send our own gossip messages even if the timestamp wasn't within their
/// request.pub static GOSSIP_STORE_LEN_PUSH_BIT: u32 = 0x40000000;
pub static GOSSIP_STORE_LEN_RATELIMIT_BIT: u32 = 0x20000000;
/// The ratelimit flag indicates that this gossip message came too fast.
/// The message are corded in the gossip map, but don't relay it to peers.
pub static GOSSIP_STORE_LEN_MASK: u16 = 0x0000FFFF;

// These duplicate constants in lightning/gossipd/gossip_store_wiregen.h
pub const WIRE_GOSSIP_STORE_PRIVATE_CHANNEL: u16 = 4104;
pub const WIRE_GOSSIP_STORE_PRIVATE_UPDATE: u16 = 4102;
pub const WIRE_GOSSIP_STORE_DELETE_CHAN: u16 = 4103;
pub const WIRE_GOSSIP_STORE_ENDED: u16 = 4105;
pub const WIRE_GOSSIP_STORE_CHANNEL_AMOUNT: u16 = 4101;
74 changes: 66 additions & 8 deletions gossip_map/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,20 +1,78 @@
struct GossipMap;
use byteorder::{BigEndian, ReadBytesExt};
use flags::{
GOSSIP_STORE_MAJOR_VERSION, GOSSIP_STORE_MAJOR_VERSION_MASK, WIRE_GOSSIP_STORE_CHANNEL_AMOUNT,
WIRE_GOSSIP_STORE_DELETE_CHAN, WIRE_GOSSIP_STORE_ENDED, WIRE_GOSSIP_STORE_PRIVATE_CHANNEL,
WIRE_GOSSIP_STORE_PRIVATE_UPDATE,
};
use std::{
fs::File,
io::{BufReader, Error, ErrorKind},
};
use types::{GossipChannel, GossipNode};

mod flags;
mod types;

/// Gossip map implementation, that allow you to manage the gossip_store
/// written by core lightning.
struct GossipMap {
version: u8,
stream: Option<BufReader<File>>,
}

impl GossipMap {
// Create a new instance of the gossip map.
pub fn new() -> Self {
GossipMap {}
pub fn new(version: u8) -> Self {
GossipMap {
version,
stream: None,
}
}

pub fn get_channel(short_chananel_id: &str) -> Result<(), ()> {
Ok(())
pub fn from_file(file_name: &str) -> Result<Self, std::io::Error> {
let gossip_store = File::open(file_name)?;
let stream = BufReader::new(gossip_store);
let mut gossip_map = GossipMap {
version: 0,
stream: Some(stream),
};
gossip_map.refresh()?;
Ok(gossip_map)
}

pub fn get_node(node_id: &str) -> Result<(), ()> {
Ok(())
pub fn get_channel(short_chananel_id: &str) -> Result<&'static GossipChannel, ()> {
todo!()
}

pub fn refresh() -> Result<(), ()> {
pub fn get_node(node_id: &str) -> Result<&'static GossipNode, ()> {
todo!()
}

fn refresh(&mut self) -> Result<(), std::io::Error> {
let version = self.stream.as_mut().unwrap().read_u8()? as u16;
if (version & GOSSIP_STORE_MAJOR_VERSION_MASK) != GOSSIP_STORE_MAJOR_VERSION {
return Err(Error::new(
ErrorKind::Other,
"Invalid gossip tore version {version}",
));
}
self.version = version as u8;

while let Ok(chunk) = self.stream.as_mut().unwrap().read_u8() {
match chunk as u16 {
// channel announcement!
256 => todo!(),
WIRE_GOSSIP_STORE_PRIVATE_CHANNEL => todo!("parsing the private channel"),
WIRE_GOSSIP_STORE_CHANNEL_AMOUNT => todo!("channel ammount"),
WIRE_GOSSIP_STORE_PRIVATE_UPDATE => todo!("private update"),
WIRE_GOSSIP_STORE_DELETE_CHAN => todo!("channel deleted"),
WIRE_GOSSIP_STORE_ENDED => todo!("need to be reimplemented the open store"),
257 => todo!("node announcment"),
258 => todo!("channel update"),
_ => continue,
}
}

Ok(())
}
}
140 changes: 130 additions & 10 deletions gossip_map/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,136 @@
//! Gossip map types implementations.
use byteorder::{BigEndian, ReadBytesExt};
use std::{collections::HashMap, io::BufRead, ops::Deref, str, str::Bytes, vec::Vec};

/// TODO: implement it.
struct GossipNodeId;
use crate::flags::{GOSSIP_STORE_LEN_DELETED_BIT, GOSSIP_STORE_LEN_MASK};

/// TODO: implement it.
struct GossipNode;
trait GossipType {
/// Decode the gossip message from a sequence of bytes.
fn decode(stream: &mut dyn BufRead) -> Result<Self, std::io::Error>
where
Self: Sized;

/// TODO: implement it
struct GossipChannel;
/// Encode the gossip message in a sequence of bytes.
fn encode(&self) -> Bytes;
}

/// TODO: implement it
struct GossipPartialChannel;
/// Node Id encoded for the gossip map
pub struct GossipNodeId {
node_id: String,
}

// TODO: implementing it
struct GossipStoredHeader;
impl GossipNodeId {
pub(crate) fn from_bytes(buff: &[u8; 32]) -> GossipNodeId {
GossipNodeId {
node_id: String::from_utf8(buff.to_vec()).unwrap(),
}
}
}

impl GossipType for GossipNodeId {
fn decode(stream: &mut dyn BufRead) -> Result<Self, std::io::Error>
where
Self: Sized,
{
let mut node_id: String = String::new();
stream.read_to_string(&mut node_id)?;

// FIXME: missed sanity check!
let res = GossipNodeId { node_id };
Ok(res)
}

fn encode(&self) -> Bytes {
todo!()
}
}

pub struct GossipNode<'a> {
node_id: GossipNodeId,
announce_fileds: Option<HashMap<String, String>>,
announce_offset: Option<u32>,
channels: Vec<&'a GossipChannel<'a>>,
}

impl<'a> GossipNode<'a> {
/// add a gossip channel inside the gossip map.
pub fn add_channel(&'a mut self, channel: &'a GossipChannel) {
self.channels.push(channel);
}
}

impl GossipType for GossipNode<'_> {
fn decode(stream: &mut dyn BufRead) -> Result<Self, std::io::Error>
where
Self: Sized,
{
let mut buff = [0; 32];
stream.read_exact(&mut buff)?;
let node_id = GossipNodeId::from_bytes(&buff);
todo!()
}

fn encode(&self) -> Bytes {
todo!()
}
}

/// Channel Information stored inside the Gossip Map.
pub struct GossipChannel<'a> {
fileds: HashMap<String, String>,
annound_offset: u32,
scid: String,
node_one: &'a GossipNode<'a>,
node_two: &'a GossipNode<'a>,
update_fields: Vec<HashMap<String, String>>,
update_offset: Vec<u32>,
satoshi: Option<u64>,
half_channels: Vec<&'a GossipPartialChannel>,
}

impl GossipType for GossipChannel<'_> {
fn decode(stream: &mut dyn BufRead) -> Result<Self, std::io::Error>
where
Self: Sized,
{
todo!()
}

fn encode(&self) -> Bytes {
todo!()
}
}

/// One direction gossip map channel
pub struct GossipPartialChannel {}

/// Gossip map header, that contains the version
/// of the gossip map.
pub struct GossipStoredHeader {
flags: bool,
len: u16,
crc: u32,
timestamp: u32,
}

impl GossipType for GossipStoredHeader {
fn decode(stream: &mut dyn BufRead) -> Result<Self, std::io::Error>
where
Self: Sized,
{
let len = stream.read_u16::<BigEndian>()?;
let crc = stream.read_u32::<BigEndian>()?;
let timestamp = stream.read_u32::<BigEndian>()?;

Ok(GossipStoredHeader {
timestamp,
crc,
flags: (len as u32 & GOSSIP_STORE_LEN_DELETED_BIT) != 0,
len: (len & GOSSIP_STORE_LEN_MASK),
})
}

fn encode(&self) -> Bytes {
todo!()
}
}

0 comments on commit a8c4382

Please sign in to comment.