Skip to content

Commit

Permalink
refac: update docs and use nodebuilder and new types
Browse files Browse the repository at this point in the history
  • Loading branch information
sebasti810 committed Dec 12, 2024
1 parent cbbaed4 commit d0022b5
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 45 deletions.
11 changes: 0 additions & 11 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 3 additions & 4 deletions node-native/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
serde_json = "1.0.64"
uniffi = { version = "0.28.3", features = ["bindgen", "tokio", "cli"] }
tokio = { version = "1.38.0", features = ["macros", "sync"] }
5 changes: 5 additions & 0 deletions node-native/src/bin/uniffi-bindgen.rs
Original file line number Diff line number Diff line change
@@ -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()
}
82 changes: 58 additions & 24 deletions node-native/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,27 @@
//! 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;
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<T> = std::result::Result<T, LuminaError>;

/// Returns the platform-specific base path for storing Lumina data.
Expand Down Expand Up @@ -52,24 +58,55 @@ fn get_base_path() -> Result<PathBuf> {
}
}

/// 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<NodeError> for LuminaError {
Expand Down Expand Up @@ -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()?;

Expand All @@ -131,26 +169,22 @@ impl LuminaNode {

let blockstore = RedbBlockstore::new(db);

let p2p_bootnodes = canonical_network_bootnodes(self.network.into()).collect::<Vec<_>>();

let p2p_bootnodes = network.canonical_bootnodes().collect::<Vec<_>>();
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);

Expand Down
14 changes: 8 additions & 6 deletions node-native/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand All @@ -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<Network> 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"))
}
}
}
}
Expand Down

0 comments on commit d0022b5

Please sign in to comment.