Skip to content

Commit

Permalink
Implement avail-light-web
Browse files Browse the repository at this point in the history
  • Loading branch information
aterentic-ethernal committed Nov 8, 2024
1 parent 4769a67 commit bb7cab8
Show file tree
Hide file tree
Showing 11 changed files with 288 additions and 7 deletions.
8 changes: 6 additions & 2 deletions .github/workflows/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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"
Expand Down
43 changes: 43 additions & 0 deletions Cargo.lock

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

3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ members = [
"crawler",
"fat",
"relay",
"web",
]
default-members = ["client"]
resolver = "2"
Expand All @@ -25,7 +26,7 @@ anyhow = "1.0.71"
async-std = { version = "1.12.0", features = ["attributes"] }
async-trait = "0.1.73"
clap = { version = "4.4.4", features = ["derive", "cargo"] }
color-eyre = "0.6.2"
color-eyre = { version = "0.6.2", default-features = false }
confy = "0.5.1"
hex = "0.4.3"
rand = "0.8.4"
Expand Down
3 changes: 2 additions & 1 deletion core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ better-panic = "0.3.0"
blake2b_simd = "1.0.2"
clap = { workspace = true }
codec = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "full", "bit-vec"] }
color-eyre = { workspace = true }
confy = { workspace = true }
derive_more = { version = "1", features = ["from"] }
dusk-bytes = { version = "0.1.6", default-features = false }
Expand Down Expand Up @@ -49,6 +48,7 @@ uuid = { workspace = true }
async-std = { workspace = true }
chrono = "0.4.19"
libp2p = { workspace = true }
color-eyre = { workspace = true, default-features = true }
hyper = { version = "0.14.23", features = ["full", "http1"] }
jsonrpsee-core = { version = "0.21.0", features = ["client"] }
libc = "0.2.150"
Expand Down Expand Up @@ -76,6 +76,7 @@ thiserror-no-std = "2.0.2"
rand = { version = "0.8.4", default-features = false }
libp2p = { workspace = true, features = ["wasm-bindgen"] }
libp2p-webrtc-websys = { workspace = true }
color-eyre = { workspace = true }
wasm-bindgen = "0.2.90"
wasm-timer = "0.2.5"
web-time = "1.1.0"
Expand Down
1 change: 1 addition & 0 deletions core/src/light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ use crate::{
utils::{blake2_256, calculate_confidence, extract_kate},
};

#[derive(Debug)]
pub enum OutputEvent {
RecordBlockProcessingDelay(f64),
CountSessionBlocks,
Expand Down
5 changes: 2 additions & 3 deletions core/src/network/p2p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,9 @@ async fn build_swarm(
};
#[cfg(target_arch = "wasm32")]
{
use libp2p_webrtc_websys as webrtc;
swarm = tokio_swarm
.with_other_transport(|key| {
libp2p_webrtc_websys::Transport::new(libp2p_webrtc_websys::Config::new(&key))
})?
.with_other_transport(|key| webrtc::Transport::new(webrtc::Config::new(&key)))?
.with_relay_client(noise::Config::new, yamux::Config::default)?
.with_behaviour(behaviour)?
.with_swarm_config(|c| generate_config(c, cfg))
Expand Down
7 changes: 7 additions & 0 deletions core/src/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,19 @@ pub fn filter_auth_set_changes(header: &AvailHeader) -> Vec<Vec<(AuthorityId, u6
}

pub fn install_panic_hooks(shutdown: Controller<String>) -> Result<()> {
#[cfg(not(target_arch = "wasm32"))]
// initialize color-eyre hooks
let (panic_hook, eyre_hook) = color_eyre::config::HookBuilder::default()
.display_location_section(true)
.display_env_section(true)
.into_hooks();

#[cfg(target_arch = "wasm32")]
// initialize color-eyre hooks
let (panic_hook, eyre_hook) = color_eyre::config::HookBuilder::default()
.display_env_section(true)
.into_hooks();

// install hook as global handler
eyre_hook.install()?;

Expand Down
30 changes: 30 additions & 0 deletions web/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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"
16 changes: 16 additions & 0 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -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
161 changes: 161 additions & 0 deletions web/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
#![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_sys::{window, UrlSearchParams};
use web_time::Duration;

#[tokio::main(flavor = "current_thread")]
#[wasm_bindgen(start)]
async fn main_js() {}

#[wasm_bindgen]
pub async fn run() {
console_error_panic_hook::set_once();
tracing_wasm::set_as_global_default();

let search = window().unwrap().location().search().unwrap();
let params = UrlSearchParams::new_with_str(&search).unwrap();

let mut network = network::Network::Local;
if let Some(value) = params.get("network") {
network = Network::from_str(&value, true).unwrap();
};

let mut bootstrap_multiaddr = network.bootstrap_multiaddr();
if let Some(value) = params.get("bootstrap") {
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 project_name = "avail".to_string();
let (p2p_client, p2p_event_loop, _p2p_event_receiver) = p2p::init(
cfg_libp2p.clone(),
project_name,
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::<LcEvent>();
let (block_tx, _block_rx) =
broadcast::channel::<avail_light_core::types::BlockVerified>(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}")
};
}
18 changes: 18 additions & 0 deletions web/www/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Avail Light Client Web</title>
</head>
<body>
<h1>Avail Light Client Web</h1>
<script type="module">
import init, { run } from './avail_light_web.js';
(async () => {
await init();
await run();
})();
</script>
</body>
</html>

0 comments on commit bb7cab8

Please sign in to comment.