Skip to content

Commit 6ab3092

Browse files
committed
Implement GossipSource to allow RGS gossip updates
Here we implement a `GossipSource` object that allows us to configure P2P or RGS gossip sources without the need to propagate and leak LDK type parameters upwards. To this end, `GossipSource` wraps the corresponding variants and implements a `RoutingMessageHandler` that is delegating or ignoring the incoming messages.
1 parent 02a4b08 commit 6ab3092

File tree

6 files changed

+226
-41
lines changed

6 files changed

+226
-41
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ categories = ["cryptography::cryptocurrencies"]
1414
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
1515

1616
[lib]
17-
crate-type = ["staticlib", "cdylib"]
17+
crate-type = ["lib", "staticlib", "cdylib"]
1818
name = "ldk_node"
1919

2020
[[bin]]

bindings/ldk_node.udl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ enum NodeError {
7777
"WalletOperationFailed",
7878
"WalletSigningFailed",
7979
"TxSyncFailed",
80+
"GossipUpdateFailed",
8081
"InvalidAddress",
8182
"InvalidPublicKey",
8283
"InvalidPaymentHash",

src/error.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ pub enum Error {
2929
WalletSigningFailed,
3030
/// A transaction sync operation failed.
3131
TxSyncFailed,
32+
/// A gossip updating operation failed.
33+
GossipUpdateFailed,
3234
/// The given address is invalid.
3335
InvalidAddress,
3436
/// The given public key is invalid.
@@ -71,6 +73,7 @@ impl fmt::Display for Error {
7173
Self::WalletOperationFailed => write!(f, "Failed to conduct wallet operation."),
7274
Self::WalletSigningFailed => write!(f, "Failed to sign given transaction."),
7375
Self::TxSyncFailed => write!(f, "Failed to sync transactions."),
76+
Self::GossipUpdateFailed => write!(f, "Failed to update gossip data."),
7477
Self::InvalidAddress => write!(f, "The given address is invalid."),
7578
Self::InvalidPublicKey => write!(f, "The given public key is invalid."),
7679
Self::InvalidPaymentHash => write!(f, "The given payment hash is invalid."),

src/gossip.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use crate::logger::{log_trace, FilesystemLogger, Logger};
2+
use crate::types::{GossipSync, NetworkGraph, P2PGossipSync, RapidGossipSync};
3+
use crate::Error;
4+
5+
use lightning::routing::utxo::UtxoLookup;
6+
7+
use std::sync::atomic::{AtomicU32, Ordering};
8+
use std::sync::Arc;
9+
10+
pub(crate) enum GossipSource {
11+
P2PNetwork {
12+
gossip_sync: Arc<P2PGossipSync>,
13+
},
14+
RapidGossipSync {
15+
gossip_sync: Arc<RapidGossipSync>,
16+
server_url: String,
17+
latest_sync_timestamp: AtomicU32,
18+
logger: Arc<FilesystemLogger>,
19+
},
20+
}
21+
22+
impl GossipSource {
23+
pub fn new_p2p(network_graph: Arc<NetworkGraph>, logger: Arc<FilesystemLogger>) -> Self {
24+
let gossip_sync = Arc::new(P2PGossipSync::new(
25+
network_graph,
26+
None::<Arc<dyn UtxoLookup + Send + Sync>>,
27+
logger,
28+
));
29+
Self::P2PNetwork { gossip_sync }
30+
}
31+
32+
pub fn new_rgs(
33+
server_url: String, network_graph: Arc<NetworkGraph>, logger: Arc<FilesystemLogger>,
34+
) -> Self {
35+
let gossip_sync = Arc::new(RapidGossipSync::new(network_graph, Arc::clone(&logger)));
36+
let latest_sync_timestamp = AtomicU32::new(0);
37+
Self::RapidGossipSync { gossip_sync, server_url, latest_sync_timestamp, logger }
38+
}
39+
40+
pub fn is_rgs(&self) -> bool {
41+
if let Self::RapidGossipSync { .. } = self {
42+
true
43+
} else {
44+
false
45+
}
46+
}
47+
48+
pub fn as_gossip_sync(&self) -> GossipSync {
49+
match self {
50+
Self::RapidGossipSync { gossip_sync, .. } => {
51+
GossipSync::Rapid(Arc::clone(&gossip_sync))
52+
}
53+
Self::P2PNetwork { gossip_sync, .. } => GossipSync::P2P(Arc::clone(&gossip_sync)),
54+
}
55+
}
56+
57+
pub async fn update_rgs_snapshot(&self) -> Result<(), Error> {
58+
match self {
59+
Self::P2PNetwork { gossip_sync: _ } => Ok(()),
60+
Self::RapidGossipSync { gossip_sync, server_url, latest_sync_timestamp, logger } => {
61+
let query_timestamp = latest_sync_timestamp.load(Ordering::Acquire);
62+
let query_url = format!("{}/{}", server_url, query_timestamp);
63+
let response = reqwest::get(query_url).await.map_err(|e| {
64+
log_trace!(logger, "Failed to retrieve RGS gossip update: {}", e);
65+
Error::GossipUpdateFailed
66+
})?;
67+
68+
match response.error_for_status() {
69+
Ok(res) => {
70+
let update_data = res.bytes().await.map_err(|e| {
71+
log_trace!(logger, "Failed to retrieve RGS gossip update: {}", e);
72+
Error::GossipUpdateFailed
73+
})?;
74+
75+
let new_latest_sync_timestamp = gossip_sync
76+
.update_network_graph(&update_data)
77+
.map_err(|_| Error::GossipUpdateFailed)?;
78+
latest_sync_timestamp.store(new_latest_sync_timestamp, Ordering::Release);
79+
Ok(())
80+
}
81+
Err(e) => {
82+
log_trace!(logger, "Failed to retrieve RGS gossip update: {}", e);
83+
Err(Error::GossipUpdateFailed)
84+
}
85+
}
86+
}
87+
}
88+
}
89+
}

0 commit comments

Comments
 (0)