Skip to content
This repository was archived by the owner on Jan 6, 2025. It is now read-only.

Further codebase modularization #58

Merged
merged 18 commits into from
Dec 15, 2023
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
6 changes: 5 additions & 1 deletion .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,11 @@ jobs:
- name: Cargo check
run: cargo check --release
- name: Check documentation
run: cargo doc --release
run: |
cargo doc --release
cargo doc --no-default-features --features no-std
RUSTFLAGS="--cfg lsps1" cargo doc --release
RUSTFLAGS="--cfg lsps1" cargo doc --no-default-features --features no-std
- name: Build on Rust ${{ matrix.toolchain }}
run: cargo build --verbose --color always
- name: Check formatting
Expand Down
16 changes: 12 additions & 4 deletions src/events.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
//!
//! [`LiquidityManager::get_and_clear_pending_events`]: crate::LiquidityManager::get_and_clear_pending_events

use crate::lsps0;
#[cfg(lsps1)]
use crate::lsps1;
use crate::lsps2;
Expand Down Expand Up @@ -78,9 +79,16 @@ impl EventQueue {
/// An event which you should probably take some action in response to.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Event {
/// An LSPS2 (JIT Channel) protocol event.
LSPS2(lsps2::LSPS2Event),
/// An LSPS1 protocol event.
/// An LSPS0 client event.
LSPS0Client(lsps0::event::LSPS0ClientEvent),
/// An LSPS1 (Channel Request) client event.
#[cfg(lsps1)]
LSPS1(lsps1::event::Event),
LSPS1Client(lsps1::event::LSPS1ClientEvent),
/// An LSPS1 (Channel Request) server event.
#[cfg(lsps1)]
LSPS1Service(lsps1::event::LSPS1ServiceEvent),
/// An LSPS2 (JIT Channel) client event.
LSPS2Client(lsps2::event::LSPS2ClientEvent),
/// An LSPS2 (JIT Channel) server event.
LSPS2Service(lsps2::event::LSPS2ServiceEvent),
}
10 changes: 7 additions & 3 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,15 @@ mod prelude {
}

pub mod events;
mod lsps0;
pub mod lsps0;
#[cfg(lsps1)]
mod lsps1;
pub mod lsps1;
pub mod lsps2;
mod manager;
pub mod message_queue;
mod sync;
#[cfg(test)]
mod tests;
mod utils;

pub use lsps0::message_handler::{JITChannelsConfig, LiquidityManager, LiquidityProviderConfig};
pub use manager::{LiquidityClientConfig, LiquidityManager, LiquidityServiceConfig};
158 changes: 158 additions & 0 deletions src/lsps0/client.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
//! Contains the main LSPS2 client-side object, [`LSPS0ClientHandler`].
//!
//! Please refer to the [LSPS0
//! specifcation](https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS0) for more
//! information.

use crate::events::{Event, EventQueue};
use crate::lsps0::event::LSPS0ClientEvent;
use crate::lsps0::msgs::{
LSPS0Message, LSPS0Request, LSPS0Response, ListProtocolsRequest, ListProtocolsResponse,
ProtocolMessageHandler, ResponseError,
};
use crate::message_queue::MessageQueue;
use crate::sync::Arc;
use crate::utils;

use lightning::ln::msgs::{ErrorAction, LightningError};
use lightning::sign::EntropySource;
use lightning::util::logger::Level;

use bitcoin::secp256k1::PublicKey;

use core::ops::Deref;

/// A message handler capable of sending and handling LSPS0 messages.
pub struct LSPS0ClientHandler<ES: Deref, MQ: Deref>
where
ES::Target: EntropySource,
MQ::Target: MessageQueue,
{
entropy_source: ES,
pending_messages: MQ,
pending_events: Arc<EventQueue>,
}

impl<ES: Deref, MQ: Deref> LSPS0ClientHandler<ES, MQ>
where
ES::Target: EntropySource,
MQ::Target: MessageQueue,
{
/// Returns a new instance of [`LSPS0ClientHandler`].
pub(crate) fn new(
entropy_source: ES, pending_messages: MQ, pending_events: Arc<EventQueue>,
) -> Self {
Self { entropy_source, pending_messages, pending_events }
}

/// Calls LSPS0's `list_protocols`.
///
/// Please refer to the [LSPS0
/// specifcation](https://github.com/BitcoinAndLightningLayerSpecs/lsp/tree/main/LSPS0#lsps-specification-support-query)
/// for more information.
pub fn list_protocols(&self, counterparty_node_id: &PublicKey) {
let msg = LSPS0Message::Request(
utils::generate_request_id(&self.entropy_source),
LSPS0Request::ListProtocols(ListProtocolsRequest {}),
);

self.pending_messages.enqueue(counterparty_node_id, msg.into());
}

fn handle_response(
&self, response: LSPS0Response, counterparty_node_id: &PublicKey,
) -> Result<(), LightningError> {
match response {
LSPS0Response::ListProtocols(ListProtocolsResponse { protocols }) => {
self.pending_events.enqueue(Event::LSPS0Client(
LSPS0ClientEvent::ListProtocolsResponse {
counterparty_node_id: *counterparty_node_id,
protocols,
},
));
Ok(())
}
LSPS0Response::ListProtocolsError(ResponseError { code, message, data, .. }) => {
Err(LightningError {
err: format!(
"ListProtocols error received. code = {}, message = {}, data = {:?}",
code, message, data
),
action: ErrorAction::IgnoreAndLog(Level::Info),
})
}
}
}
}

impl<ES: Deref, MQ: Deref> ProtocolMessageHandler for LSPS0ClientHandler<ES, MQ>
where
ES::Target: EntropySource,
MQ::Target: MessageQueue,
{
type ProtocolMessage = LSPS0Message;
const PROTOCOL_NUMBER: Option<u16> = None;

fn handle_message(
&self, message: Self::ProtocolMessage, counterparty_node_id: &PublicKey,
) -> Result<(), LightningError> {
match message {
LSPS0Message::Response(_, response) => {
self.handle_response(response, counterparty_node_id)
}
LSPS0Message::Request(..) => {
debug_assert!(
false,
"Client handler received LSPS0 request message. This should never happen."
);
Err(LightningError { err: format!("Client handler received LSPS0 request message from node {:?}. This should never happen.", counterparty_node_id), action: ErrorAction::IgnoreAndLog(Level::Info)})
}
}
}
}

#[cfg(test)]
mod tests {

use alloc::string::ToString;
use alloc::sync::Arc;

use crate::lsps0::msgs::{LSPSMessage, RequestId};
use crate::tests::utils::{TestEntropy, TestMessageQueue};

use super::*;

#[test]
fn test_list_protocols() {
let pending_messages = Arc::new(TestMessageQueue::new());
let entropy_source = Arc::new(TestEntropy {});
let event_queue = Arc::new(EventQueue::new());

let lsps0_handler = Arc::new(LSPS0ClientHandler::new(
entropy_source,
Arc::clone(&pending_messages),
event_queue,
));

let counterparty_node_id = utils::parse_pubkey(
"027100442c3b79f606f80f322d98d499eefcb060599efc5d4ecb00209c2cb54190",
)
.unwrap();

lsps0_handler.list_protocols(&counterparty_node_id);
let pending_messages = pending_messages.get_and_clear_pending_msgs();

assert_eq!(pending_messages.len(), 1);

let (pubkey, message) = &pending_messages[0];

assert_eq!(*pubkey, counterparty_node_id);
assert_eq!(
*message,
LSPSMessage::LSPS0(LSPS0Message::Request(
RequestId("00000000000000000000000000000000".to_string()),
LSPS0Request::ListProtocols(ListProtocolsRequest {})
))
);
}
}
25 changes: 25 additions & 0 deletions src/lsps0/event.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// This file is Copyright its original authors, visible in version control
// history.
//
// This file is licensed under the Apache License, Version 2.0 <LICENSE-APACHE
// or http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your option.
// You may not use this file except in accordance with one or both of these
// licenses.

//! Contains LSPS0 event types

use crate::prelude::Vec;
use bitcoin::secp256k1::PublicKey;

/// An event which an LSPS0 client may want to take some action in response to.
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum LSPS0ClientEvent {
/// Information from the LSP about the protocols they support.
ListProtocolsResponse {
/// The node id of the LSP.
counterparty_node_id: PublicKey,
/// A list of supported protocols.
protocols: Vec<u16>,
},
}
Loading