Skip to content

Commit

Permalink
apply review suggestions
Browse files Browse the repository at this point in the history
  • Loading branch information
iFrostizz committed Apr 24, 2024
1 parent cd9313a commit df3b46d
Show file tree
Hide file tree
Showing 12 changed files with 59 additions and 49 deletions.
1 change: 1 addition & 0 deletions x/programs/cmd/simulator/cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ func NewRootCmd() *cobra.Command {
// initialize simulator vm
err := s.Init()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}

Expand Down
4 changes: 2 additions & 2 deletions x/programs/cmd/simulator/vm/actions/program_execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ func WriteParams(m *program.Memory, p []CallParam) ([]uint32, error) {
case uint32:
params = append(params, v)
default:
ptr, err := argumentToSmartPtr(v, m)
ptr, err := writeToMem(v, m)
if err != nil {
return nil, err
}
Expand All @@ -224,7 +224,7 @@ func serializeParameter(obj interface{}) ([]byte, error) {
}

// Serialize the parameter and create a smart ptr
func argumentToSmartPtr(obj interface{}, memory *program.Memory) (uint32, error) {
func writeToMem(obj interface{}, memory *program.Memory) (uint32, error) {
bytes, err := serializeParameter(obj)
if err != nil {
return 0, err
Expand Down
14 changes: 7 additions & 7 deletions x/programs/examples/counter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ func TestCounterProgram(t *testing.T) {
require.NoError(err)

// write alice's key to stack and get pointer
alicePtr, err := argumentToSmartPtr(alicePublicKey, mem)
alicePtr, err := writeToMem(alicePublicKey, mem)
require.NoError(err)

// create counter for alice on program 1
Expand Down Expand Up @@ -115,7 +115,7 @@ func TestCounterProgram(t *testing.T) {
require.NoError(err)

// write alice's key to stack and get pointer
alicePtr2, err := argumentToSmartPtr(alicePublicKey, mem2)
alicePtr2, err := writeToMem(alicePublicKey, mem2)
require.NoError(err)

callContext1 := program.Context{ProgramID: programID}
Expand All @@ -128,7 +128,7 @@ func TestCounterProgram(t *testing.T) {

// increment alice's counter on program 2 by 10
incAmount := int64(10)
incAmountPtr, err := argumentToSmartPtr(incAmount, mem2)
incAmountPtr, err := writeToMem(incAmount, mem2)
require.NoError(err)
result, err = rt2.Call(ctx, "inc", callContext2, alicePtr2, incAmountPtr)
require.NoError(err)
Expand All @@ -146,7 +146,7 @@ func TestCounterProgram(t *testing.T) {
require.NoError(err)

// increment alice's counter on program 1
onePtr, err := argumentToSmartPtr(int64(1), mem)
onePtr, err := writeToMem(int64(1), mem)
require.NoError(err)
result, err = rt.Call(ctx, "inc", callContext1, alicePtr, onePtr)
require.NoError(err)
Expand All @@ -160,15 +160,15 @@ func TestCounterProgram(t *testing.T) {
)

// write program id 2 to stack of program 1
target, err := argumentToSmartPtr(programID2, mem)
target, err := writeToMem(programID2, mem)
require.NoError(err)

maxUnitsProgramToProgram := int64(10000)
maxUnitsProgramToProgramPtr, err := argumentToSmartPtr(maxUnitsProgramToProgram, mem)
maxUnitsProgramToProgramPtr, err := writeToMem(maxUnitsProgramToProgram, mem)
require.NoError(err)

// increment alice's counter on program 2
fivePtr, err := argumentToSmartPtr(int64(5), mem)
fivePtr, err := writeToMem(int64(5), mem)
require.NoError(err)
result, err = rt.Call(ctx, "inc_external", callContext1, target, maxUnitsProgramToProgramPtr, alicePtr, fivePtr)
require.NoError(err)
Expand Down
12 changes: 6 additions & 6 deletions x/programs/examples/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ func (t *Token) Run(ctx context.Context) error {
}

// write alice's key to stack and get pointer
alicePtr, err := argumentToSmartPtr(alicePublicKey, mem)
alicePtr, err := writeToMem(alicePublicKey, mem)
if err != nil {
return err
}
Expand All @@ -146,7 +146,7 @@ func (t *Token) Run(ctx context.Context) error {
}

// write bob's key to stack and get pointer
bobPtr, err := argumentToSmartPtr(bobPublicKey, mem)
bobPtr, err := writeToMem(bobPublicKey, mem)
if err != nil {
return err
}
Expand All @@ -162,7 +162,7 @@ func (t *Token) Run(ctx context.Context) error {

// mint 100 tokens to alice
mintAlice := int64(1000)
mintAlicePtr, err := argumentToSmartPtr(mintAlice, mem)
mintAlicePtr, err := writeToMem(mintAlice, mem)
if err != nil {
return err
}
Expand Down Expand Up @@ -195,7 +195,7 @@ func (t *Token) Run(ctx context.Context) error {

// transfer 50 from alice to bob
transferToBob := int64(50)
transferToBobPtr, err := argumentToSmartPtr(transferToBob, mem)
transferToBobPtr, err := writeToMem(transferToBob, mem)
if err != nil {
return err
}
Expand All @@ -208,7 +208,7 @@ func (t *Token) Run(ctx context.Context) error {
zap.Int64("to bob", transferToBob),
)

onePtr, err := argumentToSmartPtr(int64(1), mem)
onePtr, err := writeToMem(int64(1), mem)
if err != nil {
return err
}
Expand Down Expand Up @@ -259,7 +259,7 @@ func (t *Token) Run(ctx context.Context) error {
},
}

mintersPtr, err := argumentToSmartPtr(minters, mem)
mintersPtr, err := writeToMem(minters, mem)
if err != nil {
return err
}
Expand Down
4 changes: 2 additions & 2 deletions x/programs/examples/token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,12 +54,12 @@ func TestTokenProgram(t *testing.T) {
require.NoError(err)

// write alice's key to stack and get pointer
alicePtr, err := argumentToSmartPtr(alicePublicKey, mem)
alicePtr, err := writeToMem(alicePublicKey, mem)
require.NoError(err)

// mint 100 tokens to alice
mintAlice := int64(1000)
mintAlicePtr, err := argumentToSmartPtr(mintAlice, mem)
mintAlicePtr, err := writeToMem(mintAlice, mem)
require.NoError(err)

_, err = rt.Call(ctx, "mint_to", callContext, alicePtr, mintAlicePtr)
Expand Down
2 changes: 1 addition & 1 deletion x/programs/examples/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func newKey() (ed25519.PublicKey, error) {
}

// Serialize the parameter and create a smart ptr
func argumentToSmartPtr(obj interface{}, memory *program.Memory) (uint32, error) {
func writeToMem(obj interface{}, memory *program.Memory) (uint32, error) {
bytes, err := borsh.Serialize(obj)
if err != nil {
return 0, err
Expand Down
4 changes: 2 additions & 2 deletions x/programs/program/function.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ func (f *Func) Call(context Context, params ...uint32) ([]int64, error) {
if err != nil {
return nil, err
}
contextPtr, err := argumentToSmartPtr(context, mem)
contextPtr, err := writeToMem(context, mem)
if err != nil {
return nil, err
}
Expand All @@ -64,7 +64,7 @@ func (f *Func) Call(context Context, params ...uint32) ([]int64, error) {
}
}

func argumentToSmartPtr(obj interface{}, memory *Memory) (uint32, error) {
func writeToMem(obj interface{}, memory *Memory) (uint32, error) {
bytes, err := borsh.Serialize(obj)
if err != nil {
return 0, err
Expand Down
46 changes: 26 additions & 20 deletions x/programs/rust/wasmlanche-sdk/src/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ impl From<Pointer> for *mut u8 {

/// `HostPtr` is an i64 where the first 4 bytes represent the length of the bytes
/// and the following 4 bytes represent a pointer to WASM memeory where the bytes are stored.
#[deprecated]
pub type HostPtr = i64;

thread_local! {
Expand Down Expand Up @@ -74,20 +75,17 @@ where
{
match into_bytes(ptr) {
Some(bytes) => from_slice::<V>(&bytes).map_err(|_| StateError::Deserialization),
None => Err(StateError::InvalidBytes),
None => Err(StateError::InvalidPointer),
}
}

/// Reconstructs the vec from the pointer with the length given by the store
/// `host_ptr` is encoded using Big Endian as an i64.
#[must_use]
fn into_bytes(ptr: HostPtr) -> Option<Vec<u8>> {
if let Some(len) = GLOBAL_STORE.with_borrow_mut(|s| s.remove(&(ptr as *const u8))) {
let ptr = ptr as *mut u8;
Some(unsafe { std::vec::Vec::from_raw_parts(ptr, len, len) })
} else {
None
}
GLOBAL_STORE
.with_borrow_mut(|s| s.remove(&(ptr as *const u8)))
.map(|len| unsafe { std::vec::Vec::from_raw_parts(ptr as *mut u8, len, len) })
}

/* memory functions ------------------------------------------- */
Expand All @@ -98,28 +96,20 @@ fn into_bytes(ptr: HostPtr) -> Option<Vec<u8>> {
#[no_mangle]
pub extern "C" fn alloc(len: usize) -> *mut u8 {
assert!(len > 0, "cannot allocate 0 sized data");
// from https://doc.rust-lang.org/1.77.2/src/alloc/raw_vec.rs.html#547-562
// can only fail if `len > isize::MAX` for u8
let layout = Layout::array::<u8>(len).expect("capacity overflow");
// take a mutable pointer to the layout
let ptr = unsafe { std::alloc::alloc_zeroed(layout) };
let ptr = unsafe { std::alloc::alloc(layout) };
if ptr as *const _ == std::ptr::null() {
std::alloc::handle_alloc_error(layout);
}
// keep track of the pointer and the length of the allocated data
GLOBAL_STORE.with_borrow_mut(|s| s.insert(ptr, len));
// return the pointer so the runtime
// can write data at this offset
ptr
}

/// # Safety
/// `ptr` must be a pointer to a block of memory.
///
/// deallocates the memory block at `ptr` with a given `capacity`.
#[no_mangle]
pub unsafe extern "C" fn dealloc(ptr: *mut u8, capacity: usize) {
// always deallocate the full capacity, initialize vs uninitialized memory is irrelevant here
let data = Vec::from_raw_parts(ptr, capacity, capacity);
std::mem::drop(data);
}

#[cfg(test)]
mod tests {
use super::{alloc, into_bytes};
Expand Down Expand Up @@ -162,4 +152,20 @@ mod tests {
// see https://doc.rust-lang.org/1.77.2/std/alloc/struct.Layout.html#method.array
alloc(isize::MAX as usize + 1);
}

// TODO these two tests make the code abort and not panic, it's hard to write an assertion here
// #[test]
// #[should_panic]
// fn two_big_allocation_fails() {
// // see https://doc.rust-lang.org/1.77.2/std/alloc/struct.Layout.html#method.array
// alloc((isize::MAX / 2) as usize + 1);
// alloc((isize::MAX / 2) as usize + 1);
// }

// #[test]
// #[should_panic]
// fn null_pointer_allocation() {
// // see https://doc.rust-lang.org/1.77.2/std/alloc/struct.Layout.html#method.array
// alloc(isize::MAX as usize);
// }
}
3 changes: 3 additions & 0 deletions x/programs/rust/wasmlanche-sdk/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ pub enum Error {
#[error("invalid byte length: {0}")]
InvalidByteLength(usize),

#[error("invalid pointer offset")]
InvalidPointer,

#[error("invalid tag: {0}")]
InvalidTag(u8),

Expand Down
18 changes: 9 additions & 9 deletions x/programs/rust/wasmlanche-sdk/tests/public_function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ fn public_functions() {

let mut test_crate = TestCrate::new(wasm_path);

let context_ptr = test_crate.context_ptr();
let context_ptr = test_crate.write_context();
assert!(test_crate.always_true(context_ptr));

let context_ptr = test_crate.context_ptr();
let context_ptr = test_crate.write_context();
let combined_binary_digits = test_crate.combine_last_bit_of_each_id_byte(context_ptr);
assert_eq!(combined_binary_digits, u32::MAX);
}
Expand Down Expand Up @@ -91,7 +91,7 @@ impl TestCrate {
}
}

fn context_ptr(&mut self) -> i64 {
fn write_context(&mut self) -> i32 {
let program_id: [u8; Program::LEN] = std::array::from_fn(|_| 1);
// this is a hack to create a program since the constructor is private
let program: Program =
Expand All @@ -102,7 +102,7 @@ impl TestCrate {
self.allocate(serialized_context)
}

fn allocate(&mut self, data: Vec<u8>) -> i64 {
fn allocate(&mut self, data: Vec<u8>) -> i32 {
let offset = self
.allocate_func
.call(&mut self.store, data.len() as i32)
Expand All @@ -116,19 +116,19 @@ impl TestCrate {
.write(&mut self.store, offset as usize, &data)
.expect("failed to write data to memory");

offset as i64
offset
}

fn always_true(&mut self, ptr: i64) -> bool {
fn always_true(&mut self, ptr: i32) -> bool {
self.always_true_func
.call(&mut self.store, ptr)
.call(&mut self.store, ptr as i64)
.expect("failed to call `always_true` function")
== true as i64
}

fn combine_last_bit_of_each_id_byte(&mut self, ptr: i64) -> u32 {
fn combine_last_bit_of_each_id_byte(&mut self, ptr: i32) -> u32 {
self.combine_last_bit_of_each_id_byte_func
.call(&mut self.store, ptr)
.call(&mut self.store, ptr as i64)
.expect("failed to call `combine_last_bit_of_each_id_byte` function")
}
}
Binary file modified x/programs/tests/fixture/counter.wasm
Binary file not shown.
Binary file modified x/programs/tests/fixture/token.wasm
Binary file not shown.

0 comments on commit df3b46d

Please sign in to comment.