diff --git a/examples/examples/unstable_light_client_tx_basic.rs b/examples/examples/unstable_light_client_tx_basic.rs index 82b34e0225..e02f8358d4 100644 --- a/examples/examples/unstable_light_client_tx_basic.rs +++ b/examples/examples/unstable_light_client_tx_basic.rs @@ -7,7 +7,7 @@ use subxt::{rpc::LightClient, tx::PairSigner, OnlineClient, PolkadotConfig}; // #[subxt::subxt(runtime_metadata_path = "../artifacts/polkadot_metadata_small.scale")] // pub mod polkadot {} -#[tokio::main] +#[tokio::main(flavor = "current_thread")] async fn main() -> Result<(), Box> { tracing_subscriber::fmt::init(); diff --git a/subxt/Cargo.toml b/subxt/Cargo.toml index 15d400ba48..399fb537af 100644 --- a/subxt/Cargo.toml +++ b/subxt/Cargo.toml @@ -49,7 +49,7 @@ unstable-light-client = [ # "smoldot-light/std", "smoldot-light", # "futures-executor", - # "smoldot-light-wasm", + "smoldot-light-wasm", "tokio-stream", "tokio/sync", "tokio/rt", diff --git a/subxt/src/rpc/lightclient/client.rs b/subxt/src/rpc/lightclient/client.rs index 61dcb7605b..8c19c7b3f9 100644 --- a/subxt/src/rpc/lightclient/client.rs +++ b/subxt/src/rpc/lightclient/client.rs @@ -21,6 +21,7 @@ use jsonrpsee::{ }; use serde_json::value::RawValue; // use smoldot_light::{platform::async_std::AsyncStdTcpWebSocket, ChainId}; + use smoldot_light::ChainId; use std::{ iter, @@ -34,9 +35,9 @@ use std::{ use tokio::sync::{mpsc, oneshot}; use tokio_stream::wrappers::ReceiverStream; -// use smoldot_light_wasm::platform::Platform as WasmPlatform; +use smoldot_light_wasm::platform::Platform as WasmPlatform; -use super::platform::Platform as MyPlatform; +// use super::platform::Platform as MyPlatform; const LOG_TARGET: &str = "light-client"; @@ -45,7 +46,7 @@ struct LightClientInner { /// Smoldot light client implementation that leverages the `AsyncStdTcpWebSocket`. /// /// Note: `AsyncStdTcpWebSocket` is not wasm compatible. - client: smoldot_light::Client, + client: smoldot_light::Client, /// The ID of the chain used to identify the chain protocol (ie. substrate). /// /// Note: A single chain is supported for a client. This aligns with the subxt's @@ -447,7 +448,7 @@ impl LightClient { // env!("CARGO_PKG_VERSION").into(), // ); - let platform = MyPlatform::new(); + let platform = WasmPlatform::new(); let mut client = smoldot_light::Client::new(platform); diff --git a/subxt/src/rpc/lightclient/platform.rs b/subxt/src/rpc/lightclient/platform.rs index f05690fe57..cd37b48125 100644 --- a/subxt/src/rpc/lightclient/platform.rs +++ b/subxt/src/rpc/lightclient/platform.rs @@ -46,14 +46,6 @@ impl smoldot_light::platform::PlatformRef for Platform { Result, ConnectError>, >; - // type ConnectFuture = future::BoxFuture< - // 'static, - // Result< - // smoldot_light::platform::PlatformConnection, - // ConnectError, - // >, - // >; - type StreamUpdateFuture<'a> = future::BoxFuture<'a, ()>; type NextSubstreamFuture<'a> = @@ -135,7 +127,8 @@ impl smoldot_light::platform::PlatformRef for Platform { (ProtocolRef::Ip6(ip), ProtocolRef::Tcp(port), Some(ProtocolRef::Ws)) => { SocketAddr::new(IpAddr::V6((ip).into()), port) } - // // TODO: we don't care about the differences between Dns, Dns4, and Dns6 + // TODO: Minimal protocol, check that basic connection is working. + // TODO: we don't care about the differences between Dns, Dns4, and Dns6 // ( // ProtocolRef::Dns(addr) | ProtocolRef::Dns4(addr) | ProtocolRef::Dns6(addr), // ProtocolRef::Tcp(port), @@ -166,93 +159,26 @@ impl smoldot_light::platform::PlatformRef for Platform { // let (to_sender, from_sender) = mpsc::channel(1024); // let (to_receiver, from_receiver) = mpsc::channel(1024); - // TODO: Spawn a task: - // enun Protocol - /* - - enum Protocol { - Send(String), - Recv(String), - } - - bg_task { - while .. - Future: - A: if Send() .. self.send(); - B: self.next() -> recv_end.send("Msg"); - - } - - from fn send(&self, stream: &mut Self::Stream, data: &[u8]) { - let str: String = data.into(); - sender.send(str); - } - - from fn read_buffer<'a> { - - - } - - * - */ - - // Note: WebSocket is not `Send`, work around that with a spawned task. - - // wasm_bindgen_futures::spawn_local(async move { - // let sender = tokio_stream::wrappers::ReceiverStream::new(from_sender); - // let receiver = tokio_stream::wrappers::ReceiverStream::new(from_receiver); - - // // let rpc_responses_event = - // // futures_util::stream::unfold(rpc_responses, |mut rpc_responses| async { - // // rpc_responses - // // .next() - // // .await - // // .map(|result| (result, rpc_responses)) - // // }); - - // tokio::pin!(backend_event, rpc_responses_event); - - // let mut backend_event_fut = backend_event.next(); - // let mut rpc_responses_fut = rpc_responses_event.next(); - - // loop { - // match future::select(backend_event_fut, rpc_responses_fut).await { - // // Message received from the backend: user registered. - // Either::Left((backend_value, previous_fut)) => { - // let Some(message) = backend_value else { - // println!("Frontend channel closed"); - // break; - // }; - // tracing::trace!( - // target: LOG_TARGET, - // "Received register message {:?}", - // message - // ); - - // self.handle_register(message).await; - - // backend_event_fut = backend_event.next(); - // rpc_responses_fut = previous_fut; - // } - // // Message received from rpc handler: lightclient response. - // Either::Right((response, previous_fut)) => { - // // Smoldot returns `None` if the chain has been removed (which subxt does not remove). - // let Some(response) = response else { - // println!("Smoldot RPC responses channel closed"); - // break; - // }; - // println!("Received smoldot RPC result {:?}", response); - - // self.handle_rpc_response(response).await; - - // // Advance backend, save frontend. - // backend_event_fut = previous_fut; - // rpc_responses_fut = rpc_responses_event.next(); - // } - // } - // } - // }); - + //TODO: Spawn a task: + // enum Protocol { + // Send(String), + // Recv(String), + // } + // + // bg_task { + // while .. + // Future: + // A: if Send() .. self.send(); + // B: self.next() -> recv_end.send("Msg"); + // + // } + // + // from fn send(&self, stream: &mut Self::Stream, data: &[u8]) { + // let str: String = data.into(); + // sender.send(str); + // } + // + // from fn read_buffer<'a> { let (sender, receiver) = websocket.split(); let conn = ConnectionStream { inner: Arc::new(Mutex::new(ConnectionInner { sender, receiver })), @@ -290,8 +216,6 @@ impl smoldot_light::platform::PlatformRef for Platform { .lock() .expect("Mutex should not be poised; qed"); - // let fut = locked.receiver.next(); - // let msg = futures_executor::block_on(async { let msg = futures::executor::block_on(async { match locked.receiver.next().await { @@ -335,14 +259,6 @@ impl smoldot_light::platform::PlatformRef for Platform { fn close_send(&self, stream: &mut Self::Stream) {} } -/// Error potentially returned by [`PlatformRef::connect`]. -// pub struct ConnectError { -// /// Human-readable error message. -// pub message: String, -// /// `true` if the error is caused by the address to connect to being forbidden or unsupported. -// pub is_bad_addr: bool, -// } - pub struct ConnectionInner { sender: SplitSink, receiver: SplitStream, diff --git a/testing/wasm-tests/Cargo.lock b/testing/wasm-tests/Cargo.lock index 6c97e3d2c6..10f6c9403d 100644 --- a/testing/wasm-tests/Cargo.lock +++ b/testing/wasm-tests/Cargo.lock @@ -75,6 +75,20 @@ version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8da52d66c7071e2e3fa2a1e5c6d088fec47b593032b254f5e980de8ea54454d6" +[[package]] +name = "async-executor" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6fa3dc5f2a8564f07759c008b9109dc0d39de92a88d5588b8a5036d286383afb" +dependencies = [ + "async-lock", + "async-task", + "concurrent-queue", + "fastrand", + "futures-lite", + "slab", +] + [[package]] name = "async-lock" version = "2.7.0" @@ -84,6 +98,12 @@ dependencies = [ "event-listener", ] +[[package]] +name = "async-task" +version = "4.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ecc7ab41815b3c653ccd2978ec3255c81349336702dfdf62ee6f7069b12a3aae" + [[package]] name = "async-trait" version = "0.1.68" @@ -291,6 +311,15 @@ dependencies = [ "generic-array", ] +[[package]] +name = "concurrent-queue" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62ec6771ecfa0762d24683ee5a32ad78487a3d3afdc0fb8cae19d2c5deb50b7c" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "console_error_panic_hook" version = "0.1.7" @@ -584,6 +613,15 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "fastrand" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" +dependencies = [ + "instant", +] + [[package]] name = "fiat-crypto" version = "0.1.20" @@ -674,6 +712,21 @@ version = "0.3.28" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +[[package]] +name = "futures-lite" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49a9d51ce47660b1e808d3c990b4709f2f415d928835a17dfd16991515c46bce" +dependencies = [ + "fastrand", + "futures-core", + "futures-io", + "memchr", + "parking", + "pin-project-lite", + "waker-fn", +] + [[package]] name = "futures-macro" version = "0.3.28" @@ -1007,6 +1060,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e04e2fd2b8188ea827b32ef11de88377086d690286ab35747ef7f9bf3ccb590" +[[package]] +name = "instant" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a5bbe824c507c5da5956355e86a746d82e0e1464f65d862cc5e71da70e94b2c" +dependencies = [ + "cfg-if", +] + [[package]] name = "itertools" version = "0.10.5" @@ -1375,6 +1437,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "parking" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "14f2252c834a40ed9bb5422029649578e63aa341ac401f74e719dd1afda8394e" + [[package]] name = "paste" version = "1.0.12" @@ -2015,6 +2083,26 @@ dependencies = [ "smoldot", ] +[[package]] +name = "smoldot-light-wasm" +version = "1.0.6" +dependencies = [ + "async-executor", + "async-task", + "event-listener", + "fnv", + "futures-util", + "hashbrown 0.13.2", + "lazy_static", + "log", + "nom", + "pin-project", + "rand", + "slab", + "smoldot", + "smoldot-light", +] + [[package]] name = "snow" version = "0.9.2" @@ -2141,6 +2229,7 @@ dependencies = [ "serde_json", "smoldot", "smoldot-light", + "smoldot-light-wasm", "sp-core-hashing", "subxt-macro", "subxt-metadata", @@ -2462,6 +2551,12 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" +[[package]] +name = "waker-fn" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" + [[package]] name = "want" version = "0.3.0" diff --git a/testing/wasm-tests/tests/wasm.rs b/testing/wasm-tests/tests/wasm.rs index b828d0462c..5027dedc4c 100644 --- a/testing/wasm-tests/tests/wasm.rs +++ b/testing/wasm-tests/tests/wasm.rs @@ -9,6 +9,11 @@ wasm_bindgen_test::wasm_bindgen_test_configure!(run_in_browser); /// Run the tests by `$ wasm-pack test --firefox --headless` +fn init_tracing() { + console_error_panic_hook::set_once(); + tracing_wasm::set_as_global_default(); +} + #[wasm_bindgen_test] async fn wasm_ws_transport_works() { let client = subxt::client::OnlineClient::::from_url("ws://127.0.0.1:9944") @@ -21,10 +26,9 @@ async fn wasm_ws_transport_works() { #[wasm_bindgen_test] async fn light_client_transport_works() { + init_tracing(); - println!("Creating lightclient"); - - let light_client = LightClient::new(include_str!("../../../artifacts/dev_spec.json")).unwrap(); + // let light_client = LightClient::new(include_str!("../../../artifacts/dev_spec.json")).unwrap(); // let client = subxt::client::OnlineClient::::from_rpc_client(Arc::new(light_client)).await.unwrap(); // let chain = client.rpc().system_chain().await.unwrap();