Skip to content

Commit 363b311

Browse files
committed
feat: improve state copying between host and WASM contracts
- Remove 3 unnecessary WrappedState .clone() calls in contract.rs; write() only needs AsRef<[u8]>, no ownership transfer required - Add init_buf_with_capacity() to allocate WASM buffers by size without needing the data upfront - Use bincode::serialize_into to write RelatedContracts and UpdateData directly into WASM memory, eliminating intermediate Vec allocations - Fix pre-existing clippy warnings in test code (wildcard_enum_match_arm, assertions_on_constants) Depends on freenet/freenet-stdlib#62 for the std::io::Write impl on BufferMut.
1 parent 79d4827 commit 363b311

8 files changed

Lines changed: 51 additions & 27 deletions

File tree

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ winapi = "0.3"
134134
zip = { version = "8", default-features = false, features = ["deflate", "time"] }
135135

136136
# Freenet
137-
freenet-stdlib = "0.3.2"
137+
freenet-stdlib = { git = "https://github.com/freenet/freenet-stdlib", branch = "feat/improve-state-copying" }
138138

139139
[profile.dev.package."*"]
140140
opt-level = 3

crates/core/src/operations/get.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3382,6 +3382,7 @@ mod messages {
33823382
}
33833383

33843384
#[cfg(test)]
3385+
#[allow(clippy::wildcard_enum_match_arm)]
33853386
mod tests {
33863387
use super::*;
33873388
use crate::message::Transaction;

crates/core/src/operations/put.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2053,6 +2053,7 @@ mod messages {
20532053
}
20542054

20552055
#[cfg(test)]
2056+
#[allow(clippy::wildcard_enum_match_arm)]
20562057
mod tests {
20572058
use super::*;
20582059
use crate::message::Transaction;

crates/core/src/operations/update.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2444,6 +2444,7 @@ pub enum UpdateState {
24442444
}
24452445

24462446
#[cfg(test)]
2447+
#[allow(clippy::wildcard_enum_match_arm)]
24472448
mod tests {
24482449
use super::*;
24492450
use crate::operations::test_utils::make_contract_key;

crates/core/src/transport/packet_data.rs

Lines changed: 19 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -585,13 +585,16 @@ mod packet_type_discrimination_tests {
585585
// the IPv6 minimum MTU (1280), which is the most restrictive common path.
586586
const UDP_HEADER: usize = 8;
587587
const IPV4_HEADER: usize = 20;
588-
assert!(
589-
MAX_PACKET_SIZE + UDP_HEADER + IPV4_HEADER <= 1280,
590-
"MAX_PACKET_SIZE {} would cause IP fragmentation on IPv6 minimum MTU paths \
591-
(total {} > 1280)",
592-
MAX_PACKET_SIZE,
593-
MAX_PACKET_SIZE + UDP_HEADER + IPV4_HEADER,
594-
);
588+
#[allow(clippy::assertions_on_constants)]
589+
{
590+
assert!(
591+
MAX_PACKET_SIZE + UDP_HEADER + IPV4_HEADER <= 1280,
592+
"MAX_PACKET_SIZE {} would cause IP fragmentation on IPv6 minimum MTU paths \
593+
(total {} > 1280)",
594+
MAX_PACKET_SIZE,
595+
MAX_PACKET_SIZE + UDP_HEADER + IPV4_HEADER,
596+
);
597+
}
595598
}
596599

597600
#[test]
@@ -600,12 +603,15 @@ mod packet_type_discrimination_tests {
600603
// Verify that MAX_RECV_PACKET_SIZE can hold these and that PacketData
601604
// can be constructed at the receive buffer size.
602605
const OLD_MAX_PACKET_SIZE: usize = 1492;
603-
assert!(
604-
OLD_MAX_PACKET_SIZE <= MAX_RECV_PACKET_SIZE,
605-
"Receive buffer ({}) must accommodate old peer packets ({})",
606-
MAX_RECV_PACKET_SIZE,
607-
OLD_MAX_PACKET_SIZE,
608-
);
606+
#[allow(clippy::assertions_on_constants)]
607+
{
608+
assert!(
609+
OLD_MAX_PACKET_SIZE <= MAX_RECV_PACKET_SIZE,
610+
"Receive buffer ({}) must accommodate old peer packets ({})",
611+
MAX_RECV_PACKET_SIZE,
612+
OLD_MAX_PACKET_SIZE,
613+
);
614+
}
609615

610616
// Verify PacketData can be constructed from old-size received data.
611617
// In production, recv_from fills a [0u8; MAX_RECV_PACKET_SIZE] buffer,

crates/core/src/wasm_runtime/contract.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,9 +96,9 @@ impl ContractRuntimeInterface for super::Runtime {
9696
state_buf.ptr()
9797
};
9898
let related_buf_ptr = {
99-
let serialized = bincode::serialize(related)?;
100-
let mut related_buf = self.init_buf(&running.handle, &serialized)?;
101-
related_buf.write(serialized)?;
99+
let size = bincode::serialized_size(related)? as usize;
100+
let mut related_buf = self.init_buf_with_capacity(&running.handle, size)?;
101+
bincode::serialize_into(&mut related_buf, related)?;
102102
related_buf.ptr()
103103
};
104104

@@ -147,13 +147,13 @@ impl ContractRuntimeInterface for super::Runtime {
147147
};
148148
let state_buf_ptr = {
149149
let mut state_buf = self.init_buf(&running.handle, state)?;
150-
state_buf.write(state.clone())?;
150+
state_buf.write(state)?;
151151
state_buf.ptr()
152152
};
153153
let update_data_buf_ptr = {
154-
let serialized = bincode::serialize(update_data)?;
155-
let mut update_data_buf = self.init_buf(&running.handle, &serialized)?;
156-
update_data_buf.write(serialized)?;
154+
let size = bincode::serialized_size(update_data)? as usize;
155+
let mut update_data_buf = self.init_buf_with_capacity(&running.handle, size)?;
156+
bincode::serialize_into(&mut update_data_buf, update_data)?;
157157
update_data_buf.ptr()
158158
};
159159

@@ -200,7 +200,7 @@ impl ContractRuntimeInterface for super::Runtime {
200200
};
201201
let state_buf_ptr = {
202202
let mut state_buf = self.init_buf(&running.handle, state)?;
203-
state_buf.write(state.clone())?;
203+
state_buf.write(state)?;
204204
state_buf.ptr()
205205
};
206206

@@ -247,7 +247,7 @@ impl ContractRuntimeInterface for super::Runtime {
247247
};
248248
let state_buf_ptr = {
249249
let mut state_buf = self.init_buf(&running.handle, state)?;
250-
state_buf.write(state.clone())?;
250+
state_buf.write(state)?;
251251
state_buf.ptr()
252252
};
253253
let summary_buf_ptr = {

crates/core/src/wasm_runtime/runtime.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,23 @@ impl Runtime {
316316
}
317317
}
318318

319+
pub(super) fn init_buf_with_capacity(
320+
&mut self,
321+
handle: &InstanceHandle,
322+
capacity: usize,
323+
) -> RuntimeResult<BufferMut<'_>> {
324+
let builder_ptr = self.engine.initiate_buffer(handle, capacity as u32)?;
325+
let linear_mem = self.linear_mem(handle)?;
326+
// SAFETY: `builder_ptr` is returned by the WASM allocator and points to a valid
327+
// `BufferBuilder` within the instance's linear memory described by `linear_mem`.
328+
unsafe {
329+
Ok(BufferMut::from_ptr(
330+
builder_ptr as *mut BufferBuilder,
331+
linear_mem,
332+
))
333+
}
334+
}
335+
319336
pub(super) fn linear_mem(&mut self, handle: &InstanceHandle) -> RuntimeResult<WasmLinearMem> {
320337
let (ptr, size) = self.engine.memory_info(handle)?;
321338
// SAFETY: `ptr` and `size` come from the engine's live memory export for this

0 commit comments

Comments
 (0)