From fbf2eb1b4e45962c8ada0c0da232cba009f0d4d5 Mon Sep 17 00:00:00 2001 From: pgherveou Date: Tue, 3 Sep 2024 22:57:45 +0200 Subject: [PATCH] Test replace packed layout with encode macro --- substrate/frame/revive/src/wasm/runtime.rs | 5 +- .../frame/revive/uapi/src/host/riscv32.rs | 216 +++++++++++++----- 2 files changed, 163 insertions(+), 58 deletions(-) diff --git a/substrate/frame/revive/src/wasm/runtime.rs b/substrate/frame/revive/src/wasm/runtime.rs index aaec065949a8..d6e4d68857c0 100644 --- a/substrate/frame/revive/src/wasm/runtime.rs +++ b/substrate/frame/revive/src/wasm/runtime.rs @@ -1225,7 +1225,7 @@ pub mod env { ) -> Result { log::debug!( target: LOG_TARGET, - "\n===\n\n===\n", + "\n===\ncall(flags: {flags:?}, callee_ptr: {callee_ptr:?}, ref_time_limit: {ref_time_limit:?}, proof_size_limit: {proof_size_limit:?}, deposit_ptr: {deposit_ptr:?}, value_ptr: {value_ptr:?}, input_data_ptr: {input_data_ptr:?}, input_data_len: {input_data_len:?}, output_ptr: {output_ptr:?}, output_len_ptr: {output_len_ptr:?})\n===\n", ); self.call( memory, @@ -1286,6 +1286,9 @@ pub mod env { output_len_ptr: u32, salt_ptr: u32, ) -> Result { + log::debug!( + target: LOG_TARGET, + "\n===\ninstantiate(code_hash_ptr: {code_hash_ptr:?}, ref_time_limit: {ref_time_limit:?}, proof_size_limit: {proof_size_limit:?}, deposit_ptr: {deposit_ptr:?}, value_ptr: {value_ptr:?}, input_data_ptr: {input_data_ptr:?}, input_data_len: {input_data_len:?}, address_ptr: {address_ptr:?}, output_ptr: {output_ptr:?}, output_len_ptr: {output_len_ptr:?}, salt_ptr: {salt_ptr:?})\n===\n"); self.instantiate( memory, code_hash_ptr, diff --git a/substrate/frame/revive/uapi/src/host/riscv32.rs b/substrate/frame/revive/uapi/src/host/riscv32.rs index c8218bb8f737..03849e7e12a9 100644 --- a/substrate/frame/revive/uapi/src/host/riscv32.rs +++ b/substrate/frame/revive/uapi/src/host/riscv32.rs @@ -19,6 +19,80 @@ use crate::{ ReturnFlags, }; +macro_rules! encode { + (@inner $buffer:expr, $cursor:expr,) => {}; + (@size $size:expr, ) => { $size }; + + // Match a u8 variable. + (@inner $buffer:expr, $cursor:expr, $var:expr => u8, $($rest:tt)*) => { + $buffer[$cursor] = $var; + encode!(@inner $buffer, $cursor + 1, $($rest)*); + }; + + // Size of u8 variable. + (@size $size:expr, $var:expr => u8, $($rest:tt)*) => { + encode!(@size $size + 1, $($rest)*) + }; + + // Match a u64 variable. + (@inner $buffer:expr, $cursor:expr, $var:expr => u64, $($rest:tt)*) => { + $buffer[$cursor..$cursor + 8].copy_from_slice(&$var.to_le_bytes()); + encode!(@inner $buffer, $cursor + 8, $($rest)*); + }; + + // Size of u64 variable. + (@size $size:expr, $var:expr => u64, $($rest:tt)*) => { + encode!(@size $size + 8, $($rest)*) + }; + + // Match a u32 variable. + (@inner $buffer:expr, $cursor:expr, $var:expr => u32, $($rest:tt)*) => { + $buffer[$cursor..$cursor + 4].copy_from_slice(&$var.to_le_bytes()); + encode!(@inner $buffer, $cursor + 4, $($rest)*); + }; + + // Size of u32 variable. + (@size $size:expr, $var:expr => u32, $($rest:tt)*) => { + encode!(@size $size + 4, $($rest)*) + }; + + // Match a slice (converted to a pointer) + (@inner $buffer:expr, $cursor:expr, $var:expr => &[u8], $($rest:tt)*) => { + let ptr = $var.as_ptr() as usize; + $buffer[$cursor..$cursor + core::mem::size_of::()].copy_from_slice(&ptr.to_le_bytes()); + encode!(@inner $buffer, $cursor + core::mem::size_of::(), $($rest)*); + }; + + // Size of a slice (converted to a pointer). + (@size $size:expr, $var:expr => &[u8], $($rest:tt)*) => { + encode!(@size $size + core::mem::size_of::(), $($rest)*) + }; + + // Match a pointer + (@inner $buffer:expr, $cursor:expr, $var:expr => ptr, $($rest:tt)*) => { + let ptr = $var as usize; + $buffer[$cursor..$cursor + core::mem::size_of::()].copy_from_slice(&ptr.to_le_bytes()); + encode!(@inner $buffer, $cursor + core::mem::size_of::(), $($rest)*); + }; + + // Size of a pointer + (@size $size:expr, $var:expr => ptr, $($rest:tt)*) => { + encode!(@size $size + core::mem::size_of::(), $($rest)*) + }; + + // Entry point, with the buffer and it's size. + ($buffer:ident, $size:expr, $($rest:tt)*) => { + let mut $buffer = [0u8; $size]; + encode!(@inner $buffer, 0, $($rest)*); + }; + + // Entry point + // e.g encode!(buffer, var1: u32, var2: u64, ); + ($buffer: ident, $($rest:tt)*) => { + encode!($buffer, encode!(@size 0, $($rest)*), $($rest)*); + }; +} + mod sys { use crate::ReturnCode; @@ -210,36 +284,50 @@ impl HostFn for HostFnImpl { }; let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let deposit_limit_ptr = ptr_or_sentinel(&deposit_limit); - #[repr(packed)] - #[allow(dead_code)] - struct Args { - code_hash: *const u8, - ref_time_limit: u64, - proof_size_limit: u64, - deposit_limit: *const u8, - value: *const u8, - input: *const u8, - input_len: u32, - address: *const u8, - output: *mut u8, - output_len: *mut u32, - salt: *const u8, - } - let args = Args { - code_hash: code_hash.as_ptr(), - ref_time_limit, - proof_size_limit, - deposit_limit: deposit_limit_ptr, - value: value.as_ptr(), - input: input.as_ptr(), - input_len: input.len() as _, - address, - output: output_ptr, - output_len: &mut output_len as *mut _, - salt: salt.as_ptr(), - }; - - let ret_code = { unsafe { sys::instantiate(&args as *const Args as *const _) } }; + //#[repr(packed)] + //#[allow(dead_code)] + //struct Args { + // code_hash: *const u8, + // ref_time_limit: u64, + // proof_size_limit: u64, + // deposit_limit: *const u8, + // value: *const u8, + // input: *const u8, + // input_len: u32, + // address: *const u8, + // output: *mut u8, + // output_len: *mut u32, + // salt: *const u8, + //} + //let args = Args { + // code_hash: code_hash.as_ptr(), + // ref_time_limit, + // proof_size_limit, + // deposit_limit: deposit_limit_ptr, + // value: value.as_ptr(), + // input: input.as_ptr(), + // input_len: input.len() as _, + // address, + // output: output_ptr, + // output_len: &mut output_len as *mut _, + // salt: salt.as_ptr(), + //}; + + encode!( + args, + code_hash => &[u8], + ref_time_limit => u64, + proof_size_limit => u64, + ptr_or_sentinel(&deposit_limit) => ptr, + value => &[u8], + input => &[u8], + input.len() as u32 => u32, + address => ptr, + output_ptr => ptr, + (&mut output_len as *mut _) => ptr, + salt => &[u8], + ); + let ret_code = { unsafe { sys::instantiate(args.as_ptr()) } }; if let Some(ref mut output) = output { extract_from_slice(output, output_len as usize); @@ -260,34 +348,48 @@ impl HostFn for HostFnImpl { ) -> Result { let (output_ptr, mut output_len) = ptr_len_or_sentinel(&mut output); let deposit_limit_ptr = ptr_or_sentinel(&deposit_limit); - #[repr(packed)] - #[allow(dead_code)] - struct Args { - flags: u32, - callee: *const u8, - ref_time_limit: u64, - proof_size_limit: u64, - deposit_limit: *const u8, - value: *const u8, - input: *const u8, - input_len: u32, - output: *mut u8, - output_len: *mut u32, - } - let args = Args { - flags: flags.bits(), - callee: callee.as_ptr(), - ref_time_limit, - proof_size_limit, - deposit_limit: deposit_limit_ptr, - value: value.as_ptr(), - input: input.as_ptr(), - input_len: input.len() as _, - output: output_ptr, - output_len: &mut output_len as *mut _, - }; + //#[repr(packed)] + //#[allow(dead_code)] + //struct Args { + // flags: u32, + // callee: *const u8, + // ref_time_limit: u64, + // proof_size_limit: u64, + // deposit_limit: *const u8, + // value: *const u8, + // input: *const u8, + // input_len: u32, + // output: *mut u8, + // output_len: *mut u32, + //} + //let args = Args { + // flags: flags.bits(), + // callee: callee.as_ptr(), + // ref_time_limit, + // proof_size_limit, + // deposit_limit: deposit_limit_ptr, + // value: value.as_ptr(), + // input: input.as_ptr(), + // input_len: input.len() as _, + // output: output_ptr, + // output_len: &mut output_len as *mut _, + //}; + + encode!( + args, + flags.bits() => u32, + callee => &[u8], + ref_time_limit => u64, + proof_size_limit => u64, + deposit_limit_ptr => ptr, + value => &[u8], + input => &[u8], + input.len() as u32 => u32, + output_ptr => ptr, + (&mut output_len as *mut _) => ptr, + ); - let ret_code = { unsafe { sys::call(&args as *const Args as *const _) } }; + let ret_code = { unsafe { sys::call(args.as_ptr()) } }; if let Some(ref mut output) = output { extract_from_slice(output, output_len as usize);