Skip to content

Commit 4769a67

Browse files
Support WASM in avail-light-core
1 parent 7ca0ad2 commit 4769a67

21 files changed

+733
-548
lines changed

Cargo.lock

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

Cargo.toml

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,16 @@ color-eyre = "0.6.2"
2929
confy = "0.5.1"
3030
hex = "0.4.3"
3131
rand = "0.8.4"
32-
libp2p = { version = "0.54", features = ["kad", "identify", "ping", "mdns", "autonat", "relay", "dcutr", "upnp", "noise", "yamux", "dns", "metrics", "tokio", "macros", "tcp", "quic", "serde", "websocket"] }
33-
libp2p-allow-block-list = "0.4"
34-
libp2p-webrtc = { version = "=0.8.0-alpha", features = ["tokio"] }
32+
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"] }
33+
libp2p-allow-block-list = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3" }
34+
libp2p-webrtc = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3" }
35+
libp2p-webrtc-websys = { git = "https://github.com/libp2p/rust-libp2p", rev = "9a45db3f82b760c93099e66ec77a7a772d1f6cd3" }
36+
# libp2p = { version = "0.54", features = ["kad", "identify", "ping", "mdns", "autonat", "relay", "dcutr", "upnp", "noise", "yamux", "dns", "metrics", "tokio", "macros", "tcp", "quic", "serde", "websocket"] }
37+
# libp2p-allow-block-list = "0.4"
3538
multihash = { version = "0.14.0", default-features = false, features = ["blake3", "sha3"] }
3639
semver = "1.0.23"
3740
serde = { version = "1.0", features = ["derive"] }
38-
tokio = { version = "1.35", features = ["full"] }
41+
tokio = { version = "1.35", default-features = false, features = ["sync", "macros", "io-util", "rt", "time"] }
3942
tokio-stream = { version = "0.1.15", features = ["sync"] }
4043
tracing = "0.1.35"
4144
tracing-subscriber = { version = "0.3.17", features = ["json", "env-filter"] }
@@ -60,3 +63,9 @@ incremental = false
6063
inherits = "release"
6164
lto = "fat"
6265
codegen-units = 1
66+
67+
[patch.crates-io]
68+
# Patching sp-io since some dependencies references patched and some non-patched versions,
69+
# and we need to specify `disable-allocator` feature to enable wasm compilation.
70+
# Patch needs to match patched tag of dependencies, for feature toggle to be applied.
71+
sp-io = { git = "https://github.com/availproject/polkadot-sdk.git", tag = "polkadot-1.7.1-patch-10" }

core/Cargo.toml

Lines changed: 41 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -4,66 +4,85 @@ version = "1.0.4"
44
edition = "2021"
55
description = "Avail Light core driving library"
66

7+
[lib]
8+
crate-type = ["cdylib", "rlib"]
9+
710
[dependencies]
811
# Internal deps
912
avail-rust = { workspace = true }
1013
dusk-plonk = { workspace = true }
1114

1215
# 3rd-party
13-
async-std = { workspace = true }
1416
async-stream = "0.3.5"
1517
async-trait = { workspace = true }
1618
base64 = "0.21.0"
1719
better-panic = "0.3.0"
18-
chrono = "0.4.19"
20+
blake2b_simd = "1.0.2"
21+
clap = { workspace = true }
1922
codec = { package = "parity-scale-codec", version = "3", default-features = false, features = ["derive", "full", "bit-vec"] }
2023
color-eyre = { workspace = true }
2124
confy = { workspace = true }
22-
derive_more = { version = "0.99.17", features = ["from"] }
25+
derive_more = { version = "1", features = ["from"] }
26+
dusk-bytes = { version = "0.1.6", default-features = false }
2327
futures = { workspace = true }
28+
getrandom = { version = "0.2.15", features = ["js"] }
2429
hex = { workspace = true }
25-
hyper = { version = "0.14.23", features = ["full", "http1"] }
2630
itertools = "0.10.5"
27-
jsonrpsee-core = { version = "0.21.0", features = ["client"] }
28-
libc = "0.2.150"
29-
libp2p = { workspace = true }
3031
libp2p-allow-block-list = { workspace = true }
31-
libp2p-webrtc = { version = "=0.8.0-alpha", features = ["tokio"] }
3232
mockall = "0.11.3"
33-
multihash = { workspace = true }
34-
num = "0.4.0"
35-
num_cpus = "1.13.0"
36-
pcap = "1.1.0"
37-
rand = "0.8.4"
38-
rand_chacha = "0.3"
39-
rocksdb = { version = "0.21.0", features = ["snappy", "multi-threaded-cf"], optional = true }
4033
semver = { workspace = true }
4134
serde = { workspace = true }
4235
serde_json = "1.0.125"
4336
smallvec = "1.6.1"
4437
strip-ansi-escapes = "0.2.0"
38+
strum = { version = "0.26.3", features = ["derive"] }
4539
sysinfo = "0.30.12"
46-
thiserror = "1.0.64"
47-
threadpool = "1.8.1"
4840
tokio = { workspace = true }
4941
tokio-retry = "0.3"
5042
tokio-stream = { workspace = true }
5143
tokio-util = "0.7.10"
5244
tracing = { workspace = true }
45+
tracing-subscriber = { workspace = true }
5346
uuid = { workspace = true }
47+
48+
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
49+
async-std = { workspace = true }
50+
chrono = "0.4.19"
51+
libp2p = { workspace = true }
52+
hyper = { version = "0.14.23", features = ["full", "http1"] }
53+
jsonrpsee-core = { version = "0.21.0", features = ["client"] }
54+
libc = "0.2.150"
55+
libp2p-webrtc = { workspace = true, features = ["tokio"] }
56+
multihash = { workspace = true }
57+
num = "0.4.0"
58+
num_cpus = "1.13.0"
59+
pcap = "1.1.0"
60+
rand = "0.8.4"
61+
rand_chacha = "0.3"
62+
rocksdb = { version = "0.21.0", features = ["snappy", "multi-threaded-cf"], optional = true }
63+
thiserror = "1.0.64"
64+
threadpool = "1.8.1"
5465
void = { workspace = true }
5566
warp = { workspace = true }
5667

5768
# OpenTelemetry
58-
clap = { workspace = true }
5969
opentelemetry = { workspace = true }
6070
opentelemetry-otlp = { workspace = true }
6171
opentelemetry_sdk = { workspace = true }
62-
strum = { version = "0.26.3", features = ["derive"] }
63-
tracing-subscriber = { workspace = true }
6472

65-
[dev-dependencies]
66-
hex-literal = "0.4.0"
73+
[target.'cfg(target_arch = "wasm32")'.dependencies]
74+
ed25519-compact = "2.1.1"
75+
thiserror-no-std = "2.0.2"
76+
rand = { version = "0.8.4", default-features = false }
77+
libp2p = { workspace = true, features = ["wasm-bindgen"] }
78+
libp2p-webrtc-websys = { workspace = true }
79+
wasm-bindgen = "0.2.90"
80+
wasm-timer = "0.2.5"
81+
web-time = "1.1.0"
82+
tokio_with_wasm = { version = "0.7.1", default-features = false, features = ["sync", "macros", "rt", "time"] }
83+
84+
[target.'cfg(not(target_arch = "wasm32"))'.dev-dependencies]
85+
hex-literal = "0.4.1"
6786
proptest = "1.0.0"
6887
test-case = "3.2.1"
6988

core/src/finality.rs

Lines changed: 24 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
use std::collections::HashMap;
22

3-
use avail_rust::sp_core::{
4-
blake2_256,
5-
ed25519::{self, Public},
6-
Pair, H256,
7-
};
3+
#[cfg(not(target_arch = "wasm32"))]
4+
use avail_rust::sp_core::ed25519;
5+
use avail_rust::sp_core::{ed25519::Public, H256};
86
use codec::Encode;
97
use itertools::Itertools;
108
use serde::{Deserialize, Serialize};
119
use tracing::{info, warn};
1210

13-
use crate::types::{GrandpaJustification, SignerMessage};
11+
use crate::{
12+
types::{GrandpaJustification, SignerMessage},
13+
utils::blake2_256,
14+
};
1415
use color_eyre::{eyre::eyre, Result};
1516

1617
#[derive(Clone, Debug, Serialize, Deserialize)]
@@ -19,6 +20,22 @@ pub struct ValidatorSet {
1920
pub validator_set: Vec<Public>,
2021
}
2122

23+
#[cfg(not(target_arch = "wasm32"))]
24+
fn verify_signature(public_key: [u8; 32], signature: [u8; 64], message: Vec<u8>) -> bool {
25+
<ed25519::Pair as avail_rust::sp_core::Pair>::verify(
26+
&ed25519::Signature(signature),
27+
message,
28+
&ed25519::Public(public_key),
29+
)
30+
}
31+
32+
#[cfg(target_arch = "wasm32")]
33+
fn verify_signature(public_key: [u8; 32], signature: [u8; 64], message: Vec<u8>) -> bool {
34+
let public_key = ed25519_compact::PublicKey::from_slice(&public_key).unwrap();
35+
let signature = ed25519_compact::Signature::from_slice(&signature).unwrap();
36+
public_key.verify(message, &signature).is_ok()
37+
}
38+
2239
pub fn check_finality(
2340
validator_set: &ValidatorSet,
2441
justification: &GrandpaJustification,
@@ -47,12 +64,7 @@ pub fn check_finality(
4764
&justification.round,
4865
&validator_set.set_id, // Set ID is needed here.
4966
));
50-
let is_ok = <ed25519::Pair as Pair>::verify(
51-
&precommit.signature,
52-
signed_message,
53-
&precommit.id,
54-
);
55-
67+
let is_ok = verify_signature(precommit.id.0, precommit.signature.0, signed_message);
5668
let ancestry = confirm_ancestry(
5769
&precommit.precommit.target_hash,
5870
&justification.commit.target_hash,

core/src/lib.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,25 @@
1+
#[cfg(not(target_arch = "wasm32"))]
12
pub mod api;
3+
#[cfg(not(target_arch = "wasm32"))]
24
pub mod app_client;
5+
#[cfg(not(target_arch = "wasm32"))]
36
#[cfg(feature = "crawl")]
47
pub mod crawl_client;
58
pub mod data;
9+
#[cfg(not(target_arch = "wasm32"))]
610
pub mod fat_client;
711
pub mod finality;
812
pub mod light_client;
13+
#[cfg(not(target_arch = "wasm32"))]
914
pub mod maintenance;
1015
pub mod network;
1116
pub mod proof;
1217
pub mod shutdown;
18+
#[cfg(not(target_arch = "wasm32"))]
1319
pub mod sync_client;
20+
#[cfg(not(target_arch = "wasm32"))]
1421
pub mod sync_finality;
22+
#[cfg(not(target_arch = "wasm32"))]
1523
pub mod telemetry;
1624
pub mod types;
1725
pub mod utils;

core/src/light_client.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,18 @@
1919
2020
use avail_rust::{
2121
kate_recovery::{commitments, matrix::Dimensions},
22-
sp_core::blake2_256,
2322
AvailHeader, H256,
2423
};
2524
use codec::Encode;
2625
use color_eyre::Result;
26+
#[cfg(not(target_arch = "wasm32"))]
2727
use std::time::Instant;
2828
use tokio::sync::mpsc::UnboundedSender;
29+
#[cfg(target_arch = "wasm32")]
30+
use tokio_with_wasm::alias as tokio;
2931
use tracing::{error, info};
32+
#[cfg(target_arch = "wasm32")]
33+
use web_time::Instant;
3034

3135
use crate::{
3236
data::{AchievedConfidenceKey, BlockHeaderKey, Database, VerifiedCellCountKey},
@@ -36,7 +40,7 @@ use crate::{
3640
},
3741
shutdown::Controller,
3842
types::{self, BlockRange, ClientChannels, Delay},
39-
utils::{calculate_confidence, extract_kate},
43+
utils::{blake2_256, calculate_confidence, extract_kate},
4044
};
4145

4246
pub enum OutputEvent {

core/src/network.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,17 @@ use color_eyre::{eyre::WrapErr, Result};
1212
use dusk_plonk::prelude::PublicParameters;
1313
use libp2p::{Multiaddr, PeerId};
1414
use mockall::automock;
15-
use std::{str::FromStr, sync::Arc, time::Duration};
15+
#[cfg(not(target_arch = "wasm32"))]
16+
use std::time::Duration;
17+
use std::{str::FromStr, sync::Arc};
1618
use strum::Display;
19+
#[cfg(not(target_arch = "wasm32"))]
1720
use tokio::time::Instant;
1821
use tracing::{debug, info};
22+
#[cfg(target_arch = "wasm32")]
23+
use web_time::Duration;
24+
#[cfg(target_arch = "wasm32")]
25+
use web_time::Instant;
1926

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

core/src/network/p2p.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,35 @@ use libp2p::{
88
autonat, dcutr, identify,
99
identity::{self, ed25519, Keypair},
1010
kad::{self, Mode, PeerRecord, QueryStats, Record, RecordKey},
11-
mdns, noise, ping, relay,
11+
noise, ping, relay,
1212
swarm::NetworkBehaviour,
13-
tcp, upnp, yamux, Multiaddr, PeerId, Swarm, SwarmBuilder,
13+
yamux, Multiaddr, PeerId, Swarm, SwarmBuilder,
1414
};
15+
#[cfg(not(target_arch = "wasm32"))]
16+
use libp2p::{mdns, tcp, upnp};
17+
#[cfg(not(target_arch = "wasm32"))]
1518
use libp2p_webrtc as webrtc;
19+
#[cfg(not(target_arch = "wasm32"))]
1620
use multihash::{self, Hasher};
21+
#[cfg(not(target_arch = "wasm32"))]
1722
use rand::thread_rng;
1823
use semver::Version;
1924
use serde::{Deserialize, Serialize};
20-
use std::{fmt, net::Ipv4Addr, str::FromStr, time::Duration};
25+
#[cfg(not(target_arch = "wasm32"))]
26+
use std::time::Duration;
27+
use std::{fmt, net::Ipv4Addr, str::FromStr};
2128
use tokio::sync::{
2229
mpsc::{self, UnboundedReceiver},
2330
oneshot,
2431
};
32+
#[cfg(target_arch = "wasm32")]
33+
use tokio_with_wasm::alias as tokio;
2534
use tracing::{info, warn};
35+
#[cfg(target_arch = "wasm32")]
36+
use web_time::Duration;
2637

2738
#[cfg(feature = "network-analysis")]
39+
#[cfg(not(target_arch = "wasm32"))]
2840
pub mod analyzer;
2941
mod client;
3042
pub mod configuration;
@@ -170,10 +182,12 @@ pub struct Behaviour {
170182
kademlia: kad::Behaviour<Store>,
171183
identify: identify::Behaviour,
172184
ping: ping::Behaviour,
185+
#[cfg(not(target_arch = "wasm32"))]
173186
mdns: mdns::tokio::Behaviour,
174187
auto_nat: autonat::Behaviour,
175188
relay_client: relay::client::Behaviour,
176189
dcutr: dcutr::Behaviour,
190+
#[cfg(not(target_arch = "wasm32"))]
177191
upnp: upnp::tokio::Behaviour,
178192
blocked_peers: allow_block_list::Behaviour<BlockedPeers>,
179193
}
@@ -274,8 +288,12 @@ async fn build_swarm(
274288

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

294+
#[cfg(target_arch = "wasm32")]
295+
let tokio_swarm = SwarmBuilder::with_existing_identity(id_keys.clone()).with_wasm_bindgen();
296+
279297
let mut swarm;
280298

281299
let kad_cfg: kad::Config = kad_config(cfg, genesis_hash);
@@ -288,12 +306,26 @@ async fn build_swarm(
288306
dcutr: dcutr::Behaviour::new(key.public().to_peer_id()),
289307
kademlia: kad::Behaviour::with_config(key.public().to_peer_id(), kad_store, kad_cfg),
290308
auto_nat: autonat::Behaviour::new(key.public().to_peer_id(), autonat_cfg),
309+
#[cfg(not(target_arch = "wasm32"))]
291310
mdns: mdns::Behaviour::new(mdns::Config::default(), key.public().to_peer_id())?,
311+
#[cfg(not(target_arch = "wasm32"))]
292312
upnp: upnp::tokio::Behaviour::default(),
293313
blocked_peers: allow_block_list::Behaviour::default(),
294314
})
295315
};
316+
#[cfg(target_arch = "wasm32")]
317+
{
318+
swarm = tokio_swarm
319+
.with_other_transport(|key| {
320+
libp2p_webrtc_websys::Transport::new(libp2p_webrtc_websys::Config::new(&key))
321+
})?
322+
.with_relay_client(noise::Config::new, yamux::Config::default)?
323+
.with_behaviour(behaviour)?
324+
.with_swarm_config(|c| generate_config(c, cfg))
325+
.build();
326+
}
296327

328+
#[cfg(not(target_arch = "wasm32"))]
297329
if cfg.ws_transport_enable {
298330
swarm = tokio_swarm
299331
.with_websocket(noise::Config::new, yamux::Config::default)
@@ -340,6 +372,7 @@ async fn build_swarm(
340372
// From such generated keypair it derives multihash identifier of the local peer.
341373
fn keypair(secret_key: &SecretKey) -> Result<identity::Keypair> {
342374
let keypair = match secret_key {
375+
#[cfg(not(target_arch = "wasm32"))]
343376
// If seed is provided, generate secret key from seed
344377
SecretKey::Seed { seed } => {
345378
let seed_digest = multihash::Sha3_256::digest(seed.as_bytes());

core/src/network/p2p/client.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,15 @@ use libp2p::{
1616
swarm::dial_opts::DialOpts,
1717
Multiaddr, PeerId,
1818
};
19+
#[cfg(not(target_arch = "wasm32"))]
1920
use std::time::{Duration, Instant};
2021
use sysinfo::System;
2122
use tokio::sync::{mpsc::UnboundedSender, oneshot};
23+
#[cfg(target_arch = "wasm32")]
24+
use tokio_with_wasm::alias as tokio;
2225
use tracing::{debug, info, trace, warn};
26+
#[cfg(target_arch = "wasm32")]
27+
use web_time::{Duration, Instant};
2328

2429
use super::{
2530
event_loop::ConnectionEstablishedInfo, is_global, is_multiaddr_global, Command, EventLoop,

0 commit comments

Comments
 (0)