Skip to content

Commit

Permalink
Merge branch 'main' into feat/blob_service
Browse files Browse the repository at this point in the history
  • Loading branch information
zvolin committed Jan 7, 2025
2 parents 3787a92 + 17a08d3 commit 41492f9
Show file tree
Hide file tree
Showing 15 changed files with 354 additions and 173 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ prost-types = "0.13.3"
#libp2p = { path = "../../rust-libp2p/libp2p" }
#libp2p-core = { path = "../../rust-libp2p/core" }
#libp2p-swarm = { path = "../../rust-libp2p/swarm" }
#wasm-bindgen = { path = "../wasm-bindgen" }

# Uncomment this if you need debug symbols in release.
# Also check node-wasm's `Cargo.toml`.
Expand Down
4 changes: 2 additions & 2 deletions cli/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ async function showStats(node) {
return;
}

const squareRows = networkHead.dah.row_roots.length;
const squareCols = networkHead.dah.column_roots.length;
const squareRows = networkHead.dah.row_roots().length;
const squareCols = networkHead.dah.column_roots().length;

document.getElementById("block-height").innerText = networkHead.header.height;
document.getElementById("block-hash").innerText = networkHead.commit.block_id.hash;
Expand Down
4 changes: 2 additions & 2 deletions node-wasm/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ crate-type = ["cdylib", "rlib"]
blockstore.workspace = true
celestia-types = { workspace = true, features = ["wasm-bindgen"] }
libp2p = { workspace = true, features = ["serde"] }
lumina-node.workspace = true
lumina-node = { workspace = true, features = ["wasm-bindgen"] }
tendermint.workspace = true

anyhow = "1.0.86"
Expand All @@ -46,7 +46,7 @@ tokio = { version = "1.38.0", features = ["sync"] }
tracing = "0.1.40"
tracing-subscriber = { version = "0.3.18", features = ["time"] }
tracing-web = "0.1.3"
wasm-bindgen = "0.2.93"
wasm-bindgen = "0.2.99"
wasm-bindgen-futures = "0.4.43"
web-sys = { version = "0.3.70", features = [
"BroadcastChannel",
Expand Down
92 changes: 28 additions & 64 deletions node-wasm/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,17 @@ use std::time::Duration;

use blockstore::EitherBlockstore;
use celestia_types::nmt::Namespace;
use celestia_types::Blob;
use celestia_types::{Blob, ExtendedHeader};
use js_sys::Array;
use lumina_node::blockstore::{InMemoryBlockstore, IndexedDbBlockstore};
use lumina_node::network;
use lumina_node::node::{NodeBuilder, MIN_PRUNING_DELAY, MIN_SAMPLING_WINDOW};
use lumina_node::store::{EitherStore, InMemoryStore, IndexedDbStore, SamplingMetadata};
use serde::{Deserialize, Serialize};
use serde_wasm_bindgen::to_value;
use tracing::{debug, error};
use wasm_bindgen::prelude::*;
use web_sys::BroadcastChannel;

use lumina_node::blockstore::{InMemoryBlockstore, IndexedDbBlockstore};
use lumina_node::network;
use lumina_node::node::{NodeBuilder, MIN_PRUNING_DELAY, MIN_SAMPLING_WINDOW};
use lumina_node::store::{EitherStore, InMemoryStore, IndexedDbStore};

use crate::commands::{CheckableResponseExt, NodeCommand, SingleHeaderQuery};
use crate::error::{Context, Result};
use crate::ports::WorkerClient;
Expand Down Expand Up @@ -220,64 +218,44 @@ impl NodeClient {
}

/// Request the head header from the network.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestHeadHeader)]
pub async fn request_head_header(&self) -> Result<JsValue> {
pub async fn request_head_header(&self) -> Result<ExtendedHeader> {
let command = NodeCommand::RequestHeader(SingleHeaderQuery::Head);
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;

header.into()
response.into_header().check_variant()?
}

/// Request a header for the block with a given hash from the network.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestHeaderByHash)]
pub async fn request_header_by_hash(&self, hash: &str) -> Result<JsValue> {
pub async fn request_header_by_hash(&self, hash: &str) -> Result<ExtendedHeader> {
let command = NodeCommand::RequestHeader(SingleHeaderQuery::ByHash(hash.parse()?));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;

header.into()
response.into_header().check_variant()?
}

/// Request a header for the block with a given height from the network.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestHeaderByHeight)]
pub async fn request_header_by_height(&self, height: u64) -> Result<JsValue> {
pub async fn request_header_by_height(&self, height: u64) -> Result<ExtendedHeader> {
let command = NodeCommand::RequestHeader(SingleHeaderQuery::ByHeight(height));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;

header.into()
response.into_header().check_variant()?
}

/// Request headers in range (from, from + amount] from the network.
///
/// The headers will be verified with the `from` header.
///
/// Returns an array of javascript objects with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = requestVerifiedHeaders)]
pub async fn request_verified_headers(
&self,
from_header: JsValue,
from: &ExtendedHeader,
amount: u64,
) -> Result<Array> {
) -> Result<Vec<ExtendedHeader>> {
let command = NodeCommand::GetVerifiedHeaders {
from: from_header,
from: from.to_owned(),
amount,
};
let response = self.worker.exec(command).await?;
let headers = response.into_headers().check_variant()?;

headers.into()
response.into_headers().check_variant()?
}

/// Request all blobs with provided namespace in the block corresponding to this header
Expand Down Expand Up @@ -313,51 +291,43 @@ impl NodeClient {
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getNetworkHeadHeader)]
pub async fn get_network_head_header(&self) -> Result<JsValue> {
pub async fn get_network_head_header(&self) -> Result<Option<ExtendedHeader>> {
let command = NodeCommand::LastSeenNetworkHead;
let response = self.worker.exec(command).await?;
let header = response.into_last_seen_network_head().check_variant()?;

header.into()
response.into_last_seen_network_head().check_variant()?
}

/// Get the latest locally synced header.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getLocalHeadHeader)]
pub async fn get_local_head_header(&self) -> Result<JsValue> {
pub async fn get_local_head_header(&self) -> Result<ExtendedHeader> {
let command = NodeCommand::GetHeader(SingleHeaderQuery::Head);
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;

header.into()
response.into_header().check_variant()?
}

/// Get a synced header for the block with a given hash.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getHeaderByHash)]
pub async fn get_header_by_hash(&self, hash: &str) -> Result<JsValue> {
pub async fn get_header_by_hash(&self, hash: &str) -> Result<ExtendedHeader> {
let command = NodeCommand::GetHeader(SingleHeaderQuery::ByHash(hash.parse()?));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;

header.into()
response.into_header().check_variant()?
}

/// Get a synced header for the block with a given height.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/celestia-types/latest/celestia_types/struct.ExtendedHeader.html
#[wasm_bindgen(js_name = getHeaderByHeight)]
pub async fn get_header_by_height(&self, height: u64) -> Result<JsValue> {
pub async fn get_header_by_height(&self, height: u64) -> Result<ExtendedHeader> {
let command = NodeCommand::GetHeader(SingleHeaderQuery::ByHeight(height));
let response = self.worker.exec(command).await?;
let header = response.into_header().check_variant()?;

header.into()
response.into_header().check_variant()?
}

/// Get synced headers from the given heights range.
Expand All @@ -377,28 +347,24 @@ impl NodeClient {
&self,
start_height: Option<u64>,
end_height: Option<u64>,
) -> Result<Array> {
) -> Result<Vec<ExtendedHeader>> {
let command = NodeCommand::GetHeadersRange {
start_height,
end_height,
};
let response = self.worker.exec(command).await?;
let headers = response.into_headers().check_variant()?;

headers.into()
response.into_headers().check_variant()?
}

/// Get data sampling metadata of an already sampled height.
///
/// Returns a javascript object with given structure:
/// https://docs.rs/lumina-node/latest/lumina_node/store/struct.SamplingMetadata.html
#[wasm_bindgen(js_name = getSamplingMetadata)]
pub async fn get_sampling_metadata(&self, height: u64) -> Result<JsValue> {
pub async fn get_sampling_metadata(&self, height: u64) -> Result<Option<SamplingMetadata>> {
let command = NodeCommand::GetSamplingMetadata { height };
let response = self.worker.exec(command).await?;
let metadata = response.into_sampling_metadata().check_variant()?;

Ok(to_value(&metadata?)?)
response.into_sampling_metadata().check_variant()?
}

/// Returns a [`BroadcastChannel`] for events generated by [`Node`].
Expand Down Expand Up @@ -494,7 +460,6 @@ mod tests {
use gloo_timers::future::sleep;
use libp2p::{multiaddr::Protocol, Multiaddr};
use rexie::Rexie;
use serde_wasm_bindgen::from_value;
use wasm_bindgen_futures::spawn_local;
use wasm_bindgen_test::wasm_bindgen_test;
use web_sys::MessageChannel;
Expand All @@ -516,8 +481,7 @@ mod tests {
assert_eq!(info.num_peers, 1);

let bridge_head_header = rpc_client.header_network_head().await.unwrap();
let head_header: ExtendedHeader =
from_value(client.request_head_header().await.unwrap()).unwrap();
let head_header: ExtendedHeader = client.request_head_header().await.unwrap();
assert_eq!(head_header, bridge_head_header);
rpc_client
.p2p_close_peer(&PeerId(
Expand Down
16 changes: 7 additions & 9 deletions node-wasm/src/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,22 @@ use std::fmt::Debug;
use celestia_types::nmt::Namespace;
use celestia_types::Blob;
use enum_as_inner::EnumAsInner;
use js_sys::Array;
use libp2p::Multiaddr;
use libp2p::PeerId;
use serde::{Deserialize, Serialize};
use tracing::error;
use wasm_bindgen::{JsError, JsValue};
use wasm_bindgen::JsError;

use celestia_types::hash::Hash;
use celestia_types::{hash::Hash, ExtendedHeader};
use lumina_node::node::{PeerTrackerInfo, SyncingInfo};
use lumina_node::store::SamplingMetadata;

use crate::client::WasmNodeConfig;
use crate::error::Error;
use crate::error::Result;
use crate::utils::JsResult;
use crate::wrapper::libp2p::NetworkInfoSnapshot;

#[allow(clippy::large_enum_variant)]
#[derive(Debug, Serialize, Deserialize)]
pub(crate) enum NodeCommand {
InternalPing,
Expand All @@ -42,8 +41,7 @@ pub(crate) enum NodeCommand {
GetListeners,
RequestHeader(SingleHeaderQuery),
GetVerifiedHeaders {
#[serde(with = "serde_wasm_bindgen::preserve")]
from: JsValue,
from: ExtendedHeader,
amount: u64,
},
GetHeadersRange {
Expand Down Expand Up @@ -86,9 +84,9 @@ pub(crate) enum WorkerResponse {
SetPeerTrust(Result<()>),
Connected(Result<()>),
Listeners(Result<Vec<Multiaddr>>),
Header(JsResult<JsValue, Error>),
Headers(JsResult<Array, Error>),
LastSeenNetworkHead(JsResult<JsValue, Error>),
Header(Result<ExtendedHeader, Error>),
Headers(Result<Vec<ExtendedHeader>, Error>),
LastSeenNetworkHead(Result<Option<ExtendedHeader>, Error>),
SamplingMetadata(Result<Option<SamplingMetadata>>),
Blobs(Result<Vec<Blob>>),
}
Expand Down
1 change: 1 addition & 0 deletions node-wasm/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -136,6 +136,7 @@ from_display! {
tendermint::error::Error,
libp2p::identity::ParseError,
libp2p::multiaddr::Error,
celestia_types::Error,
lumina_node::node::NodeError,
lumina_node::store::StoreError,
crate::worker::WorkerError,
Expand Down
1 change: 1 addition & 0 deletions node-wasm/src/ports.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ impl From<MessagePort> for MessagePortLike {
#[derive(Debug, Clone, Copy)]
pub struct ClientId(usize);

#[allow(clippy::large_enum_variant)]
pub(crate) enum ClientMessage {
Command { id: ClientId, command: NodeCommand },
AddConnection(JsValue),
Expand Down
49 changes: 3 additions & 46 deletions node-wasm/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,7 @@ use gloo_timers::future::TimeoutFuture;
use js_sys::{Math, Promise};
use libp2p::multiaddr::Protocol;
use libp2p::{Multiaddr, PeerId};
use lumina_node::network;
use serde::de::DeserializeOwned;
use serde::{Deserialize, Serialize};
use serde::Deserialize;
use serde_repr::{Deserialize_repr, Serialize_repr};
use tracing::{info, warn};
use tracing_subscriber::filter::LevelFilter;
Expand All @@ -24,6 +22,8 @@ use web_sys::{
ServiceWorker, ServiceWorkerGlobalScope, SharedWorker, SharedWorkerGlobalScope, Worker,
};

use lumina_node::network;

use crate::error::{Context, Error, Result};

/// Supported Celestia networks.
Expand Down Expand Up @@ -110,49 +110,6 @@ impl WorkerSelf for ServiceWorker {
type GlobalScope = ServiceWorkerGlobalScope;
}

/// This type is useful in cases where we want to deal with de/serialising `Result<T, E>`, with
/// [`serde_wasm_bindgen::preserve`] where `T` is a JavaScript object (which are not serializable by
/// Rust standards, but can be passed through unchanged via cast as they implement [`JsCast`]).
///
/// [`serde_wasm_bindgen::preserve`]: https://docs.rs/serde-wasm-bindgen/latest/serde_wasm_bindgen/preserve
/// [`JsCast`]: https://docs.rs/wasm-bindgen/latest/wasm_bindgen/trait.JsCast.html
#[derive(Serialize, Deserialize, Debug)]
pub(crate) enum JsResult<T, E>
where
T: JsCast + Debug,
E: Debug,
{
#[serde(with = "serde_wasm_bindgen::preserve")]
Ok(T),
Err(E),
}

impl<T, E> From<Result<T, E>> for JsResult<T, E>
where
T: JsCast + Debug,
E: Serialize + DeserializeOwned + Debug,
{
fn from(result: Result<T, E>) -> Self {
match result {
Ok(v) => JsResult::Ok(v),
Err(e) => JsResult::Err(e),
}
}
}

impl<T, E> From<JsResult<T, E>> for Result<T, E>
where
T: JsCast + Debug,
E: Serialize + DeserializeOwned + Debug,
{
fn from(result: JsResult<T, E>) -> Self {
match result {
JsResult::Ok(v) => Ok(v),
JsResult::Err(e) => Err(e),
}
}
}

pub(crate) trait MessageEventExt {
fn get_port(&self) -> Option<JsValue>;
}
Expand Down
Loading

0 comments on commit 41492f9

Please sign in to comment.