Skip to content

Commit a3b382f

Browse files
feat: add the possiblity to add a node and a channel
Signed-off-by: Vincenzo Palazzo <[email protected]>
1 parent cd20cfc commit a3b382f

File tree

5 files changed

+236
-128
lines changed

5 files changed

+236
-128
lines changed

gossip_map/Cargo.toml

+4-2
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
byteorder = "1.4.3"
8-
fundamentals = "^0.0.1-alpha.2"
9-
fundamentals-derive = "^0.0.1-alpha.1"
8+
hex = "0.4.3"
9+
bitcoin = { version = "0.30.0" }
10+
fundamentals = "^0.0.1-alpha.3"
11+
fundamentals-derive = "^0.0.1-alpha.2"

gossip_map/src/flags.rs

+3-4
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,13 @@ pub static GOSSIP_STORE_MAJOR_VERSION: u16 = 0 << 5;
44
pub static GOSSIP_STORE_MAJOR_VERSION_MASK: u16 = 0xE0;
55

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

1615
// These duplicate constants in lightning/gossipd/gossip_store_wiregen.h
1716
pub const WIRE_GOSSIP_STORE_PRIVATE_CHANNEL: u16 = 4104;

gossip_map/src/gossip_store_msg.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ pub struct GossipStoreChannelAmount {
2020
#[warn(dead_code)]
2121
#[msg_type = 4101]
2222
ty: u16,
23-
satoshis: u16,
23+
pub satoshis: u64,
2424
}
2525

2626
#[derive(DecodeWire, EncodeWire, Debug)]

gossip_map/src/lib.rs

+139-29
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
1-
use std::{
2-
collections::{HashMap, HashSet},
3-
fs::File,
4-
io::{BufReader, Error, ErrorKind},
5-
};
1+
#![allow(dead_code)]
2+
use std::collections::HashMap;
3+
use std::fs::File;
4+
use std::io::{BufReader, Error, ErrorKind};
65

7-
use fundamentals::{
8-
bolt::bolt7::ChannelAnnouncement,
9-
prelude::bolt7::{ChannelUpdate, NodeAnnouncement},
10-
};
11-
use fundamentals::{core::FromWire, types::ShortChannelId};
6+
use fundamentals::core::FromWire;
7+
use fundamentals::prelude::bolt7::{ChannelAnnouncement, ChannelUpdate, NodeAnnouncement};
8+
use fundamentals::types::ShortChannelId;
129

1310
mod flags;
1411
mod gossip_store_msg;
@@ -20,27 +17,28 @@ use flags::{
2017
WIRE_GOSSIP_STORE_PRIVATE_UPDATE,
2118
};
2219
use gossip_store_msg::*;
23-
use types::{GossipChannel, GossipNode, GossipNodeId};
20+
use types::{GossipChannel, GossipNode, GossipNodeId, GossipStoredHeader};
2421

2522
/// Gossip map implementation, that allow you to manage the gossip_store
2623
/// written by core lightning.
27-
struct GossipMap<'a> {
24+
#[derive(Debug)]
25+
struct GossipMap {
2826
version: u8,
2927
stream: Option<BufReader<File>>,
30-
nodes: HashMap<GossipNodeId, GossipNode<'a>>,
31-
channels: HashMap<ShortChannelId, GossipChannel<'a>>,
32-
orphan_channel_updates: HashSet<ChannelUpdate>,
28+
nodes: HashMap<GossipNodeId, GossipNode>,
29+
channels: HashMap<ShortChannelId, GossipChannel>,
30+
orphan_channel_updates: HashMap<ShortChannelId, ChannelUpdate>,
3331
}
3432

35-
impl GossipMap<'_> {
33+
impl GossipMap {
3634
// Create a new instance of the gossip map.
3735
pub fn new(version: u8) -> Self {
3836
GossipMap {
3937
version,
4038
stream: None,
4139
nodes: HashMap::new(),
4240
channels: HashMap::new(),
43-
orphan_channel_updates: HashSet::new(),
41+
orphan_channel_updates: HashMap::new(),
4442
}
4543
}
4644

@@ -52,23 +50,27 @@ impl GossipMap<'_> {
5250
stream: Some(stream),
5351
nodes: HashMap::new(),
5452
channels: HashMap::new(),
55-
orphan_channel_updates: HashSet::new(),
53+
orphan_channel_updates: HashMap::new(),
5654
};
5755
gossip_map.refresh()?;
5856
Ok(gossip_map)
5957
}
6058

61-
pub fn get_channel(&self, short_chananel_id: &str) -> Option<&'static GossipChannel> {
59+
pub fn get_channel(&self, short_chananel_id: &str) -> Option<&GossipChannel> {
6260
self.channels.get(short_chananel_id.as_bytes())
6361
}
6462

65-
pub fn get_node(&self, node_id: &str) -> Option<&'static GossipNode> {
66-
// FIXME: store the node as String?
67-
self.nodes.get(&GossipNodeId {
68-
node_id: node_id.to_owned(),
69-
})
63+
pub fn get_node(&self, node_id: &str) -> Option<&GossipNode> {
64+
let node_id = GossipNodeId::from(node_id);
65+
self.nodes.get(&node_id)
7066
}
7167

68+
/// add a node announcement message inside the gossip map
69+
fn add_node_announcement(&mut self, node_announce: NodeAnnouncement) {}
70+
71+
/// add a channel announcement message inside the gossip map.
72+
fn add_channel_announcement(&mut self, channel_announce: ChannelAnnouncement) {}
73+
7274
fn refresh(&mut self) -> std::io::Result<()> {
7375
let mut stream = self.stream.as_mut().unwrap();
7476
let version = u8::from_wire(&mut stream)? as u16;
@@ -79,38 +81,146 @@ impl GossipMap<'_> {
7981
));
8082
}
8183
self.version = version as u8;
84+
println!("version {version}");
8285

83-
while let Ok(chunk) = u8::from_wire(&mut stream) {
84-
match chunk as u16 {
86+
let mut last_short_channel_id: Option<ShortChannelId> = None;
87+
loop {
88+
let Ok(header) = GossipStoredHeader::from_wire(&mut stream) else {
89+
break; // EOF?
90+
};
91+
match header.flag() {
92+
flags::GOSSIP_STORE_LEN_DELETED_BIT | flags::GOSSIP_STORE_LEN_RATELIMIT_BIT => {
93+
continue
94+
}
95+
_ => {}
96+
}
97+
98+
println!("header {:?}", header);
99+
let chunk = u16::from_wire(&mut stream)?;
100+
println!("chunk {chunk}");
101+
match chunk {
85102
// channel announcement!
86103
256 => {
87104
let channel_announcement = ChannelAnnouncement::from_wire(&mut stream)?;
105+
let node_one = GossipNodeId::from_bytes(&channel_announcement.node_id_1)?;
106+
let node_two = GossipNodeId::from_bytes(&channel_announcement.node_id_2)?;
107+
if !self.nodes.contains_key(&node_one) {
108+
let node = GossipNode::new(node_one.clone(), None);
109+
self.nodes.insert(node_one.clone(), node);
110+
}
111+
112+
if !self.nodes.contains_key(&node_two) {
113+
let node = GossipNode::new(node_two.clone(), None);
114+
self.nodes.insert(node_two.clone(), node);
115+
}
116+
println!("{:?}", self.nodes);
117+
last_short_channel_id = Some(channel_announcement.short_channel_id);
118+
let channel = GossipChannel::new(channel_announcement, &node_one, &node_two);
119+
// SAFETY: this is sage because the node is always present, due the
120+
// previous checks.
121+
let node_one = self.nodes.get_mut(&node_one).unwrap();
122+
node_one.add_channel(&channel.clone());
123+
let node_two = self.nodes.get_mut(&node_two).unwrap();
124+
node_two.add_channel(&channel.clone());
125+
self.channels
126+
.insert(last_short_channel_id.unwrap(), channel);
88127
}
89128
WIRE_GOSSIP_STORE_PRIVATE_CHANNEL => {
90-
let private_channel = GossipStorePrivateChannel::from_wire(&mut stream)?;
129+
let _ = stream.seek_relative(2 + 8 + 2)?;
130+
let channel_announcement = ChannelAnnouncement::from_wire(&mut stream)?;
131+
132+
let node_one = GossipNodeId::from_bytes(&channel_announcement.node_id_1)?;
133+
let node_two = GossipNodeId::from_bytes(&channel_announcement.node_id_2)?;
134+
if !self.nodes.contains_key(&node_one) {
135+
let node = GossipNode::new(node_one.clone(), None);
136+
self.nodes.insert(node_one.clone(), node);
137+
}
138+
139+
if !self.nodes.contains_key(&node_two) {
140+
let node = GossipNode::new(node_two.clone(), None);
141+
self.nodes.insert(node_two.clone(), node);
142+
}
143+
144+
last_short_channel_id = Some(channel_announcement.short_channel_id);
145+
let mut channel =
146+
GossipChannel::new(channel_announcement, &node_one, &node_two);
147+
// SAFETY: this is sage because the node is always present, due the
148+
// previous checks.
149+
let node_one = self.nodes.get_mut(&node_one).unwrap();
150+
node_one.add_channel(&channel.clone());
151+
let node_two = self.nodes.get_mut(&node_two).unwrap();
152+
node_two.add_channel(&channel.clone());
153+
channel.set_private(true);
154+
self.channels
155+
.insert(last_short_channel_id.unwrap(), channel);
91156
}
92157
WIRE_GOSSIP_STORE_CHANNEL_AMOUNT => {
93158
let channel_amount = GossipStoreChannelAmount::from_wire(&mut stream)?;
159+
//FIXME: remove the unwrap().
160+
assert!(last_short_channel_id.is_some());
161+
let channel = self
162+
.channels
163+
.get_mut(&last_short_channel_id.unwrap())
164+
.unwrap();
165+
channel.set_amount(channel_amount);
94166
}
95167
WIRE_GOSSIP_STORE_PRIVATE_UPDATE => {
96168
let private_update = GossipStorePrivateUpdate::from_wire(&mut stream)?;
169+
unimplemented!()
97170
}
98171
WIRE_GOSSIP_STORE_DELETE_CHAN => {
99172
let del_chan = GossipStoreDeleteChan::from_wire(&mut stream)?;
173+
unimplemented!()
100174
}
101175
WIRE_GOSSIP_STORE_ENDED => {
102-
let eof = GossipStoreEnded::from_wire(&mut stream)?;
176+
let _ = GossipStoreEnded::from_wire(&mut stream)?;
177+
break;
103178
}
104179
257 => {
105180
let node_announcement = NodeAnnouncement::from_wire(&mut stream)?;
181+
let node_id = GossipNodeId::from_bytes(&node_announcement.node_id)?;
182+
if !self.nodes.contains_key(&node_id) {
183+
let node = GossipNode::new(node_id.clone(), Some(node_announcement));
184+
self.nodes.insert(node_id, node);
185+
}
106186
}
107187
258 => {
108188
let channel_update = ChannelUpdate::from_wire(&mut stream)?;
189+
if self.channels.contains_key(&channel_update.short_channel_id) {
190+
// SAFETY: we check the existence before!
191+
let channel = self
192+
.channels
193+
.get_mut(&channel_update.short_channel_id)
194+
.unwrap();
195+
channel.channel_update(&channel_update)
196+
} else {
197+
self.orphan_channel_updates
198+
.insert(channel_update.short_channel_id, channel_update);
199+
}
109200
}
110-
_ => continue,
201+
_ => assert!(false),
111202
}
203+
println!("----------------------------------------------------");
112204
}
113205

114206
Ok(())
115207
}
116208
}
209+
210+
#[cfg(test)]
211+
mod tests {
212+
use super::*;
213+
214+
#[test]
215+
fn read_gossipmap_from_file() {
216+
let path = "/run/media/vincent/VincentSSD/.lightning/testnet/gossip_store";
217+
let pubkey = "03b39d1ddf13ce486de74e9e44e0538f960401a9ec75534ba9cfe4100d65426880";
218+
let map = GossipMap::from_file(path);
219+
assert!(map.is_ok(), "{:?}", map);
220+
let map = map.unwrap();
221+
assert!(
222+
map.get_node(pubkey).is_some(),
223+
"node with id `{pubkey}` not found!"
224+
);
225+
}
226+
}

0 commit comments

Comments
 (0)