Skip to content

Commit 80d0964

Browse files
committed
Fix data clone, and additional comments
1 parent bc21d01 commit 80d0964

File tree

1 file changed

+68
-59
lines changed

1 file changed

+68
-59
lines changed

substrate/frame/revive/src/wasm/runtime.rs

+68-59
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,6 @@ type CallOf<T> = <T as frame_system::Config>::RuntimeCall;
4646
/// The maximum nesting depth a contract can use when encoding types.
4747
const MAX_DECODE_NESTING: u32 = 256;
4848

49-
enum StorageValue {
50-
Memory { ptr: u32, len: u32 },
51-
Value(Vec<u8>),
52-
}
53-
enum StorageReadMode {
54-
ErrorIfMissing,
55-
ZeroIfMissing,
56-
}
5749
/// Abstraction over the memory access within syscalls.
5850
///
5951
/// The reason for this abstraction is that we run syscalls on the host machine when
@@ -614,6 +606,23 @@ fn extract_hi_lo(reg: u64) -> (u32, u32) {
614606
((reg >> 32) as u32, reg as u32)
615607
}
616608

609+
/// Represents different forms of storage values for operations.
610+
enum StorageValue {
611+
/// Used for variable-length values in traditional storage functions.
612+
Memory { ptr: u32, len: u32 },
613+
/// Used to implement Ethereum SSTORE-like semantics for fixed-size (256-bit) key and values.
614+
Value(Vec<u8>),
615+
}
616+
617+
/// Determines behavior when a key doesn't exist during storage read operations.
618+
enum StorageReadMode {
619+
/// Return KeyNotFound error code when the key doesn't exist.
620+
/// Used in traditional variable-length storage functions.
621+
ErrorIfMissing,
622+
/// Write zeros to the output buffer when the key doesn't exist.
623+
/// Used to implement Ethereum SLOAD-like semantics for fixed-size (256-bit) key and output.
624+
ZeroIfMissing,
625+
}
617626
/// Can only be used for one call.
618627
pub struct Runtime<'a, E: Ext, M: ?Sized> {
619628
ext: &'a mut E,
@@ -891,9 +900,9 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
891900
}
892901
};
893902

894-
let (value_len, _) = match &value {
895-
StorageValue::Memory { ptr: _, len } => (*len, None),
896-
StorageValue::Value(data) => (data.len() as u32, Some(data.clone())),
903+
let value_len = match &value {
904+
StorageValue::Memory { ptr: _, len } => *len,
905+
StorageValue::Value(data) => data.len() as u32,
897906
};
898907

899908
let max_size = self.ext.max_value_size();
@@ -904,15 +913,15 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
904913

905914
let key = self.decode_key(memory, key_ptr, key_len)?;
906915

907-
let value_data = match value {
916+
let value = match value {
908917
StorageValue::Memory { ptr, len } => Some(memory.read(ptr, len)?),
909918
StorageValue::Value(data) => Some(data),
910919
};
911920

912921
let write_outcome = if transient {
913-
self.ext.set_transient_storage(&key, value_data, false)?
922+
self.ext.set_transient_storage(&key, value, false)?
914923
} else {
915-
self.ext.set_storage(&key, value_data, false)?
924+
self.ext.set_storage(&key, value, false)?
916925
};
917926

918927
self.adjust_gas(charged, costs(value_len, write_outcome.old_len()));
@@ -977,7 +986,7 @@ impl<'a, E: Ext, M: ?Sized + Memory<E::T>> Runtime<'a, E, M> {
977986
// For fixed-size operations use write_fixed_sandbox_output
978987
if out_len_ptr == SENTINEL {
979988
let mut fixed_output = [0u8; 32];
980-
let len = std::cmp::min(value.len(), 32);
989+
let len = core::cmp::min(value.len(), 32);
981990
fixed_output[..len].copy_from_slice(&value[..len]);
982991

983992
self.write_fixed_sandbox_output(
@@ -1289,6 +1298,27 @@ pub mod env {
12891298
)
12901299
}
12911300

1301+
/// Sets the storage at a fixed 256-bit key with a fixed 256-bit value.
1302+
/// See [`pallet_revive_uapi::HostFn::set_storage_or_clear`].
1303+
#[stable]
1304+
#[mutating]
1305+
fn set_storage_or_clear(
1306+
&mut self,
1307+
memory: &mut M,
1308+
flags: u32,
1309+
key_ptr: u32,
1310+
value_ptr: u32,
1311+
) -> Result<u32, TrapReason> {
1312+
let _ = Self::is_transient(flags)?;
1313+
let value = memory.read_array::<32>(value_ptr)?;
1314+
1315+
if value.iter().all(|&b| b == 0) {
1316+
self.clear_storage(memory, flags, key_ptr, SENTINEL)
1317+
} else {
1318+
self.set_storage(memory, flags, key_ptr, SENTINEL, StorageValue::Value(value.to_vec()))
1319+
}
1320+
}
1321+
12921322
/// Retrieve the value under the given key from storage.
12931323
/// See [`pallet_revive_uapi::HostFn::get_storage`]
12941324
#[stable]
@@ -1312,6 +1342,29 @@ pub mod env {
13121342
)
13131343
}
13141344

1345+
/// Reads the storage at a fixed 256-bit key and writes back a fixed 256-bit value.
1346+
/// See [`pallet_revive_uapi::HostFn::get_storage_or_zero`].
1347+
#[stable]
1348+
fn get_storage_or_zero(
1349+
&mut self,
1350+
memory: &mut M,
1351+
flags: u32,
1352+
key_ptr: u32,
1353+
out_ptr: u32,
1354+
) -> Result<(), TrapReason> {
1355+
let _ = self.get_storage(
1356+
memory,
1357+
flags,
1358+
key_ptr,
1359+
SENTINEL,
1360+
out_ptr,
1361+
SENTINEL,
1362+
StorageReadMode::ZeroIfMissing,
1363+
)?;
1364+
1365+
Ok(())
1366+
}
1367+
13151368
/// Make a call to another contract.
13161369
/// See [`pallet_revive_uapi::HostFn::call`].
13171370
#[stable]
@@ -1888,50 +1941,6 @@ pub mod env {
18881941
Ok(self.ext.gas_meter().gas_left().ref_time())
18891942
}
18901943

1891-
/// Sets the storage at a fixed 256-bit key with a fixed 256-bit value.
1892-
/// See [`pallet_revive_uapi::HostFn::set_storage_or_clear`].
1893-
#[stable]
1894-
#[mutating]
1895-
fn set_storage_or_clear(
1896-
&mut self,
1897-
memory: &mut M,
1898-
flags: u32,
1899-
key_ptr: u32,
1900-
value_ptr: u32,
1901-
) -> Result<u32, TrapReason> {
1902-
let _ = Self::is_transient(flags)?;
1903-
let value = memory.read_array::<32>(value_ptr)?;
1904-
1905-
if value.iter().all(|&b| b == 0) {
1906-
self.clear_storage(memory, flags, key_ptr, SENTINEL)
1907-
} else {
1908-
self.set_storage(memory, flags, key_ptr, SENTINEL, StorageValue::Value(value.to_vec()))
1909-
}
1910-
}
1911-
1912-
/// Reads the storage at a fixed 256-bit key and writes back a fixed 256-bit value.
1913-
/// See [`pallet_revive_uapi::HostFn::get_storage_or_zero`].
1914-
#[stable]
1915-
fn get_storage_or_zero(
1916-
&mut self,
1917-
memory: &mut M,
1918-
flags: u32,
1919-
key_ptr: u32,
1920-
out_ptr: u32,
1921-
) -> Result<(), TrapReason> {
1922-
let _ = self.get_storage(
1923-
memory,
1924-
flags,
1925-
key_ptr,
1926-
SENTINEL,
1927-
out_ptr,
1928-
SENTINEL,
1929-
StorageReadMode::ZeroIfMissing,
1930-
)?;
1931-
1932-
Ok(())
1933-
}
1934-
19351944
/// Call into the chain extension provided by the chain if any.
19361945
/// See [`pallet_revive_uapi::HostFn::call_chain_extension`].
19371946
fn call_chain_extension(

0 commit comments

Comments
 (0)