diff --git a/Cargo.lock b/Cargo.lock index 2743d4d9..762e2b8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5341,15 +5341,6 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" -[[package]] -name = "signal-hook-registry" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" -dependencies = [ - "libc", -] - [[package]] name = "signature" version = "2.2.0" @@ -5760,9 +5751,7 @@ dependencies = [ "bytes", "libc", "mio", - "parking_lot", "pin-project-lite", - "signal-hook-registry", "socket2", "tokio-macros", "windows-sys 0.52.0", diff --git a/node-native/Cargo.toml b/node-native/Cargo.toml index e097fa66..693b6e7e 100644 --- a/node-native/Cargo.toml +++ b/node-native/Cargo.toml @@ -16,9 +16,8 @@ lumina-node.workspace = true celestia-types.workspace = true tendermint.workspace = true libp2p.workspace = true - -uniffi = { version = "0.28.3", features = ["bindgen", "tokio", "cli"] } -tokio = { version = "1.0", features = ["full"] } redb = "2.1.1" thiserror = "1.0.61" -serde_json = "1.0.64" \ No newline at end of file +serde_json = "1.0.64" +uniffi = { version = "0.28.3", features = ["bindgen", "tokio", "cli"] } +tokio = { version = "1.38.0", features = ["macros", "sync"] } \ No newline at end of file diff --git a/node-native/src/bin/uniffi-bindgen.rs b/node-native/src/bin/uniffi-bindgen.rs index f6cff6cf..c89b7813 100644 --- a/node-native/src/bin/uniffi-bindgen.rs +++ b/node-native/src/bin/uniffi-bindgen.rs @@ -1,3 +1,8 @@ +//! Binary executable for generating UniFFI bindings. +//! +//! This binary is used by the build system to generate language bindings. + +/// This is the entry point for the uniffi-bindgen binary. fn main() { uniffi::uniffi_bindgen_main() } diff --git a/node-native/src/lib.rs b/node-native/src/lib.rs index 36fc6cf8..54c3e145 100644 --- a/node-native/src/lib.rs +++ b/node-native/src/lib.rs @@ -1,3 +1,8 @@ +//! Native library providing Rust to mobile language bindings for the Lumina node. +//! +//! This crate uses Mozillas UniFFI to generate Swift and Kotlin bindings for the Lumina node, +//! allowing it to be used from iOS and Android applications. + mod types; use celestia_types::ExtendedHeader; @@ -5,17 +10,18 @@ use libp2p::identity::Keypair; use lumina_node::{ blockstore::RedbBlockstore, events::{EventSubscriber, TryRecvError}, - network::{canonical_network_bootnodes, network_id}, + network, store::RedbStore, - Node, NodeConfig, NodeError, + Node, NodeError, }; -use std::{path::PathBuf, str::FromStr, sync::Arc, time::Duration}; +use std::{path::PathBuf, str::FromStr, sync::Arc}; use tendermint::hash::Hash; use thiserror::Error; use tokio::sync::Mutex; use types::{Network, NetworkInfo, NodeEvent, PeerId, PeerTrackerInfo, SyncingInfo}; use uniffi::Object; +/// Result type alias for LuminaNode operations that can fail with a LuminaError pub type Result = std::result::Result; /// Returns the platform-specific base path for storing Lumina data. @@ -52,24 +58,55 @@ fn get_base_path() -> Result { } } +/// Represents all possible errors that can occur in the LuminaNode. #[derive(Error, Debug, uniffi::Error)] pub enum LuminaError { + /// Error returned when trying to perform operations on a node that isn't running #[error("Node is not running")] NodeNotRunning, + + /// Error returned when network operations fail #[error("Network error: {msg}")] - NetworkError { msg: String }, + NetworkError { + /// Description of the network error + msg: String, + }, + + /// Error returned when storage operations fail #[error("Storage error: {msg}")] - StorageError { msg: String }, + StorageError { + /// Description of the storage error + msg: String, + }, + + /// Error returned when trying to start a node that's already running #[error("Node is already running")] AlreadyRunning, + + /// Error returned when a mutex lock operation fails #[error("Lock error")] LockError, + + /// Error returned when a hash string is invalid or malformed #[error("Invalid hash format: {msg}")] - InvalidHash { msg: String }, + InvalidHash { + /// Description of why the hash is invalid + msg: String, + }, + + /// Error returned when a header is invalid or malformed #[error("Invalid header format: {msg}")] - InvalidHeader { msg: String }, + InvalidHeader { + /// Description of why the header is invalid + msg: String, + }, + + /// Error returned when storage initialization fails #[error("Storage initialization failed: {msg}")] - StorageInit { msg: String }, + StorageInit { + /// Description of why storage initialization failed + msg: String, + }, } impl From for LuminaError { @@ -108,7 +145,8 @@ impl LuminaNode { return Err(LuminaError::AlreadyRunning); } - let network_id = network_id(self.network.into()); + let network = network::Network::from(&self.network); + let network_id = network.id(); let base_path = get_base_path()?; @@ -131,26 +169,22 @@ impl LuminaNode { let blockstore = RedbBlockstore::new(db); - let p2p_bootnodes = canonical_network_bootnodes(self.network.into()).collect::>(); - + let p2p_bootnodes = network.canonical_bootnodes().collect::>(); let p2p_local_keypair = Keypair::generate_ed25519(); - let config = NodeConfig { - network_id: network_id.to_string(), - p2p_bootnodes, - p2p_local_keypair, - p2p_listen_on: vec![], - sync_batch_size: 128, - custom_syncing_window: Some(Duration::from_secs(60 * 60 * 24)), - store, - blockstore, - }; - - let new_node = Node::new(config) + let builder = Node::builder() + .store(store) + .blockstore(blockstore) + .network(network) + .bootnodes(p2p_bootnodes) + .keypair(p2p_local_keypair) + .sync_batch_size(128); + + let (new_node, subscriber) = builder + .start_subscribed() .await .map_err(|e| LuminaError::NetworkError { msg: e.to_string() })?; - let subscriber = new_node.event_subscriber(); let mut events_guard = self.events_subscriber.lock().await; *events_guard = Some(subscriber); diff --git a/node-native/src/types.rs b/node-native/src/types.rs index d84bd77e..d795619f 100644 --- a/node-native/src/types.rs +++ b/node-native/src/types.rs @@ -11,7 +11,7 @@ use std::time::SystemTime; use uniffi::{Enum, Record}; /// Supported Celestia networks. -#[derive(Debug, Default, Clone, Copy, Enum)] +#[derive(Debug, Default, Clone, Enum)] pub enum Network { /// Celestia mainnet. #[default] @@ -20,18 +20,20 @@ pub enum Network { Arabica, /// Mocha testnet. Mocha, - /// Private local network. - Private, + /// Custom network. + Custom { id: String }, } // From implementation for converting between Lumina and Uniffi types -impl From for network::Network { - fn from(network: Network) -> Self { +impl From<&Network> for network::Network { + fn from(network: &Network) -> Self { match network { Network::Mainnet => network::Network::Mainnet, Network::Arabica => network::Network::Arabica, Network::Mocha => network::Network::Mocha, - Network::Private => network::Network::Private, + Network::Custom { id } => { + network::Network::Custom(network::NetworkId::new(id).expect("invalid network id")) + } } } }