Skip to content

Commit

Permalink
Support WASM in avail-light-core
Browse files Browse the repository at this point in the history
  • Loading branch information
aterentic-ethernal committed Nov 26, 2024
1 parent 294f4c3 commit 1c3d037
Show file tree
Hide file tree
Showing 18 changed files with 472 additions and 450 deletions.
562 changes: 213 additions & 349 deletions Cargo.lock

Large diffs are not rendered by default.

18 changes: 14 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,17 @@ 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 = { version = "0.8.5", default-features = false }
libp2p = { version = "0.54", features = ["kad", "identify", "ping", "mdns", "autonat", "relay", "dcutr", "upnp", "noise", "yamux", "dns", "metrics", "tokio", "macros", "tcp", "quic", "serde", "websocket"] }
libp2p-allow-block-list = "0.4"
libp2p-webrtc = { version = "=0.8.0-alpha", features = ["tokio"] }
# libp2p = { version = "0.54", features = ["kad", "identify", "ping", "mdns", "autonat", "relay", "dcutr", "upnp", "noise", "yamux", "dns", "metrics", "tokio", "macros", "tcp", "quic", "serde", "websocket"] }
# libp2p-allow-block-list = "0.4"
# libp2p-webrtc = { version = "=0.8.0-alpha", features = ["tokio"] }
libp2p = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3", features = ["kad", "identify", "ping", "mdns", "autonat", "relay", "dcutr", "upnp", "noise", "yamux", "dns", "metrics", "tokio", "macros", "tcp", "quic", "serde", "websocket"] }
libp2p-allow-block-list = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3" }
libp2p-webrtc = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3" }
libp2p-webrtc-websys = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3" }
multihash = { version = "0.14.0", default-features = false, features = ["blake3", "sha3"] }
semver = "1.0.23"
serde = { version = "1.0", features = ["derive"] }
Expand Down Expand Up @@ -60,3 +64,9 @@ incremental = false
inherits = "release"
lto = "fat"
codegen-units = 1

[patch.crates-io]
# Patching sp-io since some dependencies references patched and some non-patched versions,
# and we need to specify `disable-allocator` feature to enable wasm compilation.
# Patch needs to match patched tag of dependencies, for feature toggle to be applied.
sp-io = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-10" }
2 changes: 2 additions & 0 deletions core/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

## 1.0.5

- Enable WASM compilation of the light client
- Enable WASM compilation on network, types and finality mods
- Enable WASM compilation on proof mod
- Enable WASM compilation on utils and shutdown mods
- Allocate new port on each new dial attempt
Expand Down
50 changes: 29 additions & 21 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,73 +13,81 @@ avail-rust = { workspace = true }
dusk-plonk = { workspace = true }

# 3rd-party
async-stream = "0.3.5"
async-trait = { workspace = true }
base64 = "0.21.0"
better-panic = "0.3.0"
chrono = "0.4.19"
clap = { workspace = true }
codec = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "full", "bit-vec"] }
color-eyre = { workspace = true }
color-eyre = { workspace = true, default-features = true }
confy = { workspace = true }
convert_case = "0.6.0"
derive_more = { version = "1", features = ["from"] }
dusk-bytes = "0.1.7"
futures = { workspace = true }
getrandom = { version = "0.2.15", features = ["js"] }
hex = { workspace = true }
itertools = "0.10.5"
libp2p-allow-block-list = { workspace = true }
mockall = "0.11.3"
semver = { workspace = true }
serde = { workspace = true }
serde_json = "1.0.125"
smallvec = "1.6.1"
strip-ansi-escapes = "0.2.0"
strum = { version = "0.26.3", features = ["derive"] }
sysinfo = "0.30.12"
tokio = { workspace = true }
tokio-retry = "0.3"
tokio-stream = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
uuid = { workspace = true }

[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
async-std = { workspace = true }
async-stream = "0.3.5"
async-trait = { workspace = true }
base64 = "0.21.0"
chrono = "0.4.19"
confy = { workspace = true }
convert_case = "0.6.0"
derive_more = { version = "1", features = ["from"] }
futures = { workspace = true }
hex = { workspace = true }
hyper = { version = "0.14.23", features = ["full", "http1"] }
jsonrpsee-core = { version = "0.21.0", features = ["client"] }
libc = "0.2.150"
libp2p = { workspace = true }
libp2p-allow-block-list = { workspace = true }
libp2p-webrtc = { version = "=0.8.0-alpha", features = ["tokio"] }
mockall = "0.11.3"
libp2p-webrtc = { workspace = true, features = ["tokio"] }
multihash = { workspace = true }
num = "0.4.0"
num_cpus = "1.13.0"
pcap = "1.1.0"
rand = { workspace = true, default-features = true }
rand_chacha = "0.3"
rocksdb = { version = "0.21.0", features = ["snappy", "multi-threaded-cf"], optional = true }
semver = { workspace = true }
serde = { workspace = true }
serde_json = "1.0.125"
smallvec = "1.6.1"
strip-ansi-escapes = "0.2.0"
sysinfo = "0.30.12"
thiserror = "1.0.64"
threadpool = "1.8.1"
tokio-retry = "0.3"
tokio-stream = { workspace = true }
tokio-util = "0.7.10"
tracing = { workspace = true }
uuid = { workspace = true }
tracing-subscriber = { workspace = true }
void = { workspace = true }
warp = { workspace = true }

# OpenTelemetry
clap = { workspace = true }
opentelemetry = { workspace = true }
opentelemetry-otlp = { workspace = true }
opentelemetry_sdk = { workspace = true }
strum = { version = "0.26.3", features = ["derive"] }

[target.'cfg(target_arch = "wasm32")'.dependencies]
blake2b_simd = "1.0.2"
color-eyre = { workspace = true }
ed25519-compact = "2.1.1"
# NOTE: This is used due bug explained at: https://github.com/tomaka/wasm-timer/pull/13
fluvio-wasm-timer = "0.2.5"
libp2p = { workspace = true, features = ["wasm-bindgen"] }
libp2p-webrtc-websys = { workspace = true }
rand = { workspace = true, features = ["std_rng"] }
thiserror-no-std = "2.0.2"
tokio_with_wasm = { version = "0.7.1", default-features = false, features = ["sync", "macros", "rt", "time"] }
web-time = "1.1.0"
wasm-bindgen = "0.2.90"

[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
hex-literal = "0.4.1"
Expand Down
33 changes: 20 additions & 13 deletions core/src/finality.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,8 @@
use std::collections::HashMap;

use avail_rust::{
sp_core::{
ed25519::{self, Public},
Pair,
},
H256,
};
#[cfg(not(target_arch = "wasm32"))]
use avail_rust::sp_core::ed25519;
use avail_rust::{sp_core::ed25519::Public, H256};
use codec::Encode;
use itertools::Itertools;
use serde::{Deserialize, Serialize};
Expand All @@ -24,6 +20,22 @@ pub struct ValidatorSet {
pub validator_set: Vec<Public>,
}

#[cfg(not(target_arch = "wasm32"))]
fn verify_signature(public_key: [u8; 32], signature: [u8; 64], message: Vec<u8>) -> bool {
<ed25519::Pair as avail_rust::sp_core::Pair>::verify(
&ed25519::Signature(signature),
message,
&ed25519::Public(public_key),
)
}

#[cfg(target_arch = "wasm32")]
fn verify_signature(public_key: [u8; 32], signature: [u8; 64], message: Vec<u8>) -> bool {
let public_key = ed25519_compact::PublicKey::from_slice(&public_key).unwrap();
let signature = ed25519_compact::Signature::from_slice(&signature).unwrap();
public_key.verify(message, &signature).is_ok()
}

pub fn check_finality(
validator_set: &ValidatorSet,
justification: &GrandpaJustification,
Expand Down Expand Up @@ -52,12 +64,7 @@ pub fn check_finality(
&justification.round,
&validator_set.set_id, // Set ID is needed here.
));
let is_ok = <ed25519::Pair as Pair>::verify(
&precommit.signature,
signed_message,
&precommit.id,
);

let is_ok = verify_signature(precommit.id.0, precommit.signature.0, signed_message);
let ancestry = confirm_ancestry(
&precommit.precommit.target_hash,
&justification.commit.target_hash,
Expand Down
5 changes: 0 additions & 5 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,17 +6,13 @@ pub mod app_client;
#[cfg(feature = "crawl")]
#[cfg(not(target_arch = "wasm32"))]
pub mod crawl_client;
#[cfg(not(target_arch = "wasm32"))]
pub mod data;
#[cfg(not(target_arch = "wasm32"))]
pub mod fat_client;
#[cfg(not(target_arch = "wasm32"))]
pub mod finality;
#[cfg(not(target_arch = "wasm32"))]
pub mod light_client;
#[cfg(not(target_arch = "wasm32"))]
pub mod maintenance;
#[cfg(not(target_arch = "wasm32"))]
pub mod network;
pub mod proof;
pub mod shutdown;
Expand All @@ -26,6 +22,5 @@ pub mod sync_client;
pub mod sync_finality;
#[cfg(not(target_arch = "wasm32"))]
pub mod telemetry;
#[cfg(not(target_arch = "wasm32"))]
pub mod types;
pub mod utils;
6 changes: 6 additions & 0 deletions core/src/light_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,14 @@ use avail_rust::{
};
use codec::Encode;
use color_eyre::Result;
#[cfg(not(target_arch = "wasm32"))]
use std::time::Instant;
use tokio::sync::mpsc::UnboundedSender;
#[cfg(target_arch = "wasm32")]
use tokio_with_wasm::alias as tokio;
use tracing::{error, info};
#[cfg(target_arch = "wasm32")]
use web_time::Instant;

use crate::{
data::{AchievedConfidenceKey, BlockHeaderKey, Database, VerifiedCellCountKey},
Expand All @@ -38,6 +43,7 @@ use crate::{
utils::{blake2_256, calculate_confidence, extract_kate},
};

#[derive(Debug)]
pub enum OutputEvent {
RecordBlockProcessingDelay(f64),
CountSessionBlocks,
Expand Down
9 changes: 8 additions & 1 deletion core/src/network.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,17 @@ use color_eyre::{eyre::WrapErr, Result};
use dusk_plonk::prelude::PublicParameters;
use libp2p::{Multiaddr, PeerId};
use mockall::automock;
use std::{str::FromStr, sync::Arc, time::Duration};
#[cfg(not(target_arch = "wasm32"))]
use std::time::Duration;
use std::{str::FromStr, sync::Arc};
use strum::Display;
#[cfg(not(target_arch = "wasm32"))]
use tokio::time::Instant;
use tracing::{debug, info};
#[cfg(target_arch = "wasm32")]
use web_time::Duration;
#[cfg(target_arch = "wasm32")]
use web_time::Instant;

use crate::{data::Database, proof};

Expand Down
38 changes: 35 additions & 3 deletions core/src/network/p2p.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,35 @@ use libp2p::{
autonat, dcutr, identify,
identity::{self, ed25519, Keypair},
kad::{self, Mode, PeerRecord, QueryStats, Record, RecordKey},
mdns, noise, ping, relay,
noise, ping, relay,
swarm::NetworkBehaviour,
tcp, upnp, yamux, Multiaddr, PeerId, Swarm, SwarmBuilder,
yamux, Multiaddr, PeerId, Swarm, SwarmBuilder,
};
#[cfg(not(target_arch = "wasm32"))]
use libp2p::{mdns, tcp, upnp};
#[cfg(not(target_arch = "wasm32"))]
use libp2p_webrtc as webrtc;
#[cfg(not(target_arch = "wasm32"))]
use multihash::{self, Hasher};
#[cfg(not(target_arch = "wasm32"))]
use rand::thread_rng;
use semver::Version;
use serde::{Deserialize, Serialize};
use std::{fmt, net::Ipv4Addr, str::FromStr, time::Duration};
#[cfg(not(target_arch = "wasm32"))]
use std::time::Duration;
use std::{fmt, net::Ipv4Addr, str::FromStr};
use tokio::sync::{
mpsc::{self, UnboundedReceiver},
oneshot,
};
#[cfg(target_arch = "wasm32")]
use tokio_with_wasm::alias as tokio;
use tracing::{info, warn};
#[cfg(target_arch = "wasm32")]
use web_time::Duration;

#[cfg(feature = "network-analysis")]
#[cfg(not(target_arch = "wasm32"))]
pub mod analyzer;
mod client;
pub mod configuration;
Expand Down Expand Up @@ -170,10 +182,12 @@ pub struct Behaviour {
kademlia: kad::Behaviour<Store>,
identify: identify::Behaviour,
ping: ping::Behaviour,
#[cfg(not(target_arch = "wasm32"))]
mdns: mdns::tokio::Behaviour,
auto_nat: autonat::Behaviour,
relay_client: relay::client::Behaviour,
dcutr: dcutr::Behaviour,
#[cfg(not(target_arch = "wasm32"))]
upnp: upnp::tokio::Behaviour,
blocked_peers: allow_block_list::Behaviour<BlockedPeers>,
}
Expand Down Expand Up @@ -274,8 +288,12 @@ async fn build_swarm(

// build the Swarm, connecting the lower transport logic with the
// higher layer network behaviour logic
#[cfg(not(target_arch = "wasm32"))]
let tokio_swarm = SwarmBuilder::with_existing_identity(id_keys.clone()).with_tokio();

#[cfg(target_arch = "wasm32")]
let tokio_swarm = SwarmBuilder::with_existing_identity(id_keys.clone()).with_wasm_bindgen();

let mut swarm;

let kad_cfg: kad::Config = kad_config(cfg, genesis_hash);
Expand All @@ -288,12 +306,25 @@ async fn build_swarm(
dcutr: dcutr::Behaviour::new(key.public().to_peer_id()),
kademlia: kad::Behaviour::with_config(key.public().to_peer_id(), kad_store, kad_cfg),
auto_nat: autonat::Behaviour::new(key.public().to_peer_id(), autonat_cfg),
#[cfg(not(target_arch = "wasm32"))]
mdns: mdns::Behaviour::new(mdns::Config::default(), key.public().to_peer_id())?,
#[cfg(not(target_arch = "wasm32"))]
upnp: upnp::tokio::Behaviour::default(),
blocked_peers: allow_block_list::Behaviour::default(),
})
};
#[cfg(target_arch = "wasm32")]
{
use libp2p_webrtc_websys as webrtc;
swarm = tokio_swarm
.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))
.build();
}

#[cfg(not(target_arch = "wasm32"))]
if cfg.ws_transport_enable {
swarm = tokio_swarm
.with_websocket(noise::Config::new, yamux::Config::default)
Expand Down Expand Up @@ -340,6 +371,7 @@ async fn build_swarm(
// From such generated keypair it derives multihash identifier of the local peer.
fn keypair(secret_key: &SecretKey) -> Result<identity::Keypair> {
let keypair = match secret_key {
#[cfg(not(target_arch = "wasm32"))]
// If seed is provided, generate secret key from seed
SecretKey::Seed { seed } => {
let seed_digest = multihash::Sha3_256::digest(seed.as_bytes());
Expand Down
5 changes: 5 additions & 0 deletions core/src/network/p2p/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,15 @@ use libp2p::{
swarm::dial_opts::{DialOpts, PeerCondition},
Multiaddr, PeerId,
};
#[cfg(not(target_arch = "wasm32"))]
use std::time::{Duration, Instant};
use sysinfo::System;
use tokio::sync::{mpsc::UnboundedSender, oneshot};
#[cfg(target_arch = "wasm32")]
use tokio_with_wasm::alias as tokio;
use tracing::{debug, info, trace, warn};
#[cfg(target_arch = "wasm32")]
use web_time::{Duration, Instant};

use super::{
event_loop::ConnectionEstablishedInfo, is_global, is_multiaddr_global, Command, EventLoop,
Expand Down
5 changes: 4 additions & 1 deletion core/src/network/p2p/configuration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,15 @@ use crate::network::p2p::MemoryStoreConfig;
use crate::types::{duration_seconds_format, KademliaMode, MultiaddrConfig, SecretKey};
use libp2p::{kad, multiaddr::Protocol, Multiaddr};
use serde::{Deserialize, Serialize};
#[cfg(not(target_arch = "wasm32"))]
use std::time::Duration;
use std::{
borrow::Cow,
net::Ipv4Addr,
num::{NonZeroU8, NonZeroUsize},
time::Duration,
};
#[cfg(target_arch = "wasm32")]
use web_time::Duration;

/// Libp2p AutoNAT configuration (see [RuntimeConfig] for details)
#[derive(Clone, Serialize, Deserialize, Debug)]
Expand Down
Loading

0 comments on commit 1c3d037

Please sign in to comment.