From bbcfa5d8ad56cdc458bacc0d53a9c0430178d044 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 18 Oct 2024 11:23:51 +0200 Subject: [PATCH 1/3] Update to Rust 1.82 --- .github/workflows/ci.yml | 18 +-- .github/workflows/deploy.yml | 10 +- .github/workflows/periodic-cargo-update.yml | 2 +- .../executor/host/tests/hash_algorithms.rs | 4 +- lib/src/executor/host/tests/run.rs | 14 +- wasm-node/rust/src/bindings.rs | 76 ++++----- wasm-node/rust/src/lib.rs | 27 ++-- wasm-node/rust/src/platform.rs | 152 +++++++----------- wasm-node/rust/src/timers.rs | 8 +- 9 files changed, 136 insertions(+), 175 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d8375cf00f..5129f0d2f2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -30,7 +30,7 @@ jobs: test-64bits: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 @@ -39,7 +39,7 @@ jobs: test-32bits: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - run: apt-get update && apt install -y libc6-dev-i386 - uses: actions/checkout@v4 @@ -50,7 +50,7 @@ jobs: wasm-node-check: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - run: rustup target add wasm32-unknown-unknown @@ -66,7 +66,7 @@ jobs: check-features: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 @@ -100,7 +100,7 @@ jobs: check-no-std: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - run: rustup target add thumbv7m-none-eabi @@ -112,7 +112,7 @@ jobs: check-rustdoc-links: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - uses: Swatinem/rust-cache@v2 @@ -121,7 +121,7 @@ jobs: fmt: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: # Checks `rustfmt` formatting - uses: actions/checkout@v4 @@ -135,7 +135,7 @@ jobs: clippy: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 # Since build artifacts are specific to a nightly version, we pin the specific nightly @@ -176,7 +176,7 @@ jobs: wasm-node-versions-match: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - run: apt-get update && apt install -y jq diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index f85716883c..be18345bf5 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -56,7 +56,7 @@ jobs: build-js-doc: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 with: @@ -83,7 +83,7 @@ jobs: build-rust-doc: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 with: @@ -104,7 +104,7 @@ jobs: build-tests-coverage: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - run: apt update && apt install -y jq - run: rustup component add llvm-tools-preview @@ -174,7 +174,7 @@ jobs: npm-publish: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - run: rustup target add wasm32-unknown-unknown @@ -244,7 +244,7 @@ jobs: crates-io-publish: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 - run: cargo publish --dry-run --locked diff --git a/.github/workflows/periodic-cargo-update.yml b/.github/workflows/periodic-cargo-update.yml index 786ffd681d..16eca08b99 100644 --- a/.github/workflows/periodic-cargo-update.yml +++ b/.github/workflows/periodic-cargo-update.yml @@ -9,7 +9,7 @@ jobs: cargo-update: runs-on: ubuntu-latest container: - image: rust:1.81 + image: rust:1.82 steps: - uses: actions/checkout@v4 # Note: `cargo update --workspace` doesn't seem to have any effect. diff --git a/lib/src/executor/host/tests/hash_algorithms.rs b/lib/src/executor/host/tests/hash_algorithms.rs index 505ca74dca..3539282381 100644 --- a/lib/src/executor/host/tests/hash_algorithms.rs +++ b/lib/src/executor/host/tests/hash_algorithms.rs @@ -33,7 +33,7 @@ extern "C" { fn ext_hashing_keccak_256_version_1(ptrsz: i64) -> i32; } -#[no_mangle] +#[unsafe(no_mangle)] extern "C" fn test(_param_ptr: i32, _param_sz: i32) -> i64 { let slice = b"hello world"; let ptrsz = u64::from(slice.len() as u32) << 32 | u64::from(slice.as_ptr() as usize as u32); @@ -77,7 +77,7 @@ macro_rules! gen_test { fn ext_hashing_keccak_256_version_1(ptrsz: i64) -> i32; } - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_param_ptr: i32, _param_sz: i32) -> i64 { let slice = b"hello world"; let ptrsz = u64::from(slice.len() as u32) << 32 | u64::from(slice.as_ptr() as usize as u32); diff --git a/lib/src/executor/host/tests/run.rs b/lib/src/executor/host/tests/run.rs index 8941ab09c1..a2bdc62227 100644 --- a/lib/src/executor/host/tests/run.rs +++ b/lib/src/executor/host/tests/run.rs @@ -92,7 +92,7 @@ fn function_to_run_invalid_params() { fn input_provided_correctly() { /* Source code: - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_param_ptr: i32, _param_sz: i32) -> i64 { let inparam: &[u8] = unsafe { core::slice::from_raw_parts( @@ -299,7 +299,7 @@ fn input_provided_correctly() { fn large_input_provided_correctly() { /* Source code: - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_param_ptr: i32, _param_sz: i32) -> i64 { let inparam: &[u8] = unsafe { core::slice::from_raw_parts( @@ -413,7 +413,7 @@ fn return_value_works() { static OUT: &[u8] = b"hello world"; - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_: i32, _: i32) -> i64 { let ptr = OUT.as_ptr() as usize as u32; let sz = OUT.len() as u32; @@ -482,7 +482,7 @@ fn return_value_works() { fn bad_return_value() { /* Source code: - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_: i32, _: i32) -> i32 { 0 } @@ -546,7 +546,7 @@ fn bad_return_value() { fn returned_ptr_out_of_range() { /* Source code: - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_: i32, _: i32) -> i64 { let ptr = 0xffff_fff0usize as u32; let sz = 5 as u32; @@ -613,7 +613,7 @@ fn returned_ptr_out_of_range() { fn returned_size_out_of_range() { /* Source code: - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_: i32, _: i32) -> i64 { let ptr = 5 as u32; let sz = 0xffff_fff0usize as u32; @@ -683,7 +683,7 @@ fn unresolved_host_function_called() { fn host_function_that_doesnt_exist(); } - #[no_mangle] + #[unsafe(no_mangle)] extern "C" fn test(_: i32, _: i32) -> i64 { unsafe { host_function_that_doesnt_exist() diff --git a/wasm-node/rust/src/bindings.rs b/wasm-node/rust/src/bindings.rs index 961bf5ff49..60eb9320e4 100644 --- a/wasm-node/rust/src/bindings.rs +++ b/wasm-node/rust/src/bindings.rs @@ -53,7 +53,7 @@ use alloc::vec::Vec; #[link(wasm_import_module = "smoldot")] -extern "C" { +unsafe extern "C" { /// Must stop the execution immediately. The message is a UTF-8 string found in the memory of /// the WebAssembly at offset `message_ptr` and with length `message_len`. /// @@ -81,20 +81,20 @@ extern "C" { /// /// Beyond the `panic` function itself, any other FFI function that throws must similarly /// behave like `abort` and prevent any further execution. - pub fn panic(message_ptr: u32, message_len: u32); + pub unsafe fn panic(message_ptr: u32, message_len: u32); /// Called in response to [`add_chain`] once the initialization of the chain is complete. /// /// If `error_msg_ptr` is equal to 0, then the chain initialization is successful. Otherwise, /// `error_msg_ptr` and `error_msg_len` designate a buffer in the memory of the WebAssembly /// virtual machine where a UTF-8 diagnostic error message can be found. - pub fn chain_initialized(chain_id: u32, error_msg_ptr: u32, error_msg_len: u32); + pub safe fn chain_initialized(chain_id: u32, error_msg_ptr: u32, error_msg_len: u32); /// Fills the buffer of the WebAssembly virtual machine with random data, starting at `ptr` /// and for `len` bytes. /// /// This data will be used in order to generate secrets. Do not use a dummy implementation! - pub fn random_get(ptr: u32, len: u32); + pub unsafe fn random_get(ptr: u32, len: u32); /// Returns the system clock in number of microseconds since the UNIX epoch, ignoring leap /// seconds. @@ -103,11 +103,11 @@ extern "C" { /// /// Must never return a negative number. Implementers should be aware that the system clock /// can be negative, and abort execution if that is the case. - pub fn unix_timestamp_us() -> u64; + pub safe fn unix_timestamp_us() -> u64; /// Returns the number of microseconds since an especified point in time. Must never decrease /// over time. - pub fn monotonic_clock_us() -> u64; + pub safe fn monotonic_clock_us() -> u64; /// Copies the entire content of the buffer with the given index to the memory of the /// WebAssembly at offset `target_pointer`. @@ -117,12 +117,12 @@ extern "C" { /// "buffer index" to the buffer it wants to provide. The Rust code then calls the /// [`buffer_size`] and [`buffer_copy`] functions in order to obtain the length and content /// of the buffer. - pub fn buffer_copy(buffer_index: u32, target_pointer: u32); + pub unsafe fn buffer_copy(buffer_index: u32, target_pointer: u32); /// Returns the size (in bytes) of the buffer with the given index. /// /// See the documentation of [`buffer_copy`] for context. - pub fn buffer_size(buffer_index: u32) -> u32; + pub safe fn buffer_size(buffer_index: u32) -> u32; /// The queue of JSON-RPC responses of the given chain is no longer empty. /// @@ -130,7 +130,7 @@ extern "C" { /// of 0. /// /// This function might be called spuriously, however this behavior must not be relied upon. - pub fn json_rpc_responses_non_empty(chain_id: u32); + pub safe fn json_rpc_responses_non_empty(chain_id: u32); /// Client is emitting a log entry. /// @@ -139,13 +139,13 @@ extern "C" { /// /// The log target and message is a UTF-8 string found in the memory of the WebAssembly /// virtual machine at offset `ptr` and with length `len`. - pub fn log(level: u32, target_ptr: u32, target_len: u32, message_ptr: u32, message_len: u32); + pub safe fn log(level: u32, target_ptr: u32, target_len: u32, message_ptr: u32, message_len: u32); /// Called when [`advance_execution`] should be executed again. /// /// This function might be called from within [`advance_execution`], in which case /// [`advance_execution`] should be called again immediately after it returns. - pub fn advance_execution_ready(); + pub safe fn advance_execution_ready(); /// After at least `milliseconds` milliseconds have passed, [`timer_finished`] must be called. /// @@ -159,7 +159,7 @@ extern "C" { /// If `milliseconds` is 0, [`timer_finished`] should be called as soon as possible. /// /// `milliseconds` never contains a negative number, `NaN` or infinite. - pub fn start_timer(milliseconds: f64); + pub safe fn start_timer(milliseconds: f64); /// Must return the host supports connecting to a certain type of address. /// @@ -171,7 +171,7 @@ extern "C" { /// /// Returns a non-zero value if the address is supported. Returns `0` if the address isn't /// supported. - pub fn connection_type_supported(ty: u8) -> u32; + pub safe fn connection_type_supported(ty: u8) -> u32; /// Must initialize a new connection that tries to connect to the given address. /// @@ -180,11 +180,11 @@ extern "C" { /// /// - One `type` byte (see below). /// - Two big-endian bytes representing the port (either TCP or UDP depending on the `type`) - /// to connect to. + /// to connect to. /// - (optional) The 32 bytes SHA-256 hash of the certificate of the remote. /// - An UTF-8-encoded IP address or domain name. Use the `addr_len` parameter to determine - /// its length. When using an IPv4, it is encoded as `a.b.c.d`. When using an IPv6, it is - /// encoded according to RFC5952. + /// its length. When using an IPv4, it is encoded as `a.b.c.d`. When using an IPv6, it is + /// encoded according to RFC5952. /// /// The `type` byte defines the type of connection and whether the optional field is present: /// @@ -220,7 +220,7 @@ extern "C" { /// multiplexing are handled internally by smoldot. Multi-stream connections open and close /// streams over time using [`connection_stream_opened`] and [`stream_reset`], and the /// encryption and multiplexing are handled by the user of these bindings. - pub fn connection_new(id: u32, addr_ptr: u32, addr_len: u32); + pub safe fn connection_new(id: u32, addr_ptr: u32, addr_len: u32); /// Abruptly close a connection previously initialized with [`connection_new`]. /// @@ -235,7 +235,7 @@ extern "C" { /// /// > **Note**: In JavaScript, remember to unregister event handlers before calling for /// > example `WebSocket.close()`. - pub fn reset_connection(id: u32); + pub safe fn reset_connection(id: u32); /// Queues a new outbound substream opening. The [`connection_stream_opened`] function must /// later be called when the substream has been successfully opened. @@ -247,7 +247,7 @@ extern "C" { /// > to open, as this is not supposed to happen. If you need to handle such a /// > situation, either try again opening a substream again or reset the entire /// > connection. - pub fn connection_stream_open(connection_id: u32); + pub safe fn connection_stream_open(connection_id: u32); /// Abruptly closes an existing substream of a multi-stream connection. The substream must /// currently be in the `Open` state. @@ -256,7 +256,7 @@ extern "C" { /// /// This function will only be called for multi-stream connections. The connection must /// currently be in the `Open` state. See the documentation of [`connection_new`] for details. - pub fn connection_stream_reset(connection_id: u32, stream_id: u32); + pub safe fn connection_stream_reset(connection_id: u32, stream_id: u32); /// Queues data on the given stream. /// @@ -280,7 +280,7 @@ extern "C" { /// /// The size of the buffer must not exceed the number of writable bytes of the given stream. /// Use [`stream_writable_bytes`] to notify that more data can be sent on the stream. - pub fn stream_send(connection_id: u32, stream_id: u32, ptr: u32, len: u32); + pub safe fn stream_send(connection_id: u32, stream_id: u32, ptr: u32, len: u32); /// Close the sending side of the given stream of the given connection. /// @@ -295,7 +295,7 @@ extern "C" { /// The connection associated with that stream (and, in the case of a multi-stream connection, /// the stream itself must currently be in the `Open` state. See the documentation of /// [`connection_new`] for details. - pub fn stream_send_close(connection_id: u32, stream_id: u32); + pub safe fn stream_send_close(connection_id: u32, stream_id: u32); /// Called when the Wasm execution enters the context of a certain task. This is useful for /// debugging purposes. @@ -304,13 +304,13 @@ extern "C" { /// /// The name of the task is a UTF-8 string found in the memory of the WebAssembly virtual /// machine at offset `ptr` and with length `len`. - pub fn current_task_entered(ptr: u32, len: u32); + pub safe fn current_task_entered(ptr: u32, len: u32); /// Called when the Wasm execution leave the context of a certain task. This is useful for /// debugging purposes. /// /// Only one task can be currently executing at any time. - pub fn current_task_exit(); + pub safe fn current_task_exit(); } /// See [`stream_send`]. @@ -331,7 +331,7 @@ pub struct StreamSendIoVector { /// /// The client will emit log messages by calling the [`log()`] function, provided the log level is /// inferior or equal to the value of `max_log_level` passed here. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn init(max_log_level: u32) { crate::init(max_log_level); } @@ -342,7 +342,7 @@ pub extern "C" fn init(max_log_level: u32) { /// /// After this function is called or during a call to this function, [`advance_execution_ready`] /// might be called, indicating that [`advance_execution`] should be called again. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn advance_execution() { super::advance_execution() } @@ -377,7 +377,7 @@ pub extern "C" fn advance_execution() { /// called by smoldot. /// It is possible to call [`remove_chain`] while the initialization is still in progress in /// order to cancel it. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn add_chain( chain_spec_buffer_index: u32, database_content_buffer_index: u32, @@ -398,7 +398,7 @@ pub extern "C" fn add_chain( /// subscriptions and cancels all in-progress requests corresponding to that chain. /// /// Can be called on a chain which hasn't finished initializing yet. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn remove_chain(chain_id: u32) { super::remove_chain(chain_id); } @@ -428,7 +428,7 @@ pub extern "C" fn remove_chain(chain_id: u32) { /// - 0 on success. /// - 1 if the chain has too many pending JSON-RPC requests and refuses to queue another one. /// -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn json_rpc_send(text_buffer_index: u32, chain_id: u32) -> u32 { super::json_rpc_send(get_buffer(text_buffer_index), chain_id) } @@ -449,7 +449,7 @@ pub extern "C" fn json_rpc_send(text_buffer_index: u32, chain_id: u32) -> u32 { /// /// After having read the response or notification, use [`json_rpc_responses_pop`] to remove it /// from the queue. You can then call [`json_rpc_responses_peek`] again to read the next response. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn json_rpc_responses_peek(chain_id: u32) -> u32 { super::json_rpc_responses_peek(chain_id) } @@ -471,13 +471,13 @@ pub struct JsonRpcResponseInfo { /// /// It is forbidden to call this function on a chain that hasn't finished initializing yet, or a /// chain that was created with `json_rpc_running` equal to 0. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn json_rpc_responses_pop(chain_id: u32) { super::json_rpc_responses_pop(chain_id); } /// Must be called in response to [`start_timer`] after the given duration has passed. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn timer_finished() { crate::timers::timer_finished(); } @@ -495,7 +495,7 @@ pub extern "C" fn timer_finished() { /// /// The buffer must contain a single 0 byte (indicating WebRTC), followed with the SHA-256 hash of /// the local node's TLS certificate. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn connection_multi_stream_set_handshake_info( connection_id: u32, handshake_ty_buffer_index: u32, @@ -519,7 +519,7 @@ pub extern "C" fn connection_multi_stream_set_handshake_info( /// on which the data was received, as was provided to [`connection_stream_opened`]. /// /// See also [`connection_new`]. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn stream_message(connection_id: u32, stream_id: u32, buffer_index: u32) { crate::platform::stream_message(connection_id, stream_id, get_buffer(buffer_index)); } @@ -534,7 +534,7 @@ pub extern "C" fn stream_message(connection_id: u32, stream_id: u32, buffer_inde /// If `connection_id` is a single-stream connection, then the value of `stream_id` is ignored. /// If `connection_id` is a multi-stream connection, then `stream_id` corresponds to the stream /// on which the data was received, as was provided to [`connection_stream_opened`]. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn stream_writable_bytes(connection_id: u32, stream_id: u32, num_bytes: u32) { crate::platform::stream_writable_bytes(connection_id, stream_id, num_bytes); } @@ -549,7 +549,7 @@ pub extern "C" fn stream_writable_bytes(connection_id: u32, stream_id: u32, num_ /// For the `outbound` parameter, pass `0` if the substream has been opened by the remote, and any /// value other than `0` if the substream has been opened in response to a call to /// [`connection_stream_open`]. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn connection_stream_opened(connection_id: u32, stream_id: u32, outbound: u32) { crate::platform::connection_stream_opened(connection_id, stream_id, outbound); } @@ -566,7 +566,7 @@ pub extern "C" fn connection_stream_opened(connection_id: u32, stream_id: u32, o /// index can be de-assigned and buffer destroyed once this function returns. /// /// See also [`connection_new`]. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn connection_reset(connection_id: u32, buffer_index: u32) { crate::platform::connection_reset(connection_id, get_buffer(buffer_index)); } @@ -587,7 +587,7 @@ pub extern "C" fn connection_reset(connection_id: u32, buffer_index: u32) { /// index can be de-assigned and buffer destroyed once this function returns. /// /// See also [`connection_new`]. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn stream_reset(connection_id: u32, stream_id: u32, buffer_index: u32) { crate::platform::stream_reset(connection_id, stream_id, get_buffer(buffer_index)); } diff --git a/wasm-node/rust/src/lib.rs b/wasm-node/rust/src/lib.rs index 9cf6f18854..f81f5f3bf4 100644 --- a/wasm-node/rust/src/lib.rs +++ b/wasm-node/rust/src/lib.rs @@ -102,14 +102,12 @@ fn add_chain( // updated regularly to account for changes in the implementation. if allocator::total_alloc_bytes() >= usize::MAX - 400 * 1024 * 1024 { client_lock.chains.remove(outer_chain_id); - unsafe { - let error = "Wasm node is running low on memory and will prevent any new chain from being added"; - bindings::chain_initialized( - outer_chain_id_u32, - u32::try_from(error.as_bytes().as_ptr() as usize).unwrap(), - u32::try_from(error.as_bytes().len()).unwrap(), - ); - } + let error = "Wasm node is running low on memory and will prevent any new chain from being added"; + bindings::chain_initialized( + outer_chain_id_u32, + u32::try_from(error.as_bytes().as_ptr() as usize).unwrap(), + u32::try_from(error.as_bytes().len()).unwrap(), + ); return; } @@ -141,14 +139,12 @@ fn add_chain( Ok(c) => c, Err(error) => { client_lock.chains.remove(outer_chain_id); - unsafe { let error = error.to_string(); bindings::chain_initialized( outer_chain_id_u32, u32::try_from(error.as_bytes().as_ptr() as usize).unwrap(), u32::try_from(error.as_bytes().len()).unwrap(), ); - } return; } }; @@ -180,10 +176,7 @@ fn add_chain( *json_rpc_responses_rx = json_rpc_responses; } - unsafe { - bindings::chain_initialized(outer_chain_id_u32, 0, 0); - } - + bindings::chain_initialized(outer_chain_id_u32, 0, 0); }, ); @@ -331,7 +324,7 @@ struct JsonRpcResponsesNonEmptyWaker { impl alloc::task::Wake for JsonRpcResponsesNonEmptyWaker { fn wake(self: Arc) { - unsafe { bindings::json_rpc_responses_non_empty(self.chain_id) } + bindings::json_rpc_responses_non_empty(self.chain_id) } } @@ -350,8 +343,6 @@ fn advance_execution() { runnable.run(); if !TASKS_QUEUE.is_empty() { - unsafe { - bindings::advance_execution_ready(); - } + bindings::advance_execution_ready(); } } diff --git a/wasm-node/rust/src/platform.rs b/wasm-node/rust/src/platform.rs index 3f64c45ab0..b26a1e9cee 100644 --- a/wasm-node/rust/src/platform.rs +++ b/wasm-node/rust/src/platform.rs @@ -33,7 +33,7 @@ use async_lock::Mutex; use core::{ fmt::{self, Write as _}, future, iter, mem, - net::{IpAddr, Ipv4Addr, Ipv6Addr}, + net::IpAddr, ops, pin, str, sync::atomic::{AtomicU32, AtomicU64, Ordering}, task, @@ -87,12 +87,12 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { >; fn now_from_unix_epoch(&self) -> Duration { - let microseconds = unsafe { bindings::unix_timestamp_us() }; + let microseconds = bindings::unix_timestamp_us(); Duration::from_micros(microseconds) } fn now(&self) -> Self::Instant { - let microseconds = unsafe { bindings::monotonic_clock_us() }; + let microseconds = bindings::monotonic_clock_us(); Duration::from_micros(microseconds) } @@ -130,26 +130,21 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { type Output = F::Output; fn poll(self: pin::Pin<&mut Self>, cx: &mut task::Context) -> task::Poll { let this = self.project(); - unsafe { - bindings::current_task_entered( - u32::try_from(this.name.as_bytes().as_ptr() as usize).unwrap(), - u32::try_from(this.name.as_bytes().len()).unwrap(), - ) - } + bindings::current_task_entered( + u32::try_from(this.name.as_bytes().as_ptr() as usize).unwrap(), + u32::try_from(this.name.as_bytes().len()).unwrap(), + ); - let before_polling = unsafe { bindings::monotonic_clock_us() }; + let before_polling = bindings::monotonic_clock_us(); let out = this.future.poll(cx); - let poll_duration = Duration::from_micros( - unsafe { bindings::monotonic_clock_us() } - before_polling, - ); + let poll_duration = + Duration::from_micros(bindings::monotonic_clock_us() - before_polling); TOTAL_CPU_USAGE_US.fetch_add( u64::try_from(poll_duration.as_micros()).unwrap_or(u64::MAX), Ordering::Relaxed, ); - unsafe { - bindings::current_task_exit(); - } + bindings::current_task_exit(); // Print a warning if polling the task takes a long time. // It has been noticed that sometimes in Firefox polling a task takes a 16ms + a @@ -200,9 +195,7 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { let (runnable, task) = async_task::spawn(task, |runnable| { super::TASKS_QUEUE.push(runnable); - unsafe { - bindings::advance_execution_ready(); - } + bindings::advance_execution_ready(); }); task.detach(); @@ -231,15 +224,13 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { let mut key_values = key_values.peekable(); if key_values.peek().is_none() { - unsafe { - bindings::log( - log_level, - u32::try_from(log_target.as_bytes().as_ptr() as usize).unwrap(), - u32::try_from(log_target.as_bytes().len()).unwrap(), - u32::try_from(message.as_bytes().as_ptr() as usize).unwrap(), - u32::try_from(message.as_bytes().len()).unwrap(), - ) - } + bindings::log( + log_level, + u32::try_from(log_target.as_bytes().as_ptr() as usize).unwrap(), + u32::try_from(log_target.as_bytes().len()).unwrap(), + u32::try_from(message.as_bytes().as_ptr() as usize).unwrap(), + u32::try_from(message.as_bytes().len()).unwrap(), + ) } else { let mut message_build = String::with_capacity(128); message_build.push_str(message); @@ -254,15 +245,13 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { let _ = write!(message_build, "{}={}", key, value); } - unsafe { - bindings::log( - log_level, - u32::try_from(log_target.as_bytes().as_ptr() as usize).unwrap(), - u32::try_from(log_target.as_bytes().len()).unwrap(), - u32::try_from(message_build.as_bytes().as_ptr() as usize).unwrap(), - u32::try_from(message_build.as_bytes().len()).unwrap(), - ) - } + bindings::log( + log_level, + u32::try_from(log_target.as_bytes().as_ptr() as usize).unwrap(), + u32::try_from(log_target.as_bytes().len()).unwrap(), + u32::try_from(message_build.as_bytes().as_ptr() as usize).unwrap(), + u32::try_from(message_build.as_bytes().len()).unwrap(), + ) } } @@ -302,7 +291,7 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { smoldot_light::platform::ConnectionType::WebRtcIpv6 => 17, }; - unsafe { bindings::connection_type_supported(ty) != 0 } + bindings::connection_type_supported(ty) != 0 } fn connect_stream( @@ -320,14 +309,14 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { port, } => iter::once(0u8) .chain(port.to_be_bytes()) - .chain(Ipv4Addr::from(ip).to_string().bytes()) + .chain(ip.to_string().bytes()) .collect(), smoldot_light::platform::Address::TcpIp { ip: IpAddr::V6(ip), port, } => iter::once(1u8) .chain(port.to_be_bytes()) - .chain(Ipv6Addr::from(ip).to_string().bytes()) + .chain(ip.to_string().bytes()) .collect(), smoldot_light::platform::Address::TcpDns { hostname, port } => iter::once(2u8) .chain(port.to_be_bytes()) @@ -338,14 +327,14 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { port, } => iter::once(4u8) .chain(port.to_be_bytes()) - .chain(Ipv4Addr::from(ip).to_string().bytes()) + .chain(ip.to_string().bytes()) .collect(), smoldot_light::platform::Address::WebSocketIp { ip: IpAddr::V6(ip), port, } => iter::once(5u8) .chain(port.to_be_bytes()) - .chain(Ipv6Addr::from(ip).to_string().bytes()) + .chain(ip.to_string().bytes()) .collect(), smoldot_light::platform::Address::WebSocketDns { hostname, @@ -372,13 +361,11 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { | smoldot_light::platform::Address::WebSocketDns { .. } => false, }; - unsafe { - bindings::connection_new( - connection_id, - u32::try_from(encoded_address.as_ptr() as usize).unwrap(), - u32::try_from(encoded_address.len()).unwrap(), - ) - } + bindings::connection_new( + connection_id, + u32::try_from(encoded_address.as_ptr() as usize).unwrap(), + u32::try_from(encoded_address.len()).unwrap(), + ); let _prev_value = lock.connections.insert( connection_id, @@ -431,7 +418,7 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { } => iter::once(16u8) .chain(port.to_be_bytes()) .chain(remote_certificate_sha256.iter().copied()) - .chain(Ipv4Addr::from(ip).to_string().bytes()) + .chain(ip.to_string().bytes()) .collect(), smoldot_light::platform::MultiStreamAddress::WebRtc { ip: IpAddr::V6(ip), @@ -440,17 +427,15 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { } => iter::once(17u8) .chain(port.to_be_bytes()) .chain(remote_certificate_sha256.iter().copied()) - .chain(Ipv6Addr::from(ip).to_string().bytes()) + .chain(ip.to_string().bytes()) .collect(), }; - unsafe { - bindings::connection_new( - connection_id, - u32::try_from(encoded_address.as_ptr() as usize).unwrap(), - u32::try_from(encoded_address.len()).unwrap(), - ) - } + bindings::connection_new( + connection_id, + u32::try_from(encoded_address.as_ptr() as usize).unwrap(), + u32::try_from(encoded_address.len()).unwrap(), + ); let _prev_value = lock.connections.insert( connection_id, @@ -580,9 +565,9 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { .inner { ConnectionInner::MultiStreamWebRtc { .. } - | ConnectionInner::MultiStreamUnknownHandshake { .. } => unsafe { - bindings::connection_stream_open(*connection_id) - }, + | ConnectionInner::MultiStreamUnknownHandshake { .. } => { + bindings::connection_stream_open(*connection_id); + } ConnectionInner::Reset { .. } => {} ConnectionInner::SingleStreamMsNoiseYamux { .. } => { unreachable!() @@ -688,7 +673,7 @@ impl smoldot_light::platform::PlatformRef for PlatformRef { Ok(ReadWriteAccess { read_write: read_write::ReadWrite { - now: unsafe { Duration::from_micros(bindings::monotonic_clock_us()) }, + now: Duration::from_micros(bindings::monotonic_clock_us()), incoming_buffer: mem::take(&mut stream.read_buffer), expected_incoming_bytes: Some(0), read_bytes: 0, @@ -774,26 +759,22 @@ impl<'a> Drop for ReadWriteAccess<'a> { // `unwrap()` is ok as there's no way that `buffer.len()` doesn't fit in a `u64`. TOTAL_BYTES_SENT.fetch_add(u64::try_from(total_length).unwrap(), Ordering::Relaxed); - unsafe { - bindings::stream_send( - self.stream.connection_id, - self.stream.stream_id.unwrap_or(0), - u32::try_from(io_vectors.as_ptr() as usize).unwrap(), - u32::try_from(io_vectors.len()).unwrap(), - ); - } + bindings::stream_send( + self.stream.connection_id, + self.stream.stream_id.unwrap_or(0), + u32::try_from(io_vectors.as_ptr() as usize).unwrap(), + u32::try_from(io_vectors.len()).unwrap(), + ); self.read_write.write_buffers.clear(); } if self.read_write.write_bytes_queueable.is_none() && !self.stream.write_closed { if stream_inner.reset.is_none() && self.stream.write_closable { - unsafe { - bindings::stream_send_close( - self.stream.connection_id, - self.stream.stream_id.unwrap_or(0), - ); - } + bindings::stream_send_close( + self.stream.connection_id, + self.stream.stream_id.unwrap_or(0), + ); } self.stream.write_closed = true; @@ -830,9 +811,7 @@ impl Drop for StreamWrapper { let remove_connection = match &mut connection.inner { ConnectionInner::SingleStreamMsNoiseYamux { .. } => { if removed_stream.reset.is_none() { - unsafe { - bindings::reset_connection(self.connection_id); - } + bindings::reset_connection(self.connection_id); } debug_assert!(self.stream_id.is_none()); @@ -847,19 +826,12 @@ impl Drop for StreamWrapper { .. } => { if removed_stream.reset.is_none() { - unsafe { - bindings::connection_stream_reset( - self.connection_id, - self.stream_id.unwrap(), - ) - } + bindings::connection_stream_reset(self.connection_id, self.stream_id.unwrap()); } *connection_handles_alive -= 1; let remove_connection = *connection_handles_alive == 0; if remove_connection { - unsafe { - bindings::reset_connection(self.connection_id); - } + bindings::reset_connection(self.connection_id); } remove_connection } @@ -908,9 +880,7 @@ impl Drop for MultiStreamWrapper { lock.connections.remove(&self.0).unwrap(); } if reset_connection { - unsafe { - bindings::reset_connection(self.0); - } + bindings::reset_connection(self.0); } } } diff --git a/wasm-node/rust/src/timers.rs b/wasm-node/rust/src/timers.rs index 71289f4a28..3d750450d3 100644 --- a/wasm-node/rust/src/timers.rs +++ b/wasm-node/rust/src/timers.rs @@ -47,12 +47,12 @@ pub struct Delay { impl Delay { pub fn new(after: Duration) -> Self { - let now = unsafe { Duration::from_micros(bindings::monotonic_clock_us()) }; + let now = Duration::from_micros(bindings::monotonic_clock_us()); Self::new_inner(now + after, now) } pub fn new_at_monotonic_clock(when: Duration) -> Self { - let now = unsafe { Duration::from_micros(bindings::monotonic_clock_us()) }; + let now = Duration::from_micros(bindings::monotonic_clock_us()); Self::new_inner(when, now) } @@ -200,7 +200,7 @@ fn process_timers() { let mut lock = TIMERS.try_lock().unwrap(); let lock = &mut *lock; - let now = unsafe { Duration::from_micros(bindings::monotonic_clock_us()) }; + let now = Duration::from_micros(bindings::monotonic_clock_us()); // Note that this function can be called spuriously. // For example, `process_timers` can be scheduled twice from two different timers, and the @@ -270,5 +270,5 @@ fn start_timer(duration: Duration) { // Note that ideally `duration` should be rounded up in order to make sure that it is not // truncated, but the precision of an `f64` is so high and the precision of the operating // system generally so low that this is not worth dealing with. - unsafe { bindings::start_timer(duration.as_secs_f64() * 1000.0) } + bindings::start_timer(duration.as_secs_f64() * 1000.0) } From 5e9332956678ce18b3e052a41786ac2a2782d37c Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 18 Oct 2024 11:30:28 +0200 Subject: [PATCH 2/3] Use Box instead of Vec when reading buffer --- wasm-node/rust/src/bindings.rs | 22 ++++++++++++---------- wasm-node/rust/src/lib.rs | 10 +++++----- wasm-node/rust/src/platform.rs | 10 +++++----- 3 files changed, 22 insertions(+), 20 deletions(-) diff --git a/wasm-node/rust/src/bindings.rs b/wasm-node/rust/src/bindings.rs index 60eb9320e4..0e1b28b2d6 100644 --- a/wasm-node/rust/src/bindings.rs +++ b/wasm-node/rust/src/bindings.rs @@ -50,7 +50,7 @@ //! they are treated as unsigned integers by the JavaScript. //! -use alloc::vec::Vec; +use alloc::boxed::Box; #[link(wasm_import_module = "smoldot")] unsafe extern "C" { @@ -139,7 +139,13 @@ unsafe extern "C" { /// /// The log target and message is a UTF-8 string found in the memory of the WebAssembly /// virtual machine at offset `ptr` and with length `len`. - pub safe fn log(level: u32, target_ptr: u32, target_len: u32, message_ptr: u32, message_len: u32); + pub safe fn log( + level: u32, + target_ptr: u32, + target_len: u32, + message_ptr: u32, + message_len: u32, + ); /// Called when [`advance_execution`] should be executed again. /// @@ -592,16 +598,12 @@ pub extern "C" fn stream_reset(connection_id: u32, stream_id: u32, buffer_index: crate::platform::stream_reset(connection_id, stream_id, get_buffer(buffer_index)); } -pub(crate) fn get_buffer(buffer_index: u32) -> Vec { +pub(crate) fn get_buffer(buffer_index: u32) -> Box<[u8]> { unsafe { let len = usize::try_from(buffer_size(buffer_index)).unwrap(); - let mut buffer = Vec::::with_capacity(len); - buffer_copy( - buffer_index, - buffer.spare_capacity_mut().as_mut_ptr() as usize as u32, - ); - buffer.set_len(len); - buffer + let mut buffer = Box::<[u8]>::new_uninit_slice(len); + buffer_copy(buffer_index, buffer.as_mut_ptr() as usize as u32); + buffer.assume_init() } } diff --git a/wasm-node/rust/src/lib.rs b/wasm-node/rust/src/lib.rs index f81f5f3bf4..4fccc99541 100644 --- a/wasm-node/rust/src/lib.rs +++ b/wasm-node/rust/src/lib.rs @@ -52,11 +52,11 @@ fn init(max_log_level: u32) { } fn add_chain( - chain_spec: Vec, - database_content: Vec, + chain_spec: Box<[u8]>, + database_content: Box<[u8]>, json_rpc_max_pending_requests: u32, json_rpc_max_subscriptions: u32, - potential_relay_chains: Vec, + potential_relay_chains: Box<[u8]>, ) -> u32 { let mut client_lock = CLIENT.try_lock().unwrap(); @@ -212,9 +212,9 @@ fn remove_chain(chain_id: u32) { } } -fn json_rpc_send(json_rpc_request: Vec, chain_id: u32) -> u32 { +fn json_rpc_send(json_rpc_request: Box<[u8]>, chain_id: u32) -> u32 { // As mentioned in the documentation, the bytes *must* be valid UTF-8. - let json_rpc_request: String = String::from_utf8(json_rpc_request) + let json_rpc_request: String = String::from_utf8(json_rpc_request.to_vec()) .unwrap_or_else(|_| panic!("non-UTF-8 JSON-RPC request")); let mut client_lock = CLIENT.try_lock().unwrap(); diff --git a/wasm-node/rust/src/platform.rs b/wasm-node/rust/src/platform.rs index b26a1e9cee..ba665b5653 100644 --- a/wasm-node/rust/src/platform.rs +++ b/wasm-node/rust/src/platform.rs @@ -975,7 +975,7 @@ struct Stream { pub(crate) fn connection_multi_stream_set_handshake_info( connection_id: u32, - handshake_ty: Vec, + handshake_ty: Box<[u8]>, ) { let (_, local_tls_certificate_sha256) = nom::sequence::preceded( nom::bytes::streaming::tag::<_, _, nom::error::Error<&[u8]>>(&[0]), @@ -1033,7 +1033,7 @@ pub(crate) fn stream_writable_bytes(connection_id: u32, stream_id: u32, bytes: u stream.something_happened.notify(usize::MAX); } -pub(crate) fn stream_message(connection_id: u32, stream_id: u32, message: Vec) { +pub(crate) fn stream_message(connection_id: u32, stream_id: u32, message: Box<[u8]>) { let mut lock = STATE.try_lock().unwrap(); let connection = lock.connections.get_mut(&connection_id).unwrap(); @@ -1088,7 +1088,7 @@ pub(crate) fn stream_message(connection_id: u32, stream_id: u32, message: Vec) { +pub(crate) fn connection_reset(connection_id: u32, message: Box<[u8]>) { let message = str::from_utf8(&message) .unwrap_or_else(|_| panic!("non-UTF-8 message")) .to_owned(); @@ -1173,7 +1173,7 @@ pub(crate) fn connection_reset(connection_id: u32, message: Vec) { } } -pub(crate) fn stream_reset(connection_id: u32, stream_id: u32, message: Vec) { +pub(crate) fn stream_reset(connection_id: u32, stream_id: u32, message: Box<[u8]>) { let message: String = str::from_utf8(&message) .unwrap_or_else(|_| panic!("non-UTF-8 message")) .to_owned(); From 7961b9df30df0f393655a94fed7ca6945d635ed6 Mon Sep 17 00:00:00 2001 From: Pierre Krieger Date: Fri, 18 Oct 2024 11:33:55 +0200 Subject: [PATCH 3/3] Forgot one version update --- .github/workflows/deploy.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index be18345bf5..824de63e6f 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -217,7 +217,7 @@ jobs: - uses: actions-rs/toolchain@v1 with: # Ideally we don't want to install any toolchain, but the GH action doesn't support this. - toolchain: 1.81 + toolchain: 1.82 profile: minimal - uses: Swatinem/rust-cache@v2 - id: compute-tag # Compute the tag that we might push.