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 Oct 24, 2024
1 parent ab8ba97 commit d593f80
Show file tree
Hide file tree
Showing 12 changed files with 313 additions and 35 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 @@ -317,10 +317,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
60 changes: 32 additions & 28 deletions core/src/network/rpc/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,9 +105,11 @@ impl GenesisHash {
}

let bytes: [u8; 32] = from_hex(hex_str)
.map_err(|_| ClientCreationError::InvalidGenesisHash(hex_str.to_string()))?
.map_err(|_| ClientCreationError::InvalidGenesisHash(hex_str.to_string()))
.map_err(Report::msg)?
.try_into()
.map_err(|_| ClientCreationError::InvalidGenesisHash(hex_str.to_string()))?;
.map_err(|_| ClientCreationError::InvalidGenesisHash(hex_str.to_string()))
.map_err(Report::msg)?;

Ok(Self::Hash(H256::from(bytes)))
}
Expand Down Expand Up @@ -262,8 +264,8 @@ impl<D: Database> Client<D> {

match connection_result {
Ok(Ok(ConnectionAttempt { client, node, .. })) => Ok((client, node)),
Ok(Err(err)) => Err(RetryError::ConnectionFailed(err).into()),
Err(err) => Err(RetryError::Shutdown(err.to_string()).into()),
Ok(Err(err)) => Err(Report::msg(RetryError::ConnectionFailed(err))),
Err(err) => Err(Report::msg(RetryError::Shutdown(err.to_string()))),
}
}

Expand All @@ -289,7 +291,7 @@ impl<D: Database> Client<D> {
Fut: std::future::Future<Output = Result<T>>,
{
if nodes.is_empty() {
return Err(ClientCreationError::NoNodesAvailable.into());
return Err(Report::msg(ClientCreationError::NoNodesAvailable));
}

let mut last_error = None;
Expand All @@ -306,10 +308,9 @@ impl<D: Database> Client<D> {
}
}

Err(ClientCreationError::AllNodesFailed {
Err(Report::msg(ClientCreationError::AllNodesFailed {
last_error: last_error.unwrap_or_else(|| eyre!("No error recorded")),
}
.into())
}))
}

// Tries to connect to the provided RPC host, verifies the genesis hash,
Expand All @@ -326,33 +327,32 @@ impl<D: Database> Client<D> {
match Self::create_rpc_client(&node.host, expected_genesis_hash).await {
Ok((client, node)) => {
// Execute the provided RPC function call with the created client
let result =
f(client.clone())
.await
.map_err(|e| ClientCreationError::RpcCallFailed {
host: node.host.clone(),
error: e,
})?;
let result = f(client.clone()).await.map_err(|e| {
Report::msg(ClientCreationError::RpcCallFailed {
host: node.host.clone(),
error: e,
})
})?;

Ok(ConnectionAttempt {
client,
node,
result,
})
},
Err(err) => Err(ClientCreationError::ConnectionFailed {
Err(err) => Err(Report::msg(ClientCreationError::ConnectionFailed {
host: node.host.clone(),
error: err,
}
.into()),
})),
}
}

// Creates the RPC client by connecting to the provided RPC host and checks if the provided genesis hash matches the one from the client
async fn create_rpc_client(host: &str, expected_genesis_hash: &str) -> Result<(SDK, Node)> {
let client = SDK::new_insecure(host)
.await
.map_err(|e| ClientCreationError::SdkFailure(eyre!("{e}")))?;
.map_err(|e| ClientCreationError::SdkFailure(eyre!("{e}")))
.map_err(Report::msg)?;

// Verify genesis hash
let genesis_hash = client.api.genesis_hash();
Expand All @@ -361,12 +361,11 @@ impl<D: Database> Client<D> {
let expected_hash = GenesisHash::from_hex(expected_genesis_hash)?;

if !expected_hash.matches(&genesis_hash) {
return Err(ClientCreationError::GenesisHashMismatch {
return Err(Report::msg(ClientCreationError::GenesisHashMismatch {
host: host.to_string(),
expected: expected_genesis_hash.to_string(),
found: format!("{:?}", genesis_hash),
}
.into());
}));
}

// Fetch system and runtime information
Expand All @@ -375,7 +374,8 @@ impl<D: Database> Client<D> {
.system
.version()
.await
.map_err(|e| ClientCreationError::SystemVersionError(e.into()))?;
.map_err(|e| ClientCreationError::SystemVersionError(e.into()))
.map_err(Report::msg)?;

let runtime_version = client.api.runtime_version();

Expand All @@ -402,7 +402,11 @@ impl<D: Database> Client<D> {
}

// If current client failed try to reconnect using stored node
let connected_node = self.db.get(RpcNodeKey).ok_or(RetryError::NoPreviousNode)?;
let connected_node = self
.db
.get(RpcNodeKey)
.ok_or(RetryError::NoPreviousNode)
.map_err(Report::msg)?;

warn!(
"Executing RPC call with host: {} failed. Trying to create a new RPC connection.",
Expand Down Expand Up @@ -436,8 +440,8 @@ impl<D: Database> Client<D> {

match retry_result {
Ok(Ok(result)) => Ok(result),
Ok(Err(err)) => Err(RetryError::ConnectionFailed(err).into()),
Err(err) => Err(RetryError::Shutdown(err.to_string()).into()),
Ok(Err(err)) => Err(Report::msg(RetryError::ConnectionFailed(err))),
Err(err) => Err(Report::msg(RetryError::Shutdown(err.to_string()))),
}
}

Expand All @@ -464,8 +468,8 @@ impl<D: Database> Client<D> {
self.db.put(RpcNodeKey, node);
Ok(result)
},
Ok(Err(err)) => Err(RetryError::ConnectionFailed(err).into()),
Err(err) => Err(RetryError::Shutdown(err.to_string()).into()),
Ok(Err(err)) => Err(Report::msg(RetryError::ConnectionFailed(err))),
Err(err) => Err(Report::msg(RetryError::Shutdown(err.to_string()))),
}
}

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"
15 changes: 15 additions & 0 deletions web/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
# 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 (in Safari)

http://localhost:8000/?network=hex&bootstrap=%2Fip4%2F209.38.38.158%2Fudp%2F39001%2Fwebrtc-direct%2Fcerthash%2FuEiCVz-CTCrMq4I2xwW_WznQPML3dos4GNWiXE_fJjvHiIg
Loading

0 comments on commit d593f80

Please sign in to comment.