Skip to content

Commit bb7cab8

Browse files
Implement avail-light-web
1 parent 4769a67 commit bb7cab8

File tree

11 files changed

+288
-7
lines changed

11 files changed

+288
-7
lines changed

.github/workflows/default.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,9 @@ jobs:
3333
- uses: actions-rust-lang/setup-rust-toolchain@v1
3434
with:
3535
components: clippy
36-
- run: cargo clippy --workspace -- -D warnings
36+
# TODO: Enable avail-light-web once issue with rocksdb feature being applied
37+
# accross the workspace is resolved
38+
- run: cargo clippy --workspace --exclude avail-light-web -- -D warnings
3739

3840
test:
3941
name: cargo test
@@ -42,7 +44,9 @@ jobs:
4244
- uses: actions/checkout@v4
4345
- uses: arduino/setup-protoc@v2
4446
- uses: actions-rust-lang/setup-rust-toolchain@v1
45-
- run: cargo test --workspace --benches --tests
47+
# TODO: Enable avail-light-web once issue with rocksdb feature being applied
48+
# accross the workspace is resolved
49+
- run: cargo test --workspace --benches --tests --exclude avail-light-web
4650
env:
4751
RUSTFLAGS: "-C instrument-coverage"
4852
LLVM_PROFILE_FILE: "profile-%p-%m.profraw"

Cargo.lock

Lines changed: 43 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ members = [
77
"crawler",
88
"fat",
99
"relay",
10+
"web",
1011
]
1112
default-members = ["client"]
1213
resolver = "2"
@@ -25,7 +26,7 @@ anyhow = "1.0.71"
2526
async-std = { version = "1.12.0", features = ["attributes"] }
2627
async-trait = "0.1.73"
2728
clap = { version = "4.4.4", features = ["derive", "cargo"] }
28-
color-eyre = "0.6.2"
29+
color-eyre = { version = "0.6.2", default-features = false }
2930
confy = "0.5.1"
3031
hex = "0.4.3"
3132
rand = "0.8.4"

core/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,6 @@ better-panic = "0.3.0"
2020
blake2b_simd = "1.0.2"
2121
clap = { workspace = true }
2222
codec = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "full", "bit-vec"] }
23-
color-eyre = { workspace = true }
2423
confy = { workspace = true }
2524
derive_more = { version = "1", features = ["from"] }
2625
dusk-bytes = { version = "0.1.6", default-features = false }
@@ -49,6 +48,7 @@ uuid = { workspace = true }
4948
async-std = { workspace = true }
5049
chrono = "0.4.19"
5150
libp2p = { workspace = true }
51+
color-eyre = { workspace = true, default-features = true }
5252
hyper = { version = "0.14.23", features = ["full", "http1"] }
5353
jsonrpsee-core = { version = "0.21.0", features = ["client"] }
5454
libc = "0.2.150"
@@ -76,6 +76,7 @@ thiserror-no-std = "2.0.2"
7676
rand = { version = "0.8.4", default-features = false }
7777
libp2p = { workspace = true, features = ["wasm-bindgen"] }
7878
libp2p-webrtc-websys = { workspace = true }
79+
color-eyre = { workspace = true }
7980
wasm-bindgen = "0.2.90"
8081
wasm-timer = "0.2.5"
8182
web-time = "1.1.0"

core/src/light_client.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ use crate::{
4343
utils::{blake2_256, calculate_confidence, extract_kate},
4444
};
4545

46+
#[derive(Debug)]
4647
pub enum OutputEvent {
4748
RecordBlockProcessingDelay(f64),
4849
CountSessionBlocks,

core/src/network/p2p.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -315,10 +315,9 @@ async fn build_swarm(
315315
};
316316
#[cfg(target_arch = "wasm32")]
317317
{
318+
use libp2p_webrtc_websys as webrtc;
318319
swarm = tokio_swarm
319-
.with_other_transport(|key| {
320-
libp2p_webrtc_websys::Transport::new(libp2p_webrtc_websys::Config::new(&key))
321-
})?
320+
.with_other_transport(|key| webrtc::Transport::new(webrtc::Config::new(&key)))?
322321
.with_relay_client(noise::Config::new, yamux::Config::default)?
323322
.with_behaviour(behaviour)?
324323
.with_swarm_config(|c| generate_config(c, cfg))

core/src/utils.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,12 +115,19 @@ pub fn filter_auth_set_changes(header: &AvailHeader) -> Vec<Vec<(AuthorityId, u6
115115
}
116116

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

125+
#[cfg(target_arch = "wasm32")]
126+
// initialize color-eyre hooks
127+
let (panic_hook, eyre_hook) = color_eyre::config::HookBuilder::default()
128+
.display_env_section(true)
129+
.into_hooks();
130+
124131
// install hook as global handler
125132
eyre_hook.install()?;
126133

web/Cargo.toml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
[package]
2+
name = "avail-light-web"
3+
version = "0.1.0"
4+
authors.workspace = true
5+
edition = "2021"
6+
repository.workspace = true
7+
8+
[lib]
9+
crate-type = ["cdylib", "rlib"]
10+
11+
[features]
12+
default = ["console_error_panic_hook"]
13+
14+
[dependencies]
15+
avail-light-core = { workspace = true }
16+
avail-rust = { workspace = true }
17+
clap = { workspace = true }
18+
console_error_panic_hook = { version = "0.1.7", optional = true }
19+
futures = { workspace = true }
20+
libp2p = { workspace = true }
21+
sp-io = { version = "30", features = ["disable_allocator", "disable_panic_handler"], default-features = false }
22+
tokio = { version = "^1", default-features = false, features = ["sync", "macros", "io-util", "rt"] }
23+
tokio_with_wasm = { version = "0.7.1", features = ["sync", "macros", "rt"] }
24+
tracing = { workspace = true }
25+
tracing-subscriber = { workspace = true }
26+
tracing-wasm = "0.2.1"
27+
wasm-bindgen = "0.2.93"
28+
wasm-bindgen-futures = "0.4.43"
29+
web-sys = { version = "0.3.70", features = ["console", "Window", "UrlSearchParams"] }
30+
web-time = "1.1.0"

web/README.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# Avail Light Client (Web)
2+
3+
## Compile
4+
5+
`wasm-pack build --target web --dev`
6+
7+
## Run
8+
9+
`cp www/index.html pkg/`
10+
`cd pkg`
11+
`python3 -m http.server --directory .`
12+
13+
# Start LC
14+
15+
- Safari: http://localhost:8000/?network=hex&bootstrap=%2Fip4%2F209.38.38.158%2Fudp%2F39001%2Fwebrtc-direct%2Fcerthash%2FuEiCVz-CTCrMq4I2xwW_WznQPML3dos4GNWiXE_fJjvHiIg
16+
- Firefox: 0.0.0.0:8000/?network=hex&bootstrap=%2Fip4%2F209.38.38.158%2Fudp%2F39001%2Fwebrtc-direct%2Fcerthash%2FuEiCVz-CTCrMq4I2xwW_WznQPML3dos4GNWiXE_fJjvHiIg

web/src/lib.rs

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
#![cfg(target_arch = "wasm32")]
2+
3+
use std::sync::Arc;
4+
5+
use avail_light_core::data;
6+
use avail_light_core::light_client::OutputEvent as LcEvent;
7+
use avail_light_core::network::{self, p2p, rpc, Network};
8+
use avail_light_core::shutdown::Controller;
9+
use avail_light_core::types::{Delay, MultiaddrConfig};
10+
use avail_light_core::utils::spawn_in_span;
11+
use avail_rust::kate_recovery::couscous;
12+
use clap::ValueEnum;
13+
use libp2p::Multiaddr;
14+
use std::str::FromStr;
15+
use tokio::sync::{broadcast, mpsc};
16+
use tokio_with_wasm::alias as tokio;
17+
use tracing::{error, info, warn};
18+
use wasm_bindgen::prelude::*;
19+
use web_sys::{window, UrlSearchParams};
20+
use web_time::Duration;
21+
22+
#[tokio::main(flavor = "current_thread")]
23+
#[wasm_bindgen(start)]
24+
async fn main_js() {}
25+
26+
#[wasm_bindgen]
27+
pub async fn run() {
28+
console_error_panic_hook::set_once();
29+
tracing_wasm::set_as_global_default();
30+
31+
let search = window().unwrap().location().search().unwrap();
32+
let params = UrlSearchParams::new_with_str(&search).unwrap();
33+
34+
let mut network = network::Network::Local;
35+
if let Some(value) = params.get("network") {
36+
network = Network::from_str(&value, true).unwrap();
37+
};
38+
39+
let mut bootstrap_multiaddr = network.bootstrap_multiaddr();
40+
if let Some(value) = params.get("bootstrap") {
41+
bootstrap_multiaddr = Multiaddr::from_str(&value).unwrap();
42+
};
43+
44+
let version = clap::crate_version!();
45+
let shutdown = Controller::new();
46+
let db = data::DB::default();
47+
// TODO: Store and read client_id from local storage
48+
// let client_id = Uuid::new_v4();
49+
// let execution_id = Uuid::new_v4();
50+
51+
let pp = Arc::new(couscous::public_params());
52+
53+
let cfg_rpc = rpc::configuration::RPCConfig {
54+
full_node_ws: network.full_node_ws(),
55+
..Default::default()
56+
};
57+
58+
let cfg_libp2p = p2p::configuration::LibP2PConfig {
59+
bootstraps: vec![MultiaddrConfig::PeerIdAndMultiaddr((
60+
network.bootstrap_peer_id(),
61+
bootstrap_multiaddr,
62+
))],
63+
..Default::default()
64+
};
65+
66+
let genesis_hash = &network.genesis_hash().to_string();
67+
let (rpc_event_sender, rpc_event_receiver) = broadcast::channel(1000);
68+
69+
let (rpc_client, rpc_subscriptions) = rpc::init(
70+
db.clone(),
71+
genesis_hash,
72+
&cfg_rpc,
73+
shutdown.clone(),
74+
rpc_event_sender.clone(),
75+
)
76+
.await
77+
.unwrap();
78+
79+
let (id_keys, _peer_id) = p2p::identity(&cfg_libp2p, db.clone()).unwrap();
80+
81+
let project_name = "avail".to_string();
82+
let (p2p_client, p2p_event_loop, _p2p_event_receiver) = p2p::init(
83+
cfg_libp2p.clone(),
84+
project_name,
85+
id_keys,
86+
version,
87+
"DEV",
88+
false,
89+
shutdown.clone(),
90+
)
91+
.await
92+
.unwrap();
93+
94+
let network_client = network::new(p2p_client.clone(), rpc_client, pp, false);
95+
96+
// spawn the RPC Network task for Event Loop to run in the background
97+
// and shut it down, without delays
98+
let _rpc_subscriptions_handle = spawn_in_span(shutdown.with_cancel(shutdown.with_trigger(
99+
"Subscription loop failure triggered shutdown".to_string(),
100+
async {
101+
let result = rpc_subscriptions.run().await;
102+
if let Err(ref err) = result {
103+
error!(%err, "Subscription loop ended with error");
104+
};
105+
result
106+
},
107+
)));
108+
109+
let (lc_sender, mut lc_receiver) = mpsc::unbounded_channel::<LcEvent>();
110+
let (block_tx, _block_rx) =
111+
broadcast::channel::<avail_light_core::types::BlockVerified>(1 << 7);
112+
113+
let channels = avail_light_core::types::ClientChannels {
114+
block_sender: block_tx,
115+
rpc_event_receiver,
116+
};
117+
118+
spawn_in_span(async move {
119+
loop {
120+
let Some(message) = lc_receiver.recv().await else {
121+
info!("Exiting...");
122+
break;
123+
};
124+
info!("{message:?}");
125+
}
126+
});
127+
128+
let light_client_handle = tokio::task::spawn(avail_light_core::light_client::run(
129+
db.clone(),
130+
network_client,
131+
99.9,
132+
Delay(Some(Duration::from_secs(20))),
133+
channels,
134+
shutdown.clone(),
135+
lc_sender,
136+
));
137+
138+
tokio::task::spawn(p2p_event_loop.run());
139+
140+
let bootstraps = cfg_libp2p.bootstraps.clone();
141+
let bootstrap_p2p_client = p2p_client.clone();
142+
spawn_in_span(shutdown.with_cancel(async move {
143+
info!("Bootstraping the DHT with bootstrap nodes...");
144+
let bs_result = bootstrap_p2p_client
145+
.clone()
146+
.bootstrap_on_startup(&bootstraps)
147+
.await;
148+
match bs_result {
149+
Ok(_) => {
150+
info!("Bootstrap done.");
151+
},
152+
Err(e) => {
153+
warn!("Bootstrap process: {e:?}.");
154+
},
155+
}
156+
}));
157+
158+
if let Err(error) = light_client_handle.await {
159+
error!("Error running light client: {error}")
160+
};
161+
}

web/www/index.html

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Avail Light Client Web</title>
7+
</head>
8+
<body>
9+
<h1>Avail Light Client Web</h1>
10+
<script type="module">
11+
import init, { run } from './avail_light_web.js';
12+
(async () => {
13+
await init();
14+
await run();
15+
})();
16+
</script>
17+
</body>
18+
</html>

0 commit comments

Comments
 (0)