From c8587ed17bead962a518d348a543e7d3839b0d5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Aleksandar=20Terenti=C4=87?= Date: Tue, 26 Nov 2024 09:24:34 +0100 Subject: [PATCH] Implement avail-light-web --- .github/workflows/default.yml | 8 +- web/Cargo.toml | 30 +++++++ web/README.md | 16 ++++ web/src/lib.rs | 157 ++++++++++++++++++++++++++++++++++ web/www/avail-light.js | 10 +++ web/www/index.html | 14 +++ 6 files changed, 233 insertions(+), 2 deletions(-) create mode 100644 web/Cargo.toml create mode 100644 web/README.md create mode 100644 web/src/lib.rs create mode 100644 web/www/avail-light.js create mode 100644 web/www/index.html diff --git a/.github/workflows/default.yml b/.github/workflows/default.yml index 7dd8e1e39..e110380c4 100644 --- a/.github/workflows/default.yml +++ b/.github/workflows/default.yml @@ -33,7 +33,9 @@ jobs: - uses: actions-rust-lang/setup-rust-toolchain@v1 with: components: clippy - - run: cargo clippy --workspace -- -D warnings + # TODO: Enable avail-light-web once issue with rocksdb feature being applied + # accross the workspace is resolved + - run: cargo clippy --workspace --exclude avail-light-web -- -D warnings test: name: cargo test @@ -42,7 +44,9 @@ jobs: - uses: actions/checkout@v4 - uses: arduino/setup-protoc@v2 - uses: actions-rust-lang/setup-rust-toolchain@v1 - - run: cargo test --workspace --benches --tests + # TODO: Enable avail-light-web once issue with rocksdb feature being applied + # accross the workspace is resolved + - run: cargo test --workspace --benches --tests --exclude avail-light-web env: RUSTFLAGS: "-C instrument-coverage" LLVM_PROFILE_FILE: "profile-%p-%m.profraw" diff --git a/web/Cargo.toml b/web/Cargo.toml new file mode 100644 index 000000000..32a9f7909 --- /dev/null +++ b/web/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "avail-light-web" +version = "0.1.0" +authors.workspace = true +edition = "2021" +repository.workspace = true + +[lib] +crate-type = ["cdylib", "rlib"] + +[features] +default = ["console_error_panic_hook"] + +[dependencies] +avail-light-core = { workspace = true } +avail-rust = { workspace = true } +clap = { workspace = true } +console_error_panic_hook = { version = "0.1.7", optional = true } +futures = { workspace = true } +libp2p = { workspace = true } +sp-io = { version = "30", features = ["disable_allocator", "disable_panic_handler"], default-features = false } +tokio = { version = "^1", default-features = false, features = ["sync", "macros", "io-util", "rt"] } +tokio_with_wasm = { version = "0.7.1", features = ["sync", "macros", "rt"] } +tracing = { workspace = true } +tracing-subscriber = { workspace = true } +tracing-wasm = "0.2.1" +wasm-bindgen = "0.2.93" +wasm-bindgen-futures = "0.4.43" +web-sys = { version = "0.3.70", features = ["console", "Window", "UrlSearchParams"] } +web-time = "1.1.0" diff --git a/web/README.md b/web/README.md new file mode 100644 index 000000000..c442bb09b --- /dev/null +++ b/web/README.md @@ -0,0 +1,16 @@ +# Avail Light Client (Web) + +## Compile + +`wasm-pack build --target web --dev` + +## Run + +`cp www/index.html pkg/` +`cd pkg` +`python3 -m http.server --directory .` + +# Start LC + +- Safari: http://localhost:8000/?network=hex&bootstrap=%2Fip4%2F209.38.38.158%2Fudp%2F39001%2Fwebrtc-direct%2Fcerthash%2FuEiCVz-CTCrMq4I2xwW_WznQPML3dos4GNWiXE_fJjvHiIg +- Firefox: 0.0.0.0:8000/?network=hex&bootstrap=%2Fip4%2F209.38.38.158%2Fudp%2F39001%2Fwebrtc-direct%2Fcerthash%2FuEiCVz-CTCrMq4I2xwW_WznQPML3dos4GNWiXE_fJjvHiIg diff --git a/web/src/lib.rs b/web/src/lib.rs new file mode 100644 index 000000000..ed5b7a21a --- /dev/null +++ b/web/src/lib.rs @@ -0,0 +1,157 @@ +#![cfg(target_arch = "wasm32")] + +use std::sync::Arc; + +use avail_light_core::data; +use avail_light_core::light_client::OutputEvent as LcEvent; +use avail_light_core::network::{self, p2p, rpc, Network}; +use avail_light_core::shutdown::Controller; +use avail_light_core::types::{Delay, MultiaddrConfig}; +use avail_light_core::utils::spawn_in_span; +use avail_rust::kate_recovery::couscous; +use clap::ValueEnum; +use libp2p::Multiaddr; +use std::str::FromStr; +use tokio::sync::{broadcast, mpsc}; +use tokio_with_wasm::alias as tokio; +use tracing::{error, info, warn}; +use wasm_bindgen::prelude::*; +use web_time::Duration; + +#[tokio::main(flavor = "current_thread")] +#[wasm_bindgen(start)] +async fn main_js() {} + +#[wasm_bindgen] +pub async fn run(network_param: Option, bootstrap_param: Option) { + console_error_panic_hook::set_once(); + tracing_wasm::set_as_global_default(); + + let mut network = network::Network::Local; + if let Some(value) = network_param { + network = Network::from_str(&value, true).unwrap(); + }; + + let mut bootstrap_multiaddr = network.bootstrap_multiaddr(); + if let Some(value) = bootstrap_param { + bootstrap_multiaddr = Multiaddr::from_str(&value).unwrap(); + }; + + let version = clap::crate_version!(); + let shutdown = Controller::new(); + let db = data::DB::default(); + + // TODO: Store and read client_id from local storage + // let client_id = Uuid::new_v4(); + // let execution_id = Uuid::new_v4(); + + let pp = Arc::new(couscous::public_params()); + + let cfg_rpc = rpc::configuration::RPCConfig { + full_node_ws: network.full_node_ws(), + ..Default::default() + }; + + let cfg_libp2p = p2p::configuration::LibP2PConfig { + bootstraps: vec![MultiaddrConfig::PeerIdAndMultiaddr(( + network.bootstrap_peer_id(), + bootstrap_multiaddr, + ))], + ..Default::default() + }; + + let genesis_hash = &network.genesis_hash().to_string(); + let (rpc_event_sender, rpc_event_receiver) = broadcast::channel(1000); + + let (rpc_client, rpc_subscriptions) = rpc::init( + db.clone(), + genesis_hash, + &cfg_rpc, + shutdown.clone(), + rpc_event_sender.clone(), + ) + .await + .unwrap(); + + let (id_keys, _peer_id) = p2p::identity(&cfg_libp2p, db.clone()).unwrap(); + + let (p2p_client, p2p_event_loop, _p2p_event_receiver) = p2p::init( + cfg_libp2p.clone(), + Default::default(), + id_keys, + version, + "DEV", + false, + shutdown.clone(), + ) + .await + .unwrap(); + + let network_client = network::new(p2p_client.clone(), rpc_client, pp, false); + + // spawn the RPC Network task for Event Loop to run in the background + // and shut it down, without delays + let _rpc_subscriptions_handle = spawn_in_span(shutdown.with_cancel(shutdown.with_trigger( + "Subscription loop failure triggered shutdown".to_string(), + async { + let result = rpc_subscriptions.run().await; + if let Err(ref err) = result { + error!(%err, "Subscription loop ended with error"); + }; + result + }, + ))); + + let (lc_sender, mut lc_receiver) = mpsc::unbounded_channel::(); + let (block_tx, _block_rx) = + broadcast::channel::(1 << 7); + + let channels = avail_light_core::types::ClientChannels { + block_sender: block_tx, + rpc_event_receiver, + }; + + spawn_in_span(async move { + loop { + let Some(message) = lc_receiver.recv().await else { + info!("Exiting..."); + break; + }; + info!("{message:?}"); + } + }); + + let light_client_handle = tokio::task::spawn(avail_light_core::light_client::run( + db.clone(), + network_client, + 99.9, + Delay(Some(Duration::from_secs(20))), + channels, + shutdown.clone(), + lc_sender, + )); + + tokio::task::spawn(p2p_event_loop.run()); + + let bootstraps = cfg_libp2p.bootstraps.clone(); + let bootstrap_p2p_client = p2p_client.clone(); + spawn_in_span(shutdown.with_cancel(async move { + info!("Bootstraping the DHT with bootstrap nodes..."); + let bs_result = bootstrap_p2p_client + .clone() + .bootstrap_on_startup(&bootstraps) + .await; + match bs_result { + Ok(_) => { + info!("Bootstrap done."); + }, + Err(e) => { + warn!("Bootstrap process: {e:?}."); + }, + } + })); + + if let Err(error) = light_client_handle.await { + error!("Error running light client: {error}") + }; +} diff --git a/web/www/avail-light.js b/web/www/avail-light.js new file mode 100644 index 000000000..3ad2cd06d --- /dev/null +++ b/web/www/avail-light.js @@ -0,0 +1,10 @@ +import init, { run } from './avail_light_web.js'; + +(async () => { + try { + await init(); + await run("hex", null); + } catch (error) { + console.error("Error:", error); + } +})(); diff --git a/web/www/index.html b/web/www/index.html new file mode 100644 index 000000000..64e12e043 --- /dev/null +++ b/web/www/index.html @@ -0,0 +1,14 @@ + + + + + + Avail Light Client Web + + +

Avail Light Client Web

+ + +