Skip to content
Open
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
82 changes: 54 additions & 28 deletions crates/fiber-bin/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ use fnn::watchtower::{
WatchtowerActor, WatchtowerMessage, DEFAULT_WATCHTOWER_CHECK_INTERVAL_SECONDS,
};
use fnn::{start_network, CchActor, Config, NetworkServiceEvent};
use jsonrpsee::http_client::HttpClientBuilder;
use jsonrpsee::http_client::{HttpClient, HttpClientBuilder};
use jsonrpsee::ws_client::{HeaderMap, HeaderValue};
use ractor::{port::OutputPortSubscriberTrait as _, Actor, ActorRef, OutputPort};
#[cfg(debug_assertions)]
Expand All @@ -44,6 +44,27 @@ const ASSUME_WATCHTOWER_CLIENT_CALL_OK: &str = "watchtower client call should be

pub struct ExitMessage(String);

/// Build an HTTP client for the standalone watchtower RPC, optionally with a Bearer token.
fn build_watchtower_rpc_client(
url: impl AsRef<str>,
token: Option<&str>,
) -> Result<HttpClient, ExitMessage> {
let mut client_builder = HttpClientBuilder::default();
if let Some(token) = token {
let mut headers = HeaderMap::new();
headers.insert(
"Authorization",
HeaderValue::from_str(&format!("Bearer {}", token)).map_err(|err| {
ExitMessage(format!("failed to create watchtower rpc client: {err:?}"))
})?,
);
client_builder = client_builder.set_headers(headers);
}
client_builder
.build(url)
.map_err(|err| ExitMessage(format!("failed to create watchtower rpc client: {}", err)))
}

#[tokio::main]
pub async fn main() -> Result<(), ExitMessage> {
// ractor will set "id" for each actor:
Expand Down Expand Up @@ -168,6 +189,36 @@ pub async fn main() -> Result<(), ExitMessage> {

info!("Starting fiber");

// Build the standalone watchtower RPC client once if configured.
let standalone_watchtower_client = fiber_config
.standalone_watchtower_rpc_url
.as_ref()
.map(|url| {
if fiber_config.standalone_watchtower_token.is_none() {
tracing::debug!(
"create watchtower rpc client without standalone_watchtower_token"
);
}
build_watchtower_rpc_client(
url,
fiber_config.standalone_watchtower_token.as_deref(),
)
})
.transpose()?;

// Construct watchtower querier before starting network.
// Prefer local store (built-in watchtower) over standalone RPC for efficiency.
let watchtower_querier: Option<Arc<dyn fnn::fiber::WatchtowerQuerier>> =
if !fiber_config.disable_built_in_watchtower.unwrap_or_default() {
Some(Arc::new(store.clone()))
} else if let Some(client) = standalone_watchtower_client.clone() {
Some(Arc::new(fnn::rpc::watchtower::WatchtowerRpcQuerier::new(
client,
)))
} else {
None
};

let chain_client = CkbRpcClient::new(&ckb_config);
let network_actor: ActorRef<NetworkActorMessage> = start_network(
fiber_config.clone(),
Expand All @@ -179,6 +230,7 @@ pub async fn main() -> Result<(), ExitMessage> {
store.clone(),
network_graph.clone(),
default_shutdown_script,
watchtower_querier,
)
.await;

Expand All @@ -191,33 +243,7 @@ pub async fn main() -> Result<(), ExitMessage> {
);
}

let watchtower_client = if let Some(url) =
fiber_config.standalone_watchtower_rpc_url.clone()
{
let mut client_builder = HttpClientBuilder::default();

if let Some(token) = fiber_config.standalone_watchtower_token.as_ref() {
let mut headers = HeaderMap::new();
headers.insert(
"Authorization",
HeaderValue::from_str(&format!("Bearer {}", token)).map_err(|err| {
ExitMessage(format!("failed to create watchtower rpc client: {err:?}"))
})?,
);
client_builder = client_builder.set_headers(headers);
} else {
tracing::debug!(
"create watchtower rpc client without standalone_watchtower_token"
);
}

let watchtower_client = client_builder.build(url).map_err(|err| {
ExitMessage(format!("failed to create watchtower rpc client: {}", err))
})?;
Some(watchtower_client)
} else {
None
};
let watchtower_client = standalone_watchtower_client;

let watchtower_actor = if fiber_config.disable_built_in_watchtower.unwrap_or_default() {
None
Expand Down
2 changes: 0 additions & 2 deletions crates/fiber-lib/src/fiber/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6895,8 +6895,6 @@ pub trait ChannelActorStateStore {
fn remove_payment_hold_tlc(&self, payment_hash: &Hash256, channel_id: &Hash256, tlc_id: u64);
fn get_payment_hold_tlcs(&self, payment_hash: Hash256) -> Vec<HoldTlc>;
fn get_node_hold_tlcs(&self) -> HashMap<Hash256, Vec<HoldTlc>>;
/// Check if a tlc is settled on chain
fn is_tlc_settled(&self, channel_id: &Hash256, payment_hash: &Hash256) -> bool;
}

/// Store trait for persisting and querying outbound channel-opening records.
Expand Down
3 changes: 3 additions & 0 deletions crates/fiber-lib/src/fiber/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ pub mod payment;
#[cfg(all(feature = "pprof", not(target_arch = "wasm32")))]
pub mod profiling;
pub mod types;
pub mod watchtower_query;

mod fee;
mod in_flight_ckb_tx_actor;
mod key;
mod path;
mod settle_tlc_set_command;
mod watchtower_query_actor;

pub use config::FiberConfig;
pub use fiber_types::*;
Expand All @@ -26,6 +28,7 @@ pub use network::{
NetworkServiceEvent,
};
pub use settle_tlc_set_command::SettleTlcSetCommand;
pub use watchtower_query::{TlcWatchtowerStatus, WatchtowerQuerier};

pub(crate) const ASSUME_NETWORK_ACTOR_ALIVE: &str = "network actor must be alive";

Expand Down
Loading
Loading