Skip to content

[0.0.111-bindings] Improve RGS Documentation and Support RGS no-std #1755

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lightning-rapid-gossip-sync/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ Utility to process gossip routing data from Rapid Gossip Sync Server.
"""

[features]
default = ["std"]
no-std = ["lightning/no-std"]
std = ["lightning/std"]
_bench_unstable = []

[dependencies]
Expand Down
74 changes: 43 additions & 31 deletions lightning-rapid-gossip-sync/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,24 +10,35 @@
#![deny(unused_mut)]
#![deny(unused_variables)]
#![deny(unused_imports)]
//! This crate exposes functionality to rapidly sync gossip data, aimed primarily at mobile
//! This crate exposes client functionality to rapidly sync gossip data, aimed primarily at mobile
//! devices.
//!
//! The server sends a compressed response containing differential gossip data. The gossip data is
//! formatted compactly, omitting signatures and opportunistically incremental where previous
//! channel updates are known (a mechanism that is enabled when the timestamp of the last known
//! channel update is communicated). A reference server implementation can be found
//! [here](https://github.com/lightningdevkit/rapid-gossip-sync-server).
//! The rapid gossip sync server will provide a compressed response containing differential gossip
//! data. The gossip data is formatted compactly, omitting signatures and opportunistically
//! incremental where previous channel updates are known. This mechanism is enabled when the
//! timestamp of the last known channel update is communicated. A reference server implementation
//! can be found [on Github](https://github.com/lightningdevkit/rapid-gossip-sync-server).
//!
//! An example server request could look as simple as the following. Note that the first ever rapid
//! sync should use `0` for `last_sync_timestamp`:
//! The primary benefit of this syncing mechanism is that it allows a low-powered client to offload
//! the validation of gossip signatures to a semi-trusted server. This enables the client to
//! privately calculate routes for payments, and to do so much faster than requiring a full
//! peer-to-peer gossip sync to complete.
//!
//! The server calculates its response on the basis of a client-provided `latest_seen` timestamp,
//! i.e., the server will return all rapid gossip sync data it has seen after the given timestamp.
//!
//! # Getting Started
//! Firstly, the data needs to be retrieved from the server. For example, you could use the server
//! at <https://rapidsync.lightningdevkit.org> with the following request format:
//!
//! ```shell
//! curl -o rapid_sync.lngossip https://rapidsync.lightningdevkit.org/snapshot/<last_sync_timestamp>
//! ```
//! Note that the first ever rapid sync should use `0` for `last_sync_timestamp`.
//!
//! Then, call the network processing function. In this example, we process the update by reading
//! its contents from disk, which we do by calling the `sync_network_graph_with_file_path` method:
//! After the gossip data snapshot has been downloaded, one of the client's graph processing
//! functions needs to be called. In this example, we process the update by reading its contents
//! from disk, which we do by calling [sync_network_graph_with_file_path]:
//!
//! ```
//! use bitcoin::blockdata::constants::genesis_block;
Expand All @@ -47,31 +58,19 @@
//! let rapid_sync = RapidGossipSync::new(&network_graph);
//! let new_last_sync_timestamp_result = rapid_sync.sync_network_graph_with_file_path("./rapid_sync.lngossip");
//! ```
//!
//! The primary benefit this syncing mechanism provides is that given a trusted server, a
//! low-powered client can offload the validation of gossip signatures. This enables a client to
//! privately calculate routes for payments, and do so much faster and earlier than requiring a full
//! peer-to-peer gossip sync to complete.
//!
//! The reason the rapid sync server requires trust is that it could provide bogus data, though at
//! worst, all that would result in is a fake network topology, which wouldn't enable the server to
//! steal or siphon off funds. It could, however, reduce the client's privacy by forcing all
//! payments to be routed via channels the server controls.
//!
//! The way a server is meant to calculate this rapid gossip sync data is by using a `latest_seen`
//! timestamp provided by the client. It's not included in either channel announcement or update,
//! (not least due to announcements not including any timestamps at all, but only a block height)
//! but rather, it's a timestamp of when the server saw a particular message.
//! [sync_network_graph_with_file_path]: RapidGossipSync::sync_network_graph_with_file_path

// Allow and import test features for benching
#![cfg_attr(all(test, feature = "_bench_unstable"), feature(test))]
#[cfg(all(test, feature = "_bench_unstable"))]
extern crate test;

#[cfg(feature = "std")]
use std::fs::File;
use std::ops::Deref;
use std::sync::atomic::{AtomicBool, Ordering};
use core::ops::Deref;
use core::sync::atomic::{AtomicBool, Ordering};

use lightning::io;
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;

Expand All @@ -83,7 +82,8 @@ pub mod error;
/// Core functionality of this crate
pub mod processing;

/// Rapid Gossip Sync struct
/// The main Rapid Gossip Sync object.
///
/// See [crate-level documentation] for usage.
///
/// [crate-level documentation]: crate
Expand All @@ -94,21 +94,22 @@ where L::Target: Logger {
}

impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
/// Instantiate a new [`RapidGossipSync`] instance
/// Instantiate a new [`RapidGossipSync`] instance.
pub fn new(network_graph: NG) -> Self {
Self {
network_graph,
is_initial_sync_complete: AtomicBool::new(false)
}
}

/// Sync gossip data from a file
/// Sync gossip data from a file.
/// Returns the last sync timestamp to be used the next time rapid sync data is queried.
///
/// `network_graph`: The network graph to apply the updates to
///
/// `sync_path`: Path to the file where the gossip update data is located
///
#[cfg(feature = "std")]
pub fn sync_network_graph_with_file_path(
&self,
sync_path: &str,
Expand All @@ -117,6 +118,17 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
self.update_network_graph_from_byte_stream(&mut file)
}

/// Update network graph from binary data.
/// Returns the last sync timestamp to be used the next time rapid sync data is queried.
///
/// `network_graph`: network graph to be updated
///
/// `update_data`: `&[u8]` binary stream that comprises the update data
pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
let mut read_cursor = io::Cursor::new(update_data);
self.update_network_graph_from_byte_stream(&mut read_cursor)
}

/// Gets a reference to the underlying [`NetworkGraph`] which was provided in
/// [`RapidGossipSync::new`].
///
Expand All @@ -125,7 +137,7 @@ impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L
&self.network_graph
}

/// Returns whether a rapid gossip sync has completed at least once
/// Returns whether a rapid gossip sync has completed at least once.
pub fn is_initial_sync_complete(&self) -> bool {
self.is_initial_sync_complete.load(Ordering::Acquire)
}
Expand Down
23 changes: 5 additions & 18 deletions lightning-rapid-gossip-sync/src/processing.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
use std::cmp::max;
use std::io;
use std::io::Read;
use std::ops::Deref;
use std::sync::atomic::Ordering;
use core::cmp::max;
use core::ops::Deref;
use core::sync::atomic::Ordering;

use bitcoin::BlockHash;
use bitcoin::secp256k1::PublicKey;
Expand All @@ -13,6 +11,7 @@ use lightning::ln::msgs::{
use lightning::routing::gossip::NetworkGraph;
use lightning::util::logger::Logger;
use lightning::util::ser::{BigSize, Readable};
use lightning::io;

use crate::error::GraphSyncError;
use crate::RapidGossipSync;
Expand All @@ -28,19 +27,7 @@ const GOSSIP_PREFIX: [u8; 4] = [76, 68, 75, 1];
const MAX_INITIAL_NODE_ID_VECTOR_CAPACITY: u32 = 50_000;

impl<NG: Deref<Target=NetworkGraph<L>>, L: Deref> RapidGossipSync<NG, L> where L::Target: Logger {
/// Update network graph from binary data.
/// Returns the last sync timestamp to be used the next time rapid sync data is queried.
///
/// `network_graph`: network graph to be updated
///
/// `update_data`: `&[u8]` binary stream that comprises the update data
pub fn update_network_graph(&self, update_data: &[u8]) -> Result<u32, GraphSyncError> {
let mut read_cursor = io::Cursor::new(update_data);
self.update_network_graph_from_byte_stream(&mut read_cursor)
}


pub(crate) fn update_network_graph_from_byte_stream<R: Read>(
pub(crate) fn update_network_graph_from_byte_stream<R: io::Read>(
&self,
mut read_cursor: &mut R,
) -> Result<u32, GraphSyncError> {
Expand Down
3 changes: 2 additions & 1 deletion no-std-check/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,9 @@ version = "0.1.0"
edition = "2018"

[features]
default = ["lightning/no-std", "lightning-invoice/no-std"]
default = ["lightning/no-std", "lightning-invoice/no-std", "lightning-rapid-gossip-sync/no-std"]

[dependencies]
lightning = { path = "../lightning", default-features = false }
lightning-invoice = { path = "../lightning-invoice", default-features = false }
lightning-rapid-gossip-sync = { path = "../lightning-rapid-gossip-sync", default-features = false }