From c49fbc68f97d0f015205c86be2c929cf6bf563ad Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 01:50:38 -0600 Subject: [PATCH 01/74] adding Key struct --- x/programs/examples/benchvset.cpu | Bin 0 -> 331 bytes x/programs/examples/benchvset.mem | Bin 0 -> 2171 bytes x/programs/examples/testdata/token.wasm | Bin 32204 -> 31645 bytes x/programs/examples/testdata/verify.wasm | Bin 0 -> 96454 bytes x/programs/rust/examples/counter/src/lib.rs | 6 +-- x/programs/rust/examples/token/src/lib.rs | 14 +++--- x/programs/rust/sdk_macros/Cargo.toml | 3 ++ x/programs/rust/sdk_macros/src/lib.rs | 6 +++ .../rust/wasmlanche_sdk/src/host/state.rs | 7 ++- x/programs/rust/wasmlanche_sdk/src/state.rs | 40 ++++++++++++++++-- 10 files changed, 59 insertions(+), 17 deletions(-) create mode 100644 x/programs/examples/benchvset.cpu create mode 100644 x/programs/examples/benchvset.mem create mode 100755 x/programs/examples/testdata/verify.wasm diff --git a/x/programs/examples/benchvset.cpu b/x/programs/examples/benchvset.cpu new file mode 100644 index 0000000000000000000000000000000000000000..162626e370a701daf077e248d54f0962e195ed0f GIT binary patch literal 331 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 literal 0 HcmV?d00001 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 6f20bf1bb36381a2157ab534bda2a907835ddf59..c6debdd62c406ae87145666d90d5fde3ca916747 100755 GIT binary patch literal 31645 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 A#sB~S literal 32204 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

UdV09fV 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 literal 0 HcmV?d00001 diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index af7cfe847c..711e95196f 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::Key}; #[state_keys] enum StateKeys { @@ -19,7 +19,7 @@ fn initialize_address(program: Program, address: Address) -> bool { program .state() - .store(StateKeys::Counter(address).to_vec(), &0_i64) + .store(StateKeys::Counter(address), &0_i64) .expect("failed to store counter"); true @@ -32,7 +32,7 @@ fn inc(program: Program, to: Address, amount: i64) -> bool { program .state() - .store(StateKeys::Counter(to).to_vec(), &counter) + .store(StateKeys::Counter(to), &counter) .expect("failed to store counter"); true diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index f706affdd5..88583c25d0 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::Key}; /// The program state keys. #[state_keys] @@ -19,19 +19,19 @@ pub fn init(program: Program) -> bool { // set total supply program .state() - .store(StateKey::TotalSupply.to_vec(), &123456789_i64) + .store(StateKey::TotalSupply, &123456789_i64) .expect("failed to store total supply"); // set token name program .state() - .store(StateKey::Name.to_vec(), b"WasmCoin") + .store(StateKey::Name, b"WasmCoin") .expect("failed to store coin name"); // set token symbol program .state() - .store(StateKey::Symbol.to_vec(), b"WACK") + .store(StateKey::Symbol, b"WACK") .expect("failed to store symbol"); true @@ -56,7 +56,7 @@ pub fn mint_to(program: Program, recipient: Address, amount: i64) -> bool { program .state() - .store(StateKey::Balance(recipient).to_vec(), &(balance + amount)) + .store(StateKey::Balance(recipient), &(balance + amount)) .expect("failed to store balance"); true @@ -84,7 +84,7 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i program .state() .store( - StateKey::Balance(sender).to_vec(), + StateKey::Balance(sender), &(sender_balance - amount), ) .expect("failed to store balance"); @@ -92,7 +92,7 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i program .state() .store( - StateKey::Balance(recipient).to_vec(), + StateKey::Balance(recipient), &(recipient_balance + amount), ) .expect("failed to store balance"); diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index a16ddcf5a4..bfc55f1041 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -6,6 +6,9 @@ edition = "2021" [lib] proc-macro = true +[dev-dependencies] +wasmlanche_sdk = { version = "0.1.0", path = "../wasmlanche_sdk" } + [dependencies] proc-macro2 = "1.0.67" quote = "1.0.33" diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 222d01f066..97bea7ab2d 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -110,6 +110,12 @@ pub fn state_keys(_attr: TokenStream, item: TokenStream) -> TokenStream { } } } + // Generate the into_key implementation + impl Into for #name { + fn into(self) -> Key { + Key(self.to_vec()) + } + } }; TokenStream::from(gen) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 0571032e66..4c12af28f8 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -1,6 +1,6 @@ //! The `state` module provides functions for interacting with persistent //! storage exposed by the host. -use crate::program::Program; +use crate::{program::Program, state::Key}; #[link(wasm_import_module = "state")] extern "C" { @@ -28,12 +28,11 @@ extern "C" { #[must_use] pub(crate) unsafe fn put_bytes( caller: &Program, - key_ptr: *const u8, - key_len: usize, + key: Key, value_ptr: *const u8, value_len: usize, ) -> i32 { - unsafe { _put(caller.id(), key_ptr, key_len, value_ptr, value_len) } + unsafe { _put(caller.id(), key.as_bytes().as_ptr(), key.len(), value_ptr, value_len) } } /// Returns the length of the bytes associated with the key from the host storage. diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index d7a18901ec..511b991981 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -25,14 +25,13 @@ impl State { pub fn store(&self, key: K, value: &V) -> Result<(), StateError> where V: Serialize, - K: AsRef<[u8]>, + K: Into, { let value_bytes = to_vec(value).map_err(|_| StateError::Serialization)?; match unsafe { put_bytes( &self.program, - key.as_ref().as_ptr(), - key.as_ref().len(), + key.into(), value_bytes.as_ptr(), value_bytes.len(), ) @@ -77,3 +76,38 @@ impl State { from_slice(&val).map_err(|_| StateError::InvalidBytes) } } + + + + +#[derive(Debug, Default, Clone)] +pub struct Key(pub Vec); + +impl Key { + #[must_use] + pub fn new(bytes: Vec) -> Self { + Self(bytes) + } + + #[must_use] + pub fn as_bytes(&self) -> &[u8] { + &self.0 + } + + #[must_use] + pub fn len(&self) -> usize { + self.0.len() + } + + #[must_use] + pub fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +// implement from Vec for Key +impl From> for Key { + fn from(value: Vec) -> Self { + Self(value) + } +} \ No newline at end of file From 2eaa9aab76071211b333aa9fe9448d0e6188e747 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 02:01:37 -0600 Subject: [PATCH 02/74] use Key struct in state methods --- x/programs/rust/examples/counter/src/lib.rs | 4 ++-- x/programs/rust/examples/token/src/lib.rs | 10 +++++----- x/programs/rust/sdk_macros/src/lib.rs | 4 +++- x/programs/rust/wasmlanche_sdk/src/host/state.rs | 9 ++++----- x/programs/rust/wasmlanche_sdk/src/state.rs | 10 ++++------ 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 711e95196f..6236bfadbf 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -11,7 +11,7 @@ enum StateKeys { fn initialize_address(program: Program, address: Address) -> bool { if program .state() - .get::(StateKeys::Counter(address).to_vec()) + .get::(StateKeys::Counter(address)) .is_ok() { panic!("counter already initialized for address") @@ -55,7 +55,7 @@ fn inc_external( fn get_value(program: Program, of: Address) -> i64 { program .state() - .get(StateKeys::Counter(of).to_vec()) + .get(StateKeys::Counter(of)) .expect("failed to get counter") } diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 88583c25d0..3b177deac2 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -42,7 +42,7 @@ pub fn init(program: Program) -> bool { pub fn get_total_supply(program: Program) -> i64 { program .state() - .get(StateKey::TotalSupply.to_vec()) + .get(StateKey::TotalSupply) .expect("failed to get total supply") } @@ -51,7 +51,7 @@ pub fn get_total_supply(program: Program) -> i64 { pub fn mint_to(program: Program, recipient: Address, amount: i64) -> bool { let balance = program .state() - .get::(StateKey::Balance(recipient).to_vec()) + .get::(StateKey::Balance(recipient)) .unwrap_or_default(); program @@ -70,14 +70,14 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i // ensure the sender has adequate balance let sender_balance = program .state() - .get::(StateKey::Balance(sender).to_vec()) + .get::(StateKey::Balance(sender)) .expect("failed to update balance"); assert!(amount >= 0 && sender_balance >= amount, "invalid input"); let recipient_balance = program .state() - .get::(StateKey::Balance(recipient).to_vec()) + .get::(StateKey::Balance(recipient)) .unwrap_or_default(); // update balances @@ -105,7 +105,7 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i pub fn get_balance(program: Program, recipient: Address) -> i64 { program .state() - .get(StateKey::Balance(recipient).to_vec()) + .get(StateKey::Balance(recipient)) .unwrap_or_default() } diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 97bea7ab2d..3611ef9ce7 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -110,7 +110,9 @@ pub fn state_keys(_attr: TokenStream, item: TokenStream) -> TokenStream { } } } - // Generate the into_key implementation + // Generate the Into implementation + // This is needed to convert the enum to a Key type. + // Key types are used to pass StateKeys to the host. impl Into for #name { fn into(self) -> Key { Key(self.to_vec()) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 4c12af28f8..1298d982ba 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -40,8 +40,8 @@ pub(crate) unsafe fn put_bytes( /// # Safety /// The caller must ensure that `key_ptr` + `key_len` points to valid memory locations. #[must_use] -pub(crate) unsafe fn len_bytes(caller: &Program, key_ptr: *const u8, key_len: usize) -> i32 { - unsafe { _len(caller.id(), key_ptr, key_len) } +pub(crate) unsafe fn len_bytes(caller: &Program, key: &Key) -> i32 { + unsafe { _len(caller.id(), key.as_bytes().as_ptr(), key.len()) } } /// Gets the bytes associated with the key from the host. @@ -51,9 +51,8 @@ pub(crate) unsafe fn len_bytes(caller: &Program, key_ptr: *const u8, key_len: us #[must_use] pub(crate) unsafe fn get_bytes( caller: &Program, - key_ptr: *const u8, - key_len: usize, + key: Key, val_len: i32, ) -> i32 { - unsafe { _get(caller.id(), key_ptr, key_len, val_len) } + unsafe { _get(caller.id(), key.as_bytes().as_ptr(), key.len(), val_len) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 511b991981..92aeecb26c 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -53,14 +53,12 @@ impl State { /// Panics if the value cannot be converted from i32 to usize. pub fn get(&self, key: K) -> Result where - K: AsRef<[u8]>, + K: Into, T: DeserializeOwned, { - let key_ptr = key.as_ref().as_ptr(); - let key_len = key.as_ref().len(); - - let val_len = unsafe { len_bytes(&self.program, key_ptr, key_len) }; - let val_ptr = unsafe { get_bytes(&self.program, key_ptr, key_len, val_len) }; + let key : Key = key.into(); + let val_len = unsafe { len_bytes(&self.program, &key) }; + let val_ptr = unsafe { get_bytes(&self.program, key, val_len) }; if val_ptr < 0 { return Err(StateError::Read); } From 2526ced3c0937f4d17894caaefc18789704800cf Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 12:51:36 -0600 Subject: [PATCH 03/74] comments --- x/programs/examples/benchvset.cpu | Bin 331 -> 303 bytes x/programs/examples/benchvset.mem | Bin 2171 -> 1543 bytes x/programs/examples/testdata/counter.wasm | Bin 30542 -> 29954 bytes x/programs/examples/testdata/token.wasm | Bin 31645 -> 31597 bytes x/programs/examples/testdata/verify.wasm | Bin 96454 -> 0 bytes x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/examples/token/src/lib.rs | 12 +++--------- x/programs/rust/sdk_macros/src/lib.rs | 2 +- .../rust/wasmlanche_sdk/src/host/state.rs | 16 ++++++++++------ x/programs/rust/wasmlanche_sdk/src/state.rs | 17 ++++------------- 10 files changed, 19 insertions(+), 30 deletions(-) delete mode 100755 x/programs/examples/testdata/verify.wasm diff --git a/x/programs/examples/benchvset.cpu b/x/programs/examples/benchvset.cpu index 162626e370a701daf077e248d54f0962e195ed0f..ae62d5ad4b0184af7779f7faef845fa5c9091396 100644 GIT binary patch literal 303 zcmV+~0nq**iwFP!00004|76awOY=Y&$MN?rcYPmPD5oGEPLiQWhn&69wFr*RE;hX$ zwUFF}OM)Hi%P;+qN}4QbYf^lCy>NQa!g(X|MU&Mr1h zk6K9X!X?3u75ofcD~Oa@szP;ga1c?@#YF_S`V9nE6{5AE+XFwI=lQSgz3!asj_&XN z7fe6|7fdjSxjwm=)HkxR-W^X(rwEAlZ?4X$g8>m#!GN5sR;&MVIVZP(DMTgZJTY1i%Xz5dXvTu@^>xh`HsfR3_Z;qmQ`>JBiTJ3u>w<_zF`|!nRZ>8d_|#ng{|XE*7Y-AROC zL1I(2g;pWj3Q~=;yXQ{E&h8m!X471MT~quh7Aph%uUXf%IBQPPxccm| zg#~-jnjLta5yRcv{6-%WOTC&TPmWc{DA%Lp* z%3m+3lGGqlC8@z)yw|;*K1=}B@IU^jOR_vgm*Eb4heVxq$Nsi)`AJt@Y_nP`S6Y_r z%{r;0W&GMJzf_e2ct*Drz{Re+kA9~}>Im@mle%?v_`B9$2ZD*apMKvUfa>_=*X4N= zIq)eZ%Yg&{iHTOhS9@0AAU^2sr;l`OvtpUZ%cH`J-RKsjq&-P zTv2!nc66Cq(8XQ1M}JXtZg)z*S^ur-TxA*R&dTaqqlu?w{-$x?Uw-iC3s*1v;n&TU ziHu{0zu;S05)8O+^*3{#`PCqf#o(0af07UK%(n(&GS2;SpjP$HYBZi?{Q8!%e%08% zffywz&oXZ#4sy5$~t`G4BMA;~@1y;q{o`V_h$f`ur>( zcv(8|W`{MKH{_Z%6h7V!u@CUaK9WW`PyM~uk?_+|!e~dYx0$;8$KOhL$)qka^ucs8 z&Z80ck|Y%yjCSNLiupa0C?4{(&HD1ef6p9&b}@QMDsmws?b)@?rg2mr>8cVZAW^BYp8x)NV(JoW7kCLz<5OWOCP^j*Ov^h(75)GE_)hX* z$kVy}BHi%DsPLlkh8h{6@X2*Zet624lD*AR9t`hO&;C7gB)E&t3nyba7((&iqe5rV zW+!>ZbHBOkoE$M4_wNpc2xHDd5eMUti8R#TY=5%hMdO^O;~@5=|5?n#V6gds2!`*A zVty~r27Yiew!0C%wA_&{>+TNY=`g3{6q0$p`z`2ukY`yCYKgg-pP(=UN2R=shZ-4-*hNR#fayp`6TlOam2^@sgW4+SPo42 tlV@H3k-0?NfbaO3E<3`yawLy2!!_^iwFP!00004|Fl+XY#dh=_O5r=*Smh4UB9m1*VlG(y>VvNV<+U%CQj_8 zX_Y{fG$2sHjAyUM)9%hJGqXr)JwxAIH@Lv}X0~OYzG>XFTS_DGrI0^y6h*Y!n=>!Tx9LGt5{WL-`3gZh$ zFCPXPMU`+cN~0(Or$Z1*Cr~BS;2M%(&qmV;6oFb?OX}EDA(}*$_`Nf4NuMY@Q7Mh1 zP><^guy?{Vi6VIa`8OpVgI8h_k3kYANs1kbrJ7SQ^rJnrq9Ps%g)1X%F%-sga}kPB z6rVhL`7qEZs)XmFG>Rf{Is~CqQz{m^a%xpYMZ7XvS#mhTXcEQn_s<4GRq$*eR0R#V zfuz{uF$$;(UpR3^mIFaX)&W5yZX``irAdVFxvQsSnAPw+$S|v+88?#__6*P@s>a8E z7vORDPo2c$fH5X5?0a<-P#hn4;fF^>u@f*X*%Q!;TS=Q_PvC=Z|ND?grUsr0OYa(J z$L*wpeKVB8saWLLxBDt8;;~p2s*Wd0Wk3Q6edntW-hzzMB&xy3=FZ88YvGU8lCu^% zaVP0wClF1dTKx9G0I!1&0=y2oaX0B=?^n|#s>A;{cSicx!xK^IUk?Nm(!<`0&?KtI zFCGbSfcJx#0Vt-Vhy6tyEZ`Rp1b7mD5|aK&=*7LHhaC@5KuLUIpTHw11vy!f6!hUf z(!+F`L@B)QPy3GojiLs4FYs=Fe%w!%us@5oYQSIn=hG5zgbSi=6Q~iE;-!SK^CG%N zeCU}EWks9d@`zM#f&n~0I@l{C6r(15=}J)XW;i)Qqo@Y11~Sc%#%a>QUK&Ytr{aHT z_}d(jpLo2cwyqwMsfNa;wkQhY--l=yYR1QY^}4K53mgv7D8le$m_|@5JSIh3U>ROU z2H6in=>)>C94{w>Y;QOnN3Eb>g$%OK(9WppWhS-lo6r(o$?mGeA0eeMQo$$-xj5=$7Qs2v}8_23cFqFt~=Dt5sL9w95(V5&0}f39+F50RfZYHq=;ZSAEx z%*AOEb>QQdFUf$q;f3IKb;C-$l6;CCi_s+N#3#QITvq~r4+18z3a=uo*$I(u7rt~= z_(xC=d_{`)z#6=UtY#){M&02H zBqDhKYr;N?`rv7y7Ds)s4zDBY*%v9G9{lsO0*;`5SS5-2VHA&&^(;dHQT*=d09^u1 zqDx={-ayu~J_@K8|7LH1E`=V6E`^PFBN=0zG>Q7~zVE(qM6@k~Q$jd_7>wg_avwV> z+O{9>|Jg-}55W1LOarh9ZzA`zS7WKJRMolA*(XUwMZBh?v#Xo*(B8iO`7$?ce*T01 zerwP1i@$AYi=fb|kXE5Zy@GCVEjl^tb5E<)b2-PDa3&w&hVN-n!ztRnmI!tO%Ua7W zdVFHuBoX`@V4a4OFSy+E)Tx~AbH(Pn#<^T>(mh|>tU3i>op$nk(&f9DkCo#ai&ien z-2r7%EVK;^5GrF-3$EikLaDuMUn%LxJlw_b3nIbaSX+swq%JryQ4S_kIkC zc^=czV16w*w-;@#IpWmv{*YEzzM*xw+~m6psyA!< z`tH)pYvsg)WZ9mtjV++j%BWQF)LOFOT6Y;zCc^Ute^%?cvq6bQYbrMxbMk^+s|&WT znXO%Tyd?(Hxkffmo+?3Gi=IEf*JoP(ba7G$s#$%88>VQCAxWoZi+MReZZo>Jb3M!5#f(PFo|2Q@bTldoEr-1rTMA1D>;sC+_3Y+AX(6vp z8J%htZ826&N4x%`;wGK#+~dC1QsyTHbP$KO_SVZ&5EE~*ICXu}SouOu$#GLRX16$c zc9WIkbe{VtB1fMuxSyt+8P^&j zSSZ`MX?Z?(MO50(yNK!fg};eVbl3`IIN()X$?MLFCWqhz#)7Zk)D_(o?k%CM3VKjib=cP+zH3X_WI{4W3i|Nn>lSKCGs001$(FI)fs diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index dec07aac3a4b4b2b7e02773fa2a2ba70ebbce2a9..7bbcf8652413fe85034b38946f5556fb3f0c50bf 100755 GIT binary patch literal 29954 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 literal 30542 zcmd^|dz@ZXdGGhyd%yR0X5K&`lM7_OuMsAY%j7mQ30|_(CJ;#h1*9r98IlQP5)v{q zgjj9z1|s4G1#2s(^#UFQR21#$g<7iVDO$B&@O-S;mZNB~dOnAbr7dm!R5a)Nd)D6X zJCg*D*7L{toReg-_qyz7J?puzXRW;_7@fS{1wr5*aQ)ld;ea1^cw2awyXf%Y?4FwF zkQHJssx0WLo6?~}{`L_45Ajq%4P0YNhdhvATX^V@!LUns=&(Bk1pVPgZHKnSSt(Fw z8^Pdc1iSI08|d&waba?5bZRWxGqyJP;*iG9~jj9y>gKDuYm z)~pbeqbskdFyU&g?(~PL2Vq$6348nMjqU~Cu0|ep^JkkiVN-r_ktG`A{Wdm&W#ScwB0@y)D8#f?f3cX9lDn8cGcqb zW7qGScwHFu@7lX-YS-wVUB5oIb#%v$iLuGat=HZ-HaQi{sqEUjJ-eTKn(oIAPK{0M z9o>^vF6d*vTMvxxxp6G3IlI4Gb3*5Z1t_p@dvIxK$C$snth#mUj?t;ntz&z4M6R}V z>vdzJH*CFTbaE^TD+4Y_U9Gij={e1pu0Jh3{fb#Huhsh+ueiLY_XUdvSFK(%G(585 z$_p>qRQ=1pa911+UE%Nx+WZO9#_m?M$ZnHxAS^dyU4mvIT<`xTE-56j|G#1VTE)f@ zJ=%)X;G&)&DW-?F^hBNh#k6#BPml&ngNHwGtR2it8;v(w_fij>t0h5NS{DRKki?6F zU^pt*T`ei4;ZPVPrN*u5Nf)Os#f?3*#f>+qvL?LZ9#;7~KyVHgHxmmbr{#3K1E|E|! zKm~AXl@lS6aM{hhyHxkgqR=cRp`s+t``lSFdCH7h7pJ1b=^F_6{gXFmOB8oqWv3tf{dnzCpCXJ zuI8y$A${UM=ktX?Uo|7qD#)uU}H~}SpZ=7{_AFP1q4N6V;J|1 z77rr!M!_bM>BLPmCILneaq;~o zV&hTMg+kic+!NBCPm?U$Y$i6(7K&Ccz^HJ28YT{*X*p3nND8|r7|KoU zhd&^~JX=l_ES|`bvdI8b%s5gMM+!+%96^L;aKxR+kuEbzj1G8_2QGPh8Gk&Hws-h~ z(1-O%M&RK7Y`~^d>(k;|(}YMxFLUM8(K9+Q)hbEC5+|co@&Zy$N(^rOpkzsm3BWZe z=~CC!{iUP{Fd|binaKnQeVr*l>QnfcuquL8!LTZHu_}117-bq(g$`D*eFjz{tBLuL zpE)doPR7!tj6JiW(S%z%TMLswh5Fz&(<@Gxq8BlFVG>VeT%Lg48+)Qt%eKUqR#%Gv zkXaIla;Yd|c4YJZuJ~e|I^xSbI#P?dk@(8kfSDIxc!T@_($H*yysQ%p0q&);>zRN{ zOc4`=T;OI1Io+oV4a@^1b!Ke=(XIO z*aWH23k+y_*1&*FZp=@ipg&b$y4(;BGyl$@1=iV9=lfa*D@Hnac z8Q%_{(nn=?n}HVroRCREt2myNHeq_`Tb9K`8yI~cY~M$3iIhw(t}d=)uBflWK?o|} zhd6BRk(-;=Us^~th!_Bh+j9D=Mk^z|u*!styYX}YPXgM=72@`sNW^3c>9%nR*g-Q7NK<1R zUsp_-3!N8-o_-Znu`#al7e&wEPy$^U4$B&IDEyo%Jto$lTdD4l?=4adg^#HZ)eFWw zH&W0JKoEg|wy20~mfM6p6cckwhwz39&Zymuuw-se(i@06nX0%X$W)~+N$Q$ed{($# zJj(q!Jxx^tQx!rBQP4ZzBZQ+HucS@@c=Lw#=s3f@nGqyegDQB48TN;YCa zWPIURPGTXa>2&5yNFn1e&40vKC^29^gJv!{^pLLi0 zgf!OC59l?HegMvZiHaQ?mm5C?MT}Yn&)f+@SHZJjAVP9-^UtjlJZNncgRFUAz#~2| zP!I3n2>f_}zNUfoqPRqKDBjG#Fzu7LL-m6+T+!V&aQzLs?xbzJe44aJD zPV33K#E>8WB{MfBc;+88hmN!BP*Rij!2-6&Ye?t8+%q!G%zbOZs0kpm_)l&@zR`&6 zHRTkb!}X9ScPU|}CvpYT^u*276S)*fic1N*-agD-O4!j8*OY5AmGGWrS`5N$%Zhn~ zAX7WOa40-_pSKXFG!{NG8VaBEX2eHq&^{|#phoPI6`#@--p%Z6wG8&OZ~fuS&Q?q7 zv%a-`uVIsSwpv=B^R2gKtyyQQrS+()hr&Cu)~vJD()u>vdRNw(b+%esdCu$~x9{>D z@6I}A&slA^^*vduU5CO4W)|gGigv}W z&n!Ng746E5W){Dg7413{eq(0wYgy5*usSO~p)0JO*=n^=<0;?z%*@VKOY76V^@mw& z*4b)leb%?OeKe7Gwpv=B^R2gKtyyQQrS+()VRhD;b+%es-{xEI%38C|R!i%4xeIRSiI$JHR_xje4XRTRhtEKfp-}-RYnsv5XT7TcS9?M#@&Q?q7Bfj-> zS!>qWYH5Acw?3A&W}U5;)-U?jZ)B}mXRGxlH#4Jo$FKR0KW{LCsqkwfv$$MfQ1Ax*}PNKj3L6wg@cX^o*c z*(gOUZp45bapujU>F7rt^rH;@$ROqDN2iL6W}*+BPofvZ05L=5Lgm9mM5DB=R|$V| zv8R`btoi6p$j}AY0mFBcy}82)H&~G*449X;uPg1qGMby#7>qpbwM!s2z2GAc372R$!6?hc zP$^=W#IW((hPzsuGWY;WqH$r`cw8;>d^hM-uEmV6|B~8mu<=kg&z}T~BZM_3nO z$6KgKI(OXmKm>b$JUBJ8x-|&A)>l+kI+clA93X=T9}6t`JjsnLOcE}R`b8D>PD-%C z7iNto#ZF-^Mk_0Xz?S?L(k5_hrLLmC6R@%rEliIExg1?)awL%s*DFVzvbvF!I&J@e zNxt7hTJDXaS1Tl9Fz%bUTF$qx*0@`3L5+XtT9{KDU5h-yJ$PFWCfbTICNWb|*fDa; z&&AqiV4EW?+Z~$=3lC@?MrcXRAgnAvlyaF(N#cz53fD+1oGtStSlTUWe9m|)uPoVB zcwj;zbkP?hh)*!e*c_C<)gYjs&qOTGY4l9g-B^2Oh7dt*?2Nm=6>)9(tuN7+`UYI# zzgD3m3!XI*jjdu{3FmCPjAy=0uwoDbLHKJe^VMdhuTrvStb}-6q={PdW;%}`DCy^d z@y5Gs+7de^srtrI)fg4SrNIDrlKi8bM37Vh3t>cEWOzw#Wjrb&^Y2KNunC!Br$PwX zG|QbjFJ6K0@d*ADv^E5dH+xh;N+>y=VgeFYVb4`VMIa`y1H;ip=>xXcHz(_OmzAE@ z|M|`zEnf@9H&}`;l$dOx=H8p>F%&|t^w|6D_OcAZgKEh=1a;5kI>DCfmaZ#9hC4<> zE^Ibkzj4$c)w@6?xa@BBgD(R&D3!+>AJ7zo+SjM;%SwDQl|Vd9d{6)cNDeC#3adwQ z*kM3`rdOKbP!24w^db`Z1R6S`QGZ9Hw%mr`av}4E7Nos=QVNtwn71L3Nmy<~qErmc z?F-?wECsAYvm|SgSQ$-|u*gf8)w_(9QHPb*6I6I)Ix7wA3|9J%87qw)*(PrKm`dq_ z^bxE5T}?^x#|$Ptfv3tX&0{mv^3Rxz%Lr;3vsPtKODnHX*^|-A%yK}~GL2dc_t0v| zVMn2ujP#|yqfiOzR5oR@j+*T>eaHp3JRA+A58tA>oZhy@gyL(`bg0rha@ojK|?;fzUUniQ?e25RIOQTXcV` z#9by_622C}Ojiaad98|NxAH#7jO-WDL+&Vu6q5XCfGi8C%gkyBcE@cAY*OyDK)#AE zbRl&j4o(axqZ!K{6w)Q*>3c*zix3q<4N%$kHH#8b(8PqeZSww!tjcpHNfCXL@ic6_ zSEAI6qV-mhl$bXrka-qK$LmhTY>^wTw{*NlFXzTlsXeIFU^%K?#KFu*BvD@t34L!I z7CC(I0tSKQP`KpXANZJ#njzM7sHh}`W;H1`Yv594(4^`y7zk(2I-=*n3a{TH!>z62 zN>Ud)Dw}&EdXh@6auA@B)U;Np+2$O%ZT4lyn|0$5DEk11GX;`|lGGb{Y|z>q*C_)f z;REnmsv~&RLXFm*qXIhM&CqnAxcZ z@8R0W>{O@rQMKl^h{x_3p;5=JNH4M&BGao-+M)2FQ#NbbG5neHM;|a7-r_eU?0LvS z-siVxs(S1N(Uv#TcGh9{v)j_qb}f4tkHA#hUD>c!3B{xxov~vdiA2Q4xrj{D`CM1c zfoRiSNwyVa0eRHRFh=)CB#wj{6W zGME!s&I3n==u&TmsQqs$21(CPpU^dz4D1vg*dNf2J3|r>SX@oa{g)>4TJJO&Xu}7; z`rXfe@>^ei`+wIFE6U&f$afz8;NKtr-a$-b?M<#bHB3*(Whf%SQ3$dR5jrdGNH&ob zw+Xv%B|xqtdGGNnZk$TqxCjX9ujqz5nO#-HR3u#G|8ko2f$AE@a*g|ie(if<6k-*l zobDi($$olnmI(|t-0|h$)gopyCZtzA1}fC5Cqh`Y31wZ{t$4#TpNI}6!5bvL$B&Z@ zd@9(BMRrr^J8y-k7(;inByGjm@^t6K2P0K!(&Omwx3$$DVV8Ah%}nE>Jx zlfE>EFrJ>9M7tXgn0->FvFn0r4;EaRlBBD@r>?4$S2d}~cbe#7PAWnPqb5v$cSTTkNEk%K7?8Cjl;kNp*T`V%Dy89r49%%nCOo4IvHC6PhLWT z{3sd`kS0ywF#}&tXgoi@#z>`*<(#MUNi`?%$>awy36ZX(s{A}Txy_^-GmK6#kdZCx zRC^ibO5(!vVLmQYgGma-yA;*2qR8^O%(kF(reQ*lTww3P+3ncEuYR23A;9!<#1+$ zbtmJibqfz99_q7i1^L_#-%ip!r!b9Px;Q#37sQ#rv0=jr01Dn{{+~` z4s9Y#jiF6bJMl@pJ0Vy`oUIKhCGP`znupOqvnZ#BUuKwXlcg@FH|Ua~lVPUG2oqK3 z12fs~;MvfbaaCrRS#TT%P|(v($>f_Ll*kB=%e1b)NYd?;KBR9F&u=Oj2Aw%~hncoC z4Xm3@RS1vFf_CLzx}X%7dJ-}UYeX!K#?v=o&6N!<69-`0Igy2-5gsC~&KhZ&)a$@; zR+k>098V*Uu2u&^gTpfA+yn4{Go0lPD1_4sQKw+y!pWwhc?ippBT5FZ1ByNZhQyR4 zS*6V7k|__s4!69&J1!E0FB8JZ!V-kaypbxyPGy)?Dnk%r6zM9*$DkGbJ78gVdQ2z2 zjyaBaRW=B^}2v1XvUg=DS+1#3I1eSI)GRe4@{&- zZa!MpA#Q&<>C|n0d3nkjW=aR93J>w`*nZxMm@gvWb z_H%1j?V!YaIB96!IjKX{Oq9fIoqo+`*Rlh_aW-(=oeBKGIqH-kJ>pZ(l>_f|f(O>A zEFCg}px#}A&PCz|EYy1!A-)_%PQVnrp{RTFfhzAmgozxpodZn^`4aeUfW03ccL5!$71%!pW(x z=W*@Q@p5LO2-F}18HKJP@it0<0{x(koO#K3m*a2>&@>%}Y%->$&35(n=y}Lin;kGL zcoXC!RgDL2ZP0I}tc3+#Jqx31Unschv;{-7i0*BzUq}wHpwV5VtQ{4kHze8I;>)nn_$o!Gy@}!PHjqE z&9Jepu)xoV;E068G=f4F9cN&8Rz}W0luZryq~xQG#|3uij0E=5JX4qj%(m&_(!vz_ z&t{AvgbSL64|B#&!>}ADzfaP^$(@LkX}+C+R5BFoe4fy8Fm-8QDNtc%K1OuR&PHHk zj68B53Pp1<&JIlUMlJ~PVHMG?u6C?1sj50WPLGObI!;1KoNrbX7bDqGQn7`mvUQrD z5w#1Nt~p%Z3YY=~)*Wc_449M*CJPYPL}McX)7DT;e6Ir4mLAH9*)f)k7r@9FA(v_# zP=X_Y2WDWQCf0R(4}wwVmKg_9jXcRF$&b=PG$@}IIehY5`Gb493k zzxmjIJVO23kOM(k0;H||Vy{?I4pR{3wt$$Sp@TW-)_#~5d^BImb230jHvQt9m3exc zJ)6Pw@c=^h?Qg{_b?4)HwS5`MIG~DzC8#DMdH_jR#3?C18N~3<0l~ak+UCupAU)!D z6Dg(bTOmv1!xA}LH{YRhN^~ql>79a9zHrt;7d}V7AQX8sAbS!fLG6pNtJwlP*3>2N zOkK7`@t4KbTuGcYE4C=Jcv;6gK!qJ7qT^_N!ith*w$*6PD>Qp}s&46LDXi2-O*?fz~L7 zEOvw>GWB5-|CcDZ0SRCfz!oZF1HPfeSZdmzuRbk;SF8oWS;kwOE!-*i2$c-m;fyV^ zQ-!1^1?f@X0bi=JBsnac5!&IJ9O5q4ZVkJONz#d(#iTr1-3tW6Ao!*OTv-7)mD`vu z$-OOF+HPW9&}*gof%Hk0>Q*Wq(3-}Yd(w!+kb<*>Y={ygCMDA$KosEd%rS$IhIGNs zP4Ci|cgewaM$IcckkbyNrTytM9u6Dy@X*{bR_4D*dz+48{>mq*?EPIbkh1NNL2f=< zOp{l({k_od86$xFql%<;R>j_)?%*^soIdd;xX3Nrr4MyRoR&PFg=)#>gNR3|cKfM$ zVLC2I|DUns;3-+sp$7E-d03Kj@@L@8ol#im?y%`dPZk-Po)TKyhL0ga^xV|TdYK_c zRq{ZIJ-!8`j4dOogcIf2=@X{ePwIb`-)Wd?6>b|CNJ3XbrC|ingamo0YJ&hhwk5y8 z`nJL1{mv6t>@wAihyl{VNCPiW0#!&vIzTXo3#Z_Y>3JU*6c>lHCAUhp&&jgy)UlJ7 zun`j~S!;pMYA%3l_{4m1X^^Z7MyR7Br)GFq2jiB2yS9a=qmNm`04+(snc+-fusdC4 z7)k7{3oxpfKL-%{r^lx4R3DkC8imXo7DV^wSqlgp?b2Upu`bXiq|H~$+PLw@rjrZ{ zJDZ{Bth|#0S6;;?EDtWkauaen47JtJVz2ek8@=bHB752#tPD51^$T)-Qxd=b&gLsq zb3#@{_S|}WTpK-z!AU)I7E;^e9lw7%_Cm(Ouz$oyARnvFJT=s%iybnv6Oh@u1dNYZ zqNp7zgPsISg0|%}ke1^(163Ti%m)=e$tr%5SNu4u_^~Rs=yVnmtw`7?+(>ypJpH&r zMqa43MwU;VMujD|!C-IOY8Gjb{ut43{E4522gWH(Mc4h}h5pLYU#v9?GuCT*)9Q7a z)^~yMzGs%0^7${u@auM;`-=27jS(YBoOXi*S`Ir@I6%zA&2Q*j9eW*|3?o4$3L)!0 z{^4~-aA4WK+fxqMt%^?(C^4zbrJos(^8}BQf#I#B>0J(GU2qP*OL$V3-}v8mVJ}H9 zEGw80YQ^;RR4A<%5eF+C;83zB3?vgpP(@LsDh11v7h8HNEF6<)x4a_jxokg0GjyQb z0yAYQU6x%HamcRf4O?=n*d=8vg9%(S>raR(U12GgIu7+w!|Bo~J?qn~dYB}uWB8&a zS2&yCL>RcsVr5+1&KlTaY(@5I5Ug+yXuY9U;mO z>gsUHHmlU(-Cwo4I(L`ZovhVGJTSKvk+-BxmFR$wlbj=G?szP=Tq?Wd3xsTPeGeEN>5}JZFZu~t=$^-ctnn8 z{fbTJl7AXGuIrG)6K0@8m_;4JXb1Kr!WjDOzxl&3c8q#M4UZt@dm4YR zvp+5>m&3d;{aRF^gr#Q#UT%F@41a&n(9TOX}pXa40G|2Di! zYg5gbC?iapL>o=NFB@6+^f26Z2V^M8p--g`--W6w8^kjl|A;SC0+1{@Tk7UT`DO{W zsAO*UI92wM3f`sF+sgVthAx?Lb)mIgAM5C)T-HcUY@$R^}+W*_$&W^kzLdvsy_w7Gft>v&5x( z_KDSOMDb$rwP|=jXDh)tb<25xOG8QFGRca=-YTOU6MXw*GFA?_uEzRU!%sSBxm?xR2K5zsoH_` z_ui@N`@{6B@6ydfq3^~CIDxeTHK-*4yXkX`Fr^RAklHY@)lNkb? z|Bo{SjX4#0@_4%T1HH5%ZRL~N%AlJl+$)>VKB@B;PUe}3A^3zGodtZoYg}l7%q;{-kb`Sab4k*d& z7-&EtzDnbhot8~7lOx6BsAlRn;xqRr@QsgT_6+PfwZzjHArMW8&6t5%&Z?$k$)=V& zM&i#t#8u7Lmt@T}l^RwCVoa%@Bh=$j?cmGg<)_P@GT)nfTJYT6stA~obQ1itBaoVp z+h4oW&3HX3OR#{LqH!&yNzDA7X$g0JwS?g$Q9K*#AL2?`PK5b6m&V6E4gHzyR@p^?p*Ab`mgA?Wxd}@+@^X_2p3#YZ)7Na&C@}ZR+G%ebnBtW=+-j zQ=x5CWd$gWl}i&EEPLAQM2OYE^WLp(+st&Vw&=7pFna_nxQrd)TD=sDONA_^rN3}8 z@(LFIv1BBdm53f3#$&c{CPNA5gIq90fp)33CaO3eKZxE1!nZgov`x-#h`kPB!qwuV zY7DF@Xqq5xd{K%)@Kc~L1HRm^D3XuqNt)}F&L?XE>1{Hgxo_o+==67W!bMQ44OUv2 z*EOEj$#?0Aw69C*JXhIy-9g;PD9_bJTQ5r9@gI@!12&pp&O@4|L4Pwaf&-c3D3St; zD_G9wTPMCoT#|gzJBfTC!qaorS)QCcPiHyr#O&^J{-i?^a?sWzU(TP@Lu;+DD}AnZ z8Wd08rQ?=5n)PBDc?KmFqI*Aw*cr8GhX-pR6?)H!NaP5Y65PX2Vsbr#}c5n=oCr6OXFzCq5Bm&Uf$xPj9Az z3oAyJwr$b~>>6b62wM=KD!wZN8RLoUZZ{_c%93Ty+S#)RW#dvr%%8pE$c^oB0tijf zRLq95u=Qf0ld2YB3BmlOXr?vodn>RFkXq%&I;M*X?N6eKR3FhGEw1IPq9gx>H_5fu z_vlad(G+SLpD|Gsf?Wv3E(GT8B%k>sbQCsEiCi7RcxH(>Ot24r0SiORmzACu5G*DG z;@^SGI-iWUe?d9J8$*Ya^yu4L-ykAN8RxjA-DBnFV&k6-@@FE2X88SSGqhKg^B41! zUH}i|FFj~9C!&h>&quNka-0TarO=z_`*%MPmh45#1pkBh8=X&q8#x7$4|@*lSW#$Z zhJv4&32PG6{#>WcrDpw2=OtYQ&O9gDegdi4_EEvvAYz(7-^7X!KN_t;fZpX69>Pml z_C+6ABH5A%#fmTlxEsA?4;1+l8cfePDCh(?2qh9Swx$3bi%(&+v@|kez7`G&D2u zOIjkWlhDw-4HK4u#;s7)&a5G{R4KEDN@8OHaj`}NsE~ghA)JnQe#8R;XNX&7&bXqF zJ3#i6?buAjA#YBm4t|g!N9Dqv$m@Y=xYn=G?i8O#z`#Lcue#G9PJ^SgD^D66e`|BK z4=zxj852F=jfsbt8J3fA?5o*_23UZ4eqvC+AcKmW{*;gEA!sz8`lEVLB55&epM>Ty zHB+J$A1uHisV8!zu02uzo0aE;0ZYkJ;%*`NLFM}}c z&_TrVvo-zDfllr;r76S-G;roXM?rCIK0Wb#poV$kXNDw;5)eG%v$E3%XbptE6|->4 z(+6No?-a>6;q<{T3Pn*1kh7>QsC}~(^|CiM{r#3OZs~5JUiTS2?PzeH^3%N&Y`}A}kf+qUS9Lt%bJo4IFm%Cr*Sla~l`2n3t-AY9*V@u@8gP#v;6jO_ghlCRUU zx+sm$;xNV@X`U3c%6@j8}}QMwzxqcn!On#db8?mLi1WSulf4;u^g*bHGBg?s~S>X za;GyEHX+c94mXW65j!B#0;PDSmphTZjtUUBdUMd`C|nugG4Tp$G#UKU;0CmOOEMbBQ` zA}=PwJbynA9w|PBm5o1_7hpzmRe3X``!{x>SPmSyR%~F&H7vU)14nS+fJA3To50gy zMx8oJeSN)3+?#vnGb2GzdpIQ4QPNif>aeAKU7G_Yl=OA&(0^S!Bn4z&*VYiqG!UT4 z(=32sBz_+do<8_2{>g4xzS))pI5v9*rkTXU zRw6PvAGu|%YqQUEv)iW6bSoHDrn2*KZGBRb%{d)0j=&fr8eMbK4a8OpAAy z=%1XYQK#Qesm_IA`6h5u$k8A^RNUyFu}k(@lrM^nL2V=JceCdxpRL*Q^(iyuJ6{1r zR~`$R#7l!l<4gXj6U)EOVGbYL9uqx*rEPw@55*m&p(HJDyN_0jMd?lM)0b%)2ygRE zJm&AHdPK0y2MBi7+rFjU_`Ju13H;N4JW!bShG7;cz=I}3{lcdcjiRT5^#8^o#i8!m z9a3v9ix6~Jin#x`#2Uo}WsDokqVcRbASohYkm1R{M^u}~eQqbb;s7K~Fc-=x&iIUw z!(T}_J8zR?TH!xReH$aT-LQ;}*@pzR)%)dP_x*Bi^Y_bj+j+m7KHV=1h10$)6n4HW z1gPxGLi)Ust9?0~G5gR@FI+$KuLYgGrND*!I*B4^%3tbjE4+02$UPEle5g*6J*qYItyr!?%5g8NKdP$lu@9Len8_^=}Bho z4i!4%%2H|EyRD19K6~=GSWxTpLF=Q5oZJU{VSPSieR@vS2b{W6fxif9e-@G&6a8qh zBunNGQAI*t7NRWzt^&=r?xitt_W1#JiI-~UNxM6Ee`Tl?RP%bElIe+pl$b9l=uHsv zwULd0-R69UErbaXQm33YMSbkPpM5{>>8%ebC{|61yHy+8=N0@H4{*of0nL#QJ@74c z48NpY-N_f|1Kk#@SxjTlc^|3iB69Nf%&B{WD~Hr=bRFF_ABrnbq@ct+Pc!3erZTOJ zHFKsxt=AL@H~jTBf>f&=YdIDN?PEdh4_n*!?L9CyF}Z8s-el**zUz}+t5z<*Zr}A| z%O^*#Uv|yt)a3T-#`cU&E$8>DjE`-fnp{45V07u8(Q77`U-!BjcyPz=?#)5<(ywBf zTt0E*=W2zH>OoB3J9Pl+G>ar~6|sqoX_ zC+4Th&(6_Zd&YJoQ~Q$1seKb;$@YCW?&UY7oH*pz!O`n)*fTb{JZrZ>_w2exLk6D) z;`zXulflgTB%^yK#zuF%F6sW7mL18?eG^IcyIO+hcn zJdGcXGn=0-J@|DnIW?%y#~9*XV|0F53`Ce1op{}H`^7LumWk1uwjLPU4r#WJ-Y~j- z*VOAem}*+qi1( z+tww)u|82H2tJyPBVLMbl9PUZ=JGR-pM*b4k|ouFf$EY|qP+LU>m?LV0cSq_ckv^- z4jvpF99%KDa&Xn)>cKUGLxaPEBZF&K46azQV&#feD^{;qvtnq)@QRTYYgZ1gT(NTH z%2g{@uUxZoXyx$Ak(Fy#4X#?TYUQd`t5&aCvubG7@T!qjYgZ4hUa@-R>Q$>(uU@ly zX!Y>wk=1M046a$RX62eyYgVsWvu0?`@S2e|YljAhRt&8iS~awKXwA^j(D2a6(Awd_ z;T6LxhgS`+9$qs%G(0>!GQ4(VaAd{E%8^wgt4G$142=wrjEt;Z3yNzQel4Ka^4MCc zyqt?J`q3Q4$FulZkY`|0*>#?uO7-^Tur^Wm$!Qep5ZpuWHLJCC4q;m5WInBgyTE8N;h7! zY}vA3yXJLMxu8gP_U@ZXMw9K=jZS#ULd-8nc7gdM15fVSF_t6)dSo(LEPS{90kEWZ z$GD!u_3yb#$9}-I$n`lNY@>(G&)BvpBiwI^YGiGKlc!cL(NPp?Y5I=cY_CYcc6rGD)92QC?&N@}XYM~bP#tkgQhYl1naq$NS#*{@1_tH-GyBzxT;oKT#}IhF<)VSN`*3UyWz?4-LQa zs>2`t*h7E1=E>9E^yas}FYf7`b=u+;tJiJZwE1P1T)JcI>OcIW`3p+rYHjwMp|$HC z_|P~0x-xvnoez|%7rbQWu6Mk1*1oNu{=q-I`kH5-JAU~Uzw^7xmY+Lt<$LeG=ReyvZidSxhDSD06d>!r&!53lN3Ra#cA9y#X~7oT4~@637UESNo~ zatQe8VP)z??SHLKmTx#?)3492 z&#qrpncIHTkqe_YZs_)Dztl zZ!Oki*H@26nA||Qb;*${>Suw=P`Q_`l~VgJUsyd_3|v$w6pLZ0ST0p&RTtFe*5~y! zdh300BRcK0(<^7XIdQ+68_g@tcMHOWXC~44(bC#7HyEu5SGxPd4}~9&KT`hp@JEFo zhd+sqS3Y|1b#J}>1A|xn>RaD-$AbUf+jsGnA3e8h`Ae_OFf-Qz)Q0zJI$f){Uo*{>aaJB`2p$v^q*7ry+Jr@k9>#Qg%v`)hZM9li5+ z-~0J5f2C*E;&m5n+oO`5_+p%;&%L)OVlhnYD5Aj%aZvc>DVO-~3kZ!oB+zoVE2g4t?yQ!+-L~nRCuwxaq=6E|vTrI{XKp z`PyGS@ytK|%f#e6rf&T0bCxZ?|Diwn^k01C@o)Xk`gh+o_>P7D?Q35?e#xb;eod*| z*Eo0i5B_2AzTp?Ybi>9w?!5fk8$b8?$G-ZFzy97&jt9xs*3I9FZ~o=-{J1#l$b-G@ zj}#VGj?9ndmR-C&ULBVrS1OifRWIv1t#oB6iWgKXQ8_9_VH8F6xDeHfuJ??>C8hbL zt4d*UPW`g@m!hSZr&-0m`nve67j8|ikH=rw{#@bak4N*0H~%<#Rq4!1e?Wf}f8Y!P&xcT_3{_^r!OQU9A zv#i_iKXt;9Z>e=mw%k94` zRQoT8s>PA=rgFVFRXaO+b^NMI`R7bHG%<5^=16%nwPKUUjAcn#Y+Dh`__(L zvwg?d&XeGdDa!K>;Tyn`FIdfwV!Eque0`ADT|@Z={9G~dx=pMHHt(INe2oh$wbJHrKJc6y?sbetnh69uIC_A*@d-=Lqpt+A-_g1io=R4Mt=(tz_uia zVYyfh-QdC%@gU`b8>rM-{L&#Bp^*opb>%R;D{?)qqyeMwv+D!*=glCx-EB*P;;t}= z9hrg4LTo9x&kYOi-Qm2`dfYkXxwU1{Aae`DbKNgNd49(x^IGm!0W}N@%=^5s?0z7! zIfAN2L(2pA9rs%W!kDlS4@9y1An=3mvS?FnMf`d<)VG*u+OGqiN zuHYct)<~p;DDJ(S%|62@>)e^Hw-gorysXL05mn)p`nm9bf?JX6{P4=MYQ{wmTKNT- zu`2`>7yb*JMwRE5Ob6~ES(*{iw~p5E6c9eomp^wK%Hd}3p?E1JoDlh3Y4xd z1>5-4jDC+POWkdk-Y~_oeBHVm_ue!ydc(ltZ3&C?(PY~t`}U4)OYC=oc4NTFsU5Z& zyJ3_Va5upzHbZMA#dq+{;(A+^Z(qJ8b=!%h@W22)Z!#h{)+{sdBXw}Hz;ON-) zm1~B!uiCNtn$_2gEkDVI>|({ed}?BJm+}DHxBC@T5IoH|S2E6T@uRqT`k$Y+9zJpL zeu{iSmQe6<>>CgsG95w6&k}wvWxY7TRqOBEHYMC|-V1Sd?bx7@f7<;PTc@1RzuE17 d#pty&VQCF>)dZ7%1?hpy$0qDoxQ>b`{|kZeQ3e12 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index c6debdd62c406ae87145666d90d5fde3ca916747..1cf6a9ad290421d082e18f23237b4cac2fbcf79b 100755 GIT binary patch delta 2127 zcmb7FO>9(E6h8OfH=S4BjD4kl(?7iL4J}hj5f-+f275`06K4~hTtnPF`BrN zH-#1`{+4Tu8>2>+CM<@y>H-s@M&r-Ig$oy`HEPg>2~lEP_?`P^#ui26bSC%SbI(2J zJKy=~>%WPge-$s^CuO>{b8zX%(|dhtT^D$=KtYfXig&aHVZL4FX}u)s2xMoW0C`?W zDMb)Sto&_l_5Ci0@abNkCn9Y8yzLd=rQd%l4m>A?mzJyekkPZT+UT}g89&i7oM*Wf zT2*8r_IL^7Tq1TbjqDb4{1J5C}YnQIMNq3$P!VBvye3W^~cK`tYYO_vgU;~d_V62~+@fiO&B zWYrYHRZ@Ghzptl+OsgaoMloo1r{#z$*-QQ9UAYlO6PyT;8zq2=6!5J-fwYk;Cx+uE zfXkVb<_a|vL$wz>Z>W4VmVPQu+IF?Mwo~nFAIvI93%sdUlcwh0&Xv9q=j}{yMa

RgvN(8HiZiuu?;I0i(Y8kq!^&*D16JOM zBC%lKi#CX}_F8nmIA?Xd_cph~HYoQ(W2n48s8`RD5W=qLVf${m%kC;~n7DR|E3D5k zY;L;Z`-4S|a?@f&g%MNPBtuj1zSSGwHYj$pBMDD)?sgOB6`56IREa&;UMBxQ5uG`r zwnc)2MmKKZ3uU%3$KitQ8hQfp%@0ijmyf;P)i=b0aI z$~RA6GejYx013_4lCvcgzG zYqiG99+ZL00ymk1gAGTZfP*8Lo=}I(@@dqa>8WdGwfMyXWQ|%hZ#sV3l=TvMq+b;-I|NH1l8KIOe)ri1+Og3G(Y8E8Z)saOMt-ca?sRR7!5C)c%Hx@i@QHh)gV?RZ?<$3aIZj9LyKB|? LvD&E<{cV2&f=jrX delta 2195 zcmbtUO=w(I6h8N7W?tsyHLpLm`K#RbrfDbEl)7jVHDGQb8fzD|RZP1oqLRE6saUWJ z>!dbmVX`gM1~qh_Y(~% zuU+`2V&$MDqfBK`YNM=9!a2SKYr)p#u>e*&Jk3g> z_;zOI0uo#g$6jLRPx9uP&${poJEZ1iZ+dNS?p(lE;e`sh`IEk(+@bEP;w?AQQx^;F z#hz^&(;JLmo6?~4jE4Vk&VAJLTJV_?<$~FrZnNrZWGslWKyy}XP6kW9gKP<@v@73= zoH5v{d)YEAAmC10c`sYZwhh3PHVT(gUYW2+WfeyCq7v>>hDoQGjN*a_E0RdaQ7~sv zOE!Xwce2uOli(gViDuv6wlj$pE_EhpX;BwehDlsDBEY($b$fO9CJ<&yNi3}58geWn z`<3TT=vt)u6%9d4revc8$T-5zR!NCmXYYgJbaSkCQegRX^Fb+Qo1PgEV%`l#&!A3= z@i6N2bsUM)?s|N`m~++IR<}Lw5@+04yyqSkkKuGrZQrh}GyL;Hh@y^{XgU^IQ)Shv zr@7*%o`efbiuv_0tue^C-hHQ6wY;UD4c$-yu)A>g9t1#lkFHxSDA^$tK zYs<&`l^xDqg8JbEG$;;oii7MXE{Q}@2530eW2lR^l_vsWK-y>|xFJ23~J{4#*yIVzJ-q8Jy~jqH}coN=#s6=jgu%rDQ8~WzbP@5*6vU2ykdvPtGpqa zLSz(g63bUO*7h0|u(kaj8it0G3^*X`0h(Z}K(?C>1d{z6j-^qle9$rg&6tZoDF_V; zS_;OY(F%ovUDQ`W;lQh*TysBc>upTNm?J!Gr zfhm1a2G4%f=q9ee2&CB~b-PWiGlK}2iZ&FM#@Ly)TYUZjvP SrRgxfYwp-T-`szsr{f>Qg3jgu diff --git a/x/programs/examples/testdata/verify.wasm b/x/programs/examples/testdata/verify.wasm deleted file mode 100755 index 4541611cc97f4de8d98d9448565c082e765fafe6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 96454 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

UdV09fV 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 diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 6236bfadbf..842c0d8742 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::Key}; +use wasmlanche_sdk::{program::Program, public, state::Key, state_keys, types::Address}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 3b177deac2..76c3520f7d 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::Key}; +use wasmlanche_sdk::{program::Program, public, state::Key, state_keys, types::Address}; /// The program state keys. #[state_keys] @@ -83,18 +83,12 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i // update balances program .state() - .store( - StateKey::Balance(sender), - &(sender_balance - amount), - ) + .store(StateKey::Balance(sender), &(sender_balance - amount)) .expect("failed to store balance"); program .state() - .store( - StateKey::Balance(recipient), - &(recipient_balance + amount), - ) + .store(StateKey::Balance(recipient), &(recipient_balance + amount)) .expect("failed to store balance"); true diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 3611ef9ce7..34c4e8817c 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -115,7 +115,7 @@ pub fn state_keys(_attr: TokenStream, item: TokenStream) -> TokenStream { // Key types are used to pass StateKeys to the host. impl Into for #name { fn into(self) -> Key { - Key(self.to_vec()) + Key::new(self.to_vec()) } } }; diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 1298d982ba..644c0fb33a 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -32,7 +32,15 @@ pub(crate) unsafe fn put_bytes( value_ptr: *const u8, value_len: usize, ) -> i32 { - unsafe { _put(caller.id(), key.as_bytes().as_ptr(), key.len(), value_ptr, value_len) } + unsafe { + _put( + caller.id(), + key.as_bytes().as_ptr(), + key.len(), + value_ptr, + value_len, + ) + } } /// Returns the length of the bytes associated with the key from the host storage. @@ -49,10 +57,6 @@ pub(crate) unsafe fn len_bytes(caller: &Program, key: &Key) -> i32 { /// # Safety /// The caller must ensure that `key_ptr` + `key_len` points to valid memory locations. #[must_use] -pub(crate) unsafe fn get_bytes( - caller: &Program, - key: Key, - val_len: i32, -) -> i32 { +pub(crate) unsafe fn get_bytes(caller: &Program, key: Key, val_len: i32) -> i32 { unsafe { _get(caller.id(), key.as_bytes().as_ptr(), key.len(), val_len) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 92aeecb26c..dc143245aa 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -25,7 +25,7 @@ impl State { pub fn store(&self, key: K, value: &V) -> Result<(), StateError> where V: Serialize, - K: Into, + K: Into, { let value_bytes = to_vec(value).map_err(|_| StateError::Serialization)?; match unsafe { @@ -56,7 +56,7 @@ impl State { K: Into, T: DeserializeOwned, { - let key : Key = key.into(); + let key: Key = key.into(); let val_len = unsafe { len_bytes(&self.program, &key) }; let val_ptr = unsafe { get_bytes(&self.program, key, val_len) }; if val_ptr < 0 { @@ -75,11 +75,9 @@ impl State { } } - - - +/// Key is a wrapper around a Vec that represents a key in the host storage. #[derive(Debug, Default, Clone)] -pub struct Key(pub Vec); +pub struct Key(Vec); impl Key { #[must_use] @@ -102,10 +100,3 @@ impl Key { self.len() == 0 } } - -// implement from Vec for Key -impl From> for Key { - fn from(value: Vec) -> Self { - Self(value) - } -} \ No newline at end of file From f457e235aad2a064b88169e968edffb81b7628a4 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 12:57:26 -0600 Subject: [PATCH 04/74] key as ref and lint --- x/programs/examples/benchvset.cpu | Bin 303 -> 0 bytes x/programs/examples/benchvset.mem | Bin 1543 -> 0 bytes x/programs/rust/sdk_macros/src/lib.rs | 6 +++--- x/programs/rust/wasmlanche_sdk/src/host/state.rs | 4 ++-- x/programs/rust/wasmlanche_sdk/src/state.rs | 4 ++-- 5 files changed, 7 insertions(+), 7 deletions(-) delete mode 100644 x/programs/examples/benchvset.cpu delete mode 100644 x/programs/examples/benchvset.mem diff --git a/x/programs/examples/benchvset.cpu b/x/programs/examples/benchvset.cpu deleted file mode 100644 index ae62d5ad4b0184af7779f7faef845fa5c9091396..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 303 zcmV+~0nq**iwFP!00004|76awOY=Y&$MN?rcYPmPD5oGEPLiQWhn&69wFr*RE;hX$ zwUFF}OM)Hi%P;+qN}4QbYf^lCyXE*7Y-AROC zL1I(2g;pWj3Q~=;yXQ{E&h8m!X471MT~quh7Aph%uUXf%IBQPPxccm| zg#~-jnjLta5yRcv{6-%WOTC&TPmWc{DA%Lp* z%3m+3lGGqlC8@z)yw|;*K1=}B@IU^jOR_vgm*Eb4heVxq$Nsi)`AJt@Y_nP`S6Y_r z%{r;0W&GMJzf_e2ct*Drz{Re+kA9~}>Im@mle%?v_`B9$2ZD*apMKvUfa>_=*X4N= zIq)eZ%Yg&{iHTOhS9@0AAU^2sr;l`OvtpUZ%cH`J-RKsjq&-P zTv2!nc66Cq(8XQ1M}JXtZg)z*S^ur-TxA*R&dTaqqlu?w{-$x?Uw-iC3s*1v;n&TU ziHu{0zu;S05)8O+^*3{#`PCqf#o(0af07UK%(n(&GS2;SpjP$HYBZi?{Q8!%e%08% zffywz&oXZ#4sy5$~t`G4BMA;~@1y;q{o`V_h$f`ur>( zcv(8|W`{MKH{_Z%6h7V!u@CUaK9WW`PyM~uk?_+|!e~dYx0$;8$KOhL$)qka^ucs8 z&Z80ck|Y%yjCSNLiupa0C?4{(&HD1ef6p9&b}@QMDsmws?b)@?rg2mr>8cVZAW^BYp8x)NV(JoW7kCLz<5OWOCP^j*Ov^h(75)GE_)hX* z$kVy}BHi%DsPLlkh8h{6@X2*Zet624lD*AR9t`hO&;C7gB)E&t3nyba7((&iqe5rV zW+!>ZbHBOkoE$M4_wNpc2xHDd5eMUti8R#TY=5%hMdO^O;~@5=|5?n#V6gds2!`*A zVty~r27Yiew!0C%wA_&{>+TNY=`g3{6q0$p`z`2ukY`yCYKgg-pP(=UN2R=shZ-4-*hNR#fayp`6TlOam2^@sgW4+SPo42 tlV@H3k-0?NfbaO3E<3`yawLy TokenStream { } } } - // Generate the Into implementation - // This is needed to convert the enum to a Key type. - // Key types are used to pass StateKeys to the host. + + // Generate the Into implementation needed to + // convert the enum to a Key type. impl Into for #name { fn into(self) -> Key { Key::new(self.to_vec()) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 644c0fb33a..814f6f2728 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -28,7 +28,7 @@ extern "C" { #[must_use] pub(crate) unsafe fn put_bytes( caller: &Program, - key: Key, + key: &Key, value_ptr: *const u8, value_len: usize, ) -> i32 { @@ -57,6 +57,6 @@ pub(crate) unsafe fn len_bytes(caller: &Program, key: &Key) -> i32 { /// # Safety /// The caller must ensure that `key_ptr` + `key_len` points to valid memory locations. #[must_use] -pub(crate) unsafe fn get_bytes(caller: &Program, key: Key, val_len: i32) -> i32 { +pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key, val_len: i32) -> i32 { unsafe { _get(caller.id(), key.as_bytes().as_ptr(), key.len(), val_len) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index dc143245aa..39b6dd0d73 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -31,7 +31,7 @@ impl State { match unsafe { put_bytes( &self.program, - key.into(), + &key.into(), value_bytes.as_ptr(), value_bytes.len(), ) @@ -58,7 +58,7 @@ impl State { { let key: Key = key.into(); let val_len = unsafe { len_bytes(&self.program, &key) }; - let val_ptr = unsafe { get_bytes(&self.program, key, val_len) }; + let val_ptr = unsafe { get_bytes(&self.program, &key, val_len) }; if val_ptr < 0 { return Err(StateError::Read); } From a5c652cd57ee60a8936be9eb91be9abe68780dd2 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 13:16:47 -0600 Subject: [PATCH 05/74] update sdk macro naming --- x/programs/rust/sdk_macros/src/lib.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 5e9f951b54..4b58b90d22 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -24,9 +24,9 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { let full_params = input_args.iter().enumerate().map(|(index, fn_arg)| { // A typed argument is a parameter. An untyped (receiver) argument is a `self` parameter. if let FnArg::Typed(PatType { pat, ty, .. }) = fn_arg { - // ensure first parameter is Context - if index == 0 && !is_context(ty) { - panic!("First parameter must be Context."); + // ensure first parameter type is Program + if index == 0 && !is_program(ty) { + panic!("First parameter must be Program."); } if let Pat::Ident(ref pat_ident) = **pat { @@ -161,8 +161,8 @@ fn is_supported_primitive(type_path: &std::boxed::Box) -> bool { } } -/// Returns whether the type_path represents a Context type. -fn is_context(type_path: &std::boxed::Box) -> bool { +/// Returns whether the type_path represents a Program type. +fn is_program(type_path: &std::boxed::Box) -> bool { if let Type::Path(ref type_path) = **type_path { let ident = &type_path.path.segments[0].ident; let ident_str = ident.to_string(); From baa312a738d8e9b9d7a4ec037c6242cc85bd9d1f Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 13:18:12 -0600 Subject: [PATCH 06/74] forgot one is_context() method --- x/programs/rust/sdk_macros/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 4b58b90d22..357c5dc703 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -43,7 +43,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { } // add unused variable if let Pat::Wild(_) = **pat { - if is_context(ty) { + if is_program(ty) { return ( &empty_param, parse_str::("i64") From 2158524844d72333994494c48f1b4d09f1a92655 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 15:00:15 -0600 Subject: [PATCH 07/74] update public macro to convert from raw_ptr --- x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/examples/token/src/lib.rs | 2 +- x/programs/rust/sdk_macros/src/lib.rs | 11 ++++++++++- x/programs/rust/wasmlanche_sdk/src/state.rs | 12 ++++++++++++ 4 files changed, 24 insertions(+), 3 deletions(-) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index af7cfe847c..5109bef11c 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::from_raw_ptr}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index f706affdd5..d0b2b9854b 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::Address}; /// The program state keys. #[state_keys] diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 222d01f066..d951b6743f 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -61,15 +61,24 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { // Collect all parameter names and types into separate vectors. let (param_names, param_types): (Vec<_>, Vec<_>) = full_params.unzip(); + let converted_params = param_names.iter().map(|param_name| { + quote! { + // TODO: only convert from_raw_ptr if not a supported primitive type + from_raw_ptr(#param_name) + } + }); + // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; let output = quote! { + // include conversion function + // #conversion_function // Need to include the original function in the output, so contract can call itself #input #[no_mangle] pub extern "C" fn #new_name(#(#param_names: #param_types), *) #return_type { // .into() uses the From() on each argument in the iterator to convert it to the type we want. 70% sure about this statement. - #name(#(#param_names.into()),*) // This means that every parameter type must implement From(except for the supported primitive types). + #name(#(#converted_params),*) // This means that every parameter type must implement From(except for the supported primitive types). } }; diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index d7a18901ec..54b82b30e3 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -77,3 +77,15 @@ impl State { from_slice(&val).map_err(|_| StateError::InvalidBytes) } } + +pub fn from_raw_ptr(ptr: i64) -> V +where + V: serde::de::DeserializeOwned, +{ + // grab the first 4 bytes of ptr as the length + let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; + let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; + // grab the next len bytes as the value + let value = unsafe { std::slice::from_raw_parts((ptr + 4) as *const u8, len) }; + from_slice(value).unwrap() +} From 3e5b7974c87d380e27cc5280ef8640dfba55f677 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 15:37:30 -0600 Subject: [PATCH 08/74] harden public macro, and converted params logic --- x/programs/rust/sdk_macros/src/lib.rs | 59 ++++++++++++++++----- x/programs/rust/wasmlanche_sdk/src/state.rs | 4 ++ 2 files changed, 51 insertions(+), 12 deletions(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index d951b6743f..b510bd2015 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -9,6 +9,13 @@ use syn::{ parse_macro_input, parse_str, Fields, FnArg, Ident, ItemEnum, ItemFn, Pat, PatType, Type, }; +enum ParamKind { + SupportedPrimitive, + Program, + Pointer, +} + + /// An attribute procedural macro that makes a function visible to the VM host. /// It does so by wrapping the `item` tokenstream in a new function that can be called by the host. /// The wrapper function will have the same name as the original function, but with "_guest" appended to it. @@ -31,7 +38,13 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if let Pat::Ident(ref pat_ident) = **pat { let param_name = &pat_ident.ident; - // We only set the type to i64 if it is not a supported WASM primitive. + let param_descriptor = if is_supported_primitive(ty) { + ParamKind::SupportedPrimitive + } else if is_context(ty) { + ParamKind::Program + } else { + ParamKind::Pointer + }; let param_type = if is_supported_primitive(ty) { ty.to_token_stream() } else { @@ -39,16 +52,17 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { .expect("valid i64 type") .to_token_stream() }; - return (param_name, param_type); + return (param_name, (param_type, param_descriptor)); } // add unused variable if let Pat::Wild(_) = **pat { if is_context(ty) { return ( &empty_param, - parse_str::("i64") + (parse_str::("i64") .expect("valid i64 type") .to_token_stream(), + ParamKind::Program), ); } else { panic!("Unused variables only supported for Program.") @@ -58,15 +72,37 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { panic!("Unsupported function parameter format."); }); - // Collect all parameter names and types into separate vectors. - let (param_names, param_types): (Vec<_>, Vec<_>) = full_params.unzip(); - - let converted_params = param_names.iter().map(|param_name| { - quote! { - // TODO: only convert from_raw_ptr if not a supported primitive type - from_raw_ptr(#param_name) + // Converts the parameters that are pointers to their original type. + let converted_params = full_params.clone().map(|param| { + // grab param name and type from param + let (param_name, param_type) = param; + let (_, param_descriptor) = param_type; + // return the original parameter if it is a supported primitive type + match param_descriptor { + ParamKind::SupportedPrimitive => { + return quote! { + #param_name + }; + } + // use the From trait to convert from i64 to a Program struct + ParamKind::Program => { + return quote! { + #param_name.into() + }; + } + // only convert from_raw_ptr if not a supported primitive type or Program + ParamKind::Pointer => { + return quote! { + from_raw_ptr(#param_name) + }; + } } }); + + // Collect all parameter names and types into separate vectors. + let (param_names, param_types): (Vec<_>, Vec<_>) = full_params.unzip(); + let param_types = param_types.iter().map(|(param_type, _)| param_type); + // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; @@ -77,8 +113,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { #input #[no_mangle] pub extern "C" fn #new_name(#(#param_names: #param_types), *) #return_type { - // .into() uses the From() on each argument in the iterator to convert it to the type we want. 70% sure about this statement. - #name(#(#converted_params),*) // This means that every parameter type must implement From(except for the supported primitive types). + #name(#(#converted_params),*) // pass in the converted parameters } }; diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 54b82b30e3..74b11131d3 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -78,6 +78,10 @@ impl State { } } + +/// Converts a raw pointer to a deserialized value. +/// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, +/// with the subsequent [length] bytes comprising the serialized data. pub fn from_raw_ptr(ptr: i64) -> V where V: serde::de::DeserializeOwned, From 16d9dcd21c660015fa6a5ea45924e26c1fc61296 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 15:51:38 -0600 Subject: [PATCH 09/74] reorder comments --- x/programs/rust/sdk_macros/src/lib.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index b510bd2015..dc92712f00 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -74,11 +74,10 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { // Converts the parameters that are pointers to their original type. let converted_params = full_params.clone().map(|param| { - // grab param name and type from param let (param_name, param_type) = param; let (_, param_descriptor) = param_type; - // return the original parameter if it is a supported primitive type match param_descriptor { + // return the original parameter if it is a supported primitive type ParamKind::SupportedPrimitive => { return quote! { #param_name From bfb733835abeda0d88ce6f6b95704b932ca85d22 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 20 Nov 2023 23:52:10 -0600 Subject: [PATCH 10/74] HostArgument type + Vec Example(rust) --- x/programs/rust/examples/token/src/lib.rs | 13 +++- x/programs/rust/wasmlanche_sdk/src/state.rs | 27 +++++--- x/programs/rust/wasmlanche_sdk/src/types.rs | 73 ++++++++++++++++++++- 3 files changed, 103 insertions(+), 10 deletions(-) diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index d0b2b9854b..1cc74b4df4 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::{Address, VecArg}}; /// The program state keys. #[state_keys] @@ -100,6 +100,17 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i true } +#[public] +pub fn mint_to_many(program: Program, recipients: VecArg

, amounts: VecArg) -> bool { + assert_eq!(recipients.len(), amounts.len(), "invalid input"); + + for (recipient, amount) in recipients.as_vec().iter().zip(amounts.as_vec().iter()) { + mint_to(program, *recipient, *amount); + } + + true +} + /// Gets the balance of the recipient. #[public] pub fn get_balance(program: Program, recipient: Address) -> i64 { diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 74b11131d3..808f7f0df3 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -4,7 +4,7 @@ use serde_bare::{from_slice, to_vec}; use crate::{ errors::StateError, host::{get_bytes, len_bytes, put_bytes}, - program::Program, + program::Program, types::HostArgument, }; pub struct State { @@ -78,18 +78,29 @@ impl State { } } - /// Converts a raw pointer to a deserialized value. /// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, /// with the subsequent [length] bytes comprising the serialized data. +// pub fn from_raw_ptr(ptr: i64) -> V +// where +// V: serde::de::DeserializeOwned, +// { +// let (bytes, _) = bytes_and_length(ptr); +// from_slice(&bytes).expect("failed to deserialize") +// } + pub fn from_raw_ptr(ptr: i64) -> V where - V: serde::de::DeserializeOwned, -{ - // grab the first 4 bytes of ptr as the length + V: HostArgument, +{ + let (bytes, _) = bytes_and_length(ptr); + V::from_bytes(bytes) +} + +// TODO: move this logic to return a Memory struct that conatins ptr + length +pub fn bytes_and_length(ptr: i64) -> (Vec, i32) { let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; - // grab the next len bytes as the value let value = unsafe { std::slice::from_raw_parts((ptr + 4) as *const u8, len) }; - from_slice(value).unwrap() -} + (value.to_vec(), len.try_into().unwrap()) +} \ No newline at end of file diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 65ce75f064..a64be66d52 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::borrow::Cow; -use crate::program::Program; +use crate::{program::Program, state::bytes_and_length}; pub const ADDRESS_LEN: usize = 32; /// A struct that enforces a fixed length of 32 bytes which represents an address. @@ -51,6 +51,24 @@ impl Bytes32 { } } +// pub struct VecArg(Vec); +// // TODO: this should be size & not length +// pub trait HasLen { +// fn len(&self) -> usize; +// } +// impl From for VecArg +// where T: From { +// fn from(value: i64) -> Self { +// let (bytes, len) = bytes_and_length(value); +// let len = len as usize; +// let mut vec = Vec::new(); + +// vec.push(value.into()); +// Self(Bytes32::from(value)) +// } +// } + + /// Implement the Display trait for Bytes32 so that we can print it. /// Enables `to_string()` on Bytes32. impl std::fmt::Display for Bytes32 { @@ -123,3 +141,56 @@ impl Argument for Program { true } } + +pub trait HostArgument { + fn from_bytes(bytes: Vec) -> Self; +} + +impl HostArgument for Address { + fn from_bytes(bytes: Vec) -> Self { + Self::new(bytes.try_into().unwrap()) + } +} + +impl HostArgument for i64 { + fn from_bytes(bytes: Vec) -> Self { + let bytes = bytes.try_into().unwrap(); + Self::from_be_bytes(bytes) + } +} + +pub struct VecArg(Vec); + +impl VecArg { + #[must_use] + pub fn new(vec: Vec) -> Self { + Self(vec) + } + pub fn as_vec(&self) -> &Vec { + &self.0 + } + pub fn len(&self) -> usize { + self.0.len() + } +} + +impl HostArgument for VecArg +where + T: HostArgument + Argument, +{ + // we don't know how large each element T is, but we know that each element has a from_bytes method + fn from_bytes(bytes: Vec) -> Self { + // Vec to be returned + let mut vec = Vec::new(); + let mut current_byte = 0; + let num_bytes = bytes.len(); + + while current_byte < num_bytes { + let elem : T = T::from_bytes(bytes[current_byte..].to_vec()); + current_byte += elem.len(); + vec.push(elem); + } + + Self(vec) + } +} \ No newline at end of file From 17cab874ed2739906fbcd8e61509037b4ee0f840 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 00:08:15 -0600 Subject: [PATCH 11/74] added marshaling to go side, and token examples work(hype) --- x/programs/examples/testdata/token.wasm | Bin 32204 -> 34654 bytes x/programs/examples/util.go | 12 +++++++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 6f20bf1bb36381a2157ab534bda2a907835ddf59..3af4a7f6442b427bb3fb8239c5e9c7a7870c70a6 100755 GIT binary patch literal 34654 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 literal 32204 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 Date: Tue, 21 Nov 2023 01:36:27 -0600 Subject: [PATCH 12/74] letsgoo, finally passing dynamic vecs working(needs clean up(from debugging stuff(will do this tmrw, its too late))) --- x/programs/examples/counter_test.go | 4 +- x/programs/examples/testdata/token.wasm | Bin 34654 -> 67267 bytes x/programs/examples/token.go | 55 ++++++++++++++++++-- x/programs/examples/token_test.go | 6 +-- x/programs/examples/util.go | 25 +++++++-- x/programs/rust/examples/token/src/lib.rs | 6 ++- x/programs/rust/wasmlanche_sdk/src/state.rs | 8 ++- x/programs/rust/wasmlanche_sdk/src/types.rs | 27 ++++++++-- 8 files changed, 110 insertions(+), 21 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 2dd9ac1ce6..6e4aaf9aff 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -60,7 +60,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr, err := newKeyPtr(ctx, aliceKey, rt) + alicePtr, err := newPtr(ctx, aliceKey[:], rt) require.NoError(err) // create counter for alice on program 1 @@ -96,7 +96,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := newKeyPtr(ctx, aliceKey, rt2) + alicePtr2, err := newPtr(ctx, aliceKey[:], rt2) require.NoError(err) // initialize counter for alice on runtime 2 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 3af4a7f6442b427bb3fb8239c5e9c7a7870c70a6..b1164e7c97509f9ebc639b20164fafbee4a1a09c 100755 GIT binary patch literal 67267 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 diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index 5c41e39e04..ff88aee150 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -89,7 +89,7 @@ func (t *Token) Run(ctx context.Context) error { } // write alice's key to stack and get pointer - alicePtr, err := newKeyPtr(ctx, aliceKey, rt) + alicePtr, err := newPtr(ctx, aliceKey[:], rt) if err != nil { return err } @@ -101,7 +101,20 @@ func (t *Token) Run(ctx context.Context) error { } // write bob's key to stack and get pointer - bobPtr, err := newKeyPtr(ctx, bobKey, rt) + bobPtr, err := newPtr(ctx, bobKey[:], rt) + if err != nil { + return err + } + + // combine alice and bobs addresses + addresses := append(aliceKey[:], bobKey[:]...) + addressesPtr, err := newPtr(ctx, addresses, rt) + if err != nil { + return err + } + + mintValues := marshalInts(4, 12) + mintValuesPtr, err := newPtr(ctx, mintValues, rt) if err != nil { return err } @@ -159,8 +172,8 @@ func (t *Token) Run(ctx context.Context) error { return err } t.log.Debug("transferred", - zap.Int64("alice", transferToBob), - zap.Int64("to bob", transferToBob), + zap.Int64("alice", 1), + zap.Int64("to bob", 1), ) // get balance alice @@ -183,6 +196,40 @@ func (t *Token) Run(ctx context.Context) error { zap.Uint64("unit", rt.Meter().GetBalance()), ) + // perform bulk ming + _, err = rt.Call(ctx, "mint_to_many", programIDPtr, addressesPtr, mintValuesPtr) + if err != nil { + return err + } + t.log.Debug("minted many", + zap.Int64("alice", 4), + zap.Int64("to bob", 12), + ) + + + // get balance alice + result, err = rt.Call(ctx, "get_balance", programIDPtr, alicePtr) + if err != nil { + return err + } + t.log.Debug("balance", + zap.Int64("alice", result[0]), + ) + + // get balance bob + result, err = rt.Call(ctx, "get_balance", programIDPtr, bobPtr) + if err != nil { + return err + } + t.log.Debug("balance", zap.Int64("bob", result[0])) + + + fmt.Println("addresses: ", addresses) + t.log.Debug("remaining balance", + zap.Uint64("unit", rt.Meter().GetBalance()), + ) + + return nil } diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index bd4ac68be0..4574d9be68 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -24,7 +24,7 @@ var ( log = logging.NewLogger( "", logging.NewWrappedCore( - logging.Info, + logging.Debug, os.Stderr, logging.Plain.ConsoleEncoder(), )) @@ -33,8 +33,8 @@ var ( // go test -v -timeout 30s -run ^TestTokenProgram$ github.com/ava-labs/hypersdk/x/programs/examples -memprofile benchvset.mem -cpuprofile benchvset.cpu func TestTokenProgram(t *testing.T) { require := require.New(t) - maxUnits := uint64(40000) - cfg, err := runtime.NewConfigBuilder().Build() + maxUnits := uint64(400000000) + cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() require.NoError(err) program, err := newTokenProgram(maxUnits, cfg, tokenProgramBytes) require.NoError(err) diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index 499746b45d..fa436519e1 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -6,6 +6,7 @@ package examples import ( "context" "encoding/binary" + "fmt" "os" "github.com/ava-labs/avalanchego/database/memdb" @@ -14,14 +15,16 @@ import ( "github.com/ava-labs/hypersdk/x/programs/runtime" ) -func newKeyPtr(ctx context.Context, key ed25519.PublicKey, rt runtime.Runtime) (int64, error) { - ptr, err := rt.Memory().Alloc(ed25519.PublicKeyLen) +func newPtr(ctx context.Context, bytes []byte, rt runtime.Runtime) (int64, error) { + amountToAllocate := uint64(len(bytes)) + 4 + ptr, err := rt.Memory().Alloc(amountToAllocate) if err != nil { return 0, err } // write programID to memory which we will later pass to the program - err = rt.Memory().Write(ptr, marshalArg(key[:])) + fmt.Println("bytes in go", marshalArg(bytes[:])) + err = rt.Memory().Write(ptr, marshalArg(bytes[:])) if err != nil { return 0, err } @@ -38,6 +41,22 @@ func marshalArg(arg []byte) []byte { return bytes } +// func marshalArgs(args ...[]byte) []byte { +// var bytes []byte +// for _, arg := range args { +// bytes = append(bytes, arg...) +// } +// return marshalArg(bytes) +// } + +func marshalInts(ints ...int64) []byte { + bytes := make([]byte, 4 * len(ints)) + for i, val := range ints { + binary.BigEndian.PutUint32(bytes[i * 4:], uint32(val)) + } + return bytes +} + func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { priv, err := ed25519.GeneratePrivateKey() if err != nil { diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 1cc74b4df4..96140daeb1 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -101,11 +101,12 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i } #[public] -pub fn mint_to_many(program: Program, recipients: VecArg
, amounts: VecArg) -> bool { +pub fn mint_to_many(program: Program, recipients: VecArg
, amounts: VecArg) -> bool { assert_eq!(recipients.len(), amounts.len(), "invalid input"); for (recipient, amount) in recipients.as_vec().iter().zip(amounts.as_vec().iter()) { - mint_to(program, *recipient, *amount); + println!("miniting to {:?} amount {:?}", recipient, amount); + mint_to(program, *recipient, *amount as i64); } true @@ -114,6 +115,7 @@ pub fn mint_to_many(program: Program, recipients: VecArg
, amounts: VecA /// Gets the balance of the recipient. #[public] pub fn get_balance(program: Program, recipient: Address) -> i64 { + println!("getting balance for {:?}", recipient); program .state() .get(StateKey::Balance(recipient).to_vec()) diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 808f7f0df3..60a3334a9a 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -94,13 +94,17 @@ where V: HostArgument, { let (bytes, _) = bytes_and_length(ptr); + println!("bytes returned: {:?}", bytes); V::from_bytes(bytes) } +#[no_mangle] // TODO: move this logic to return a Memory struct that conatins ptr + length pub fn bytes_and_length(ptr: i64) -> (Vec, i32) { let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; - let value = unsafe { std::slice::from_raw_parts((ptr + 4) as *const u8, len) }; - (value.to_vec(), len.try_into().unwrap()) + println!("len: {}", len); + let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len + 4) }; + println!("value: {:?}", value); + (value[4..].to_vec(), len.try_into().unwrap()) } \ No newline at end of file diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index a64be66d52..829ca98882 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -133,6 +133,16 @@ impl Argument for i64 { } } + +impl Argument for i32 { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Owned(self.to_be_bytes().to_vec()) + } + fn is_primitive(&self) -> bool { + true + } +} + impl Argument for Program { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Owned(self.id().to_be_bytes().to_vec()) @@ -148,13 +158,16 @@ pub trait HostArgument { impl HostArgument for Address { fn from_bytes(bytes: Vec) -> Self { - Self::new(bytes.try_into().unwrap()) + // get first ADDRESS_LEN bytes from bytes + let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); + Self::new(bytes) } } -impl HostArgument for i64 { +impl HostArgument for i32 { fn from_bytes(bytes: Vec) -> Self { - let bytes = bytes.try_into().unwrap(); + + let bytes = bytes[..4].try_into().unwrap(); Self::from_be_bytes(bytes) } } @@ -180,13 +193,17 @@ where { // we don't know how large each element T is, but we know that each element has a from_bytes method fn from_bytes(bytes: Vec) -> Self { + println!("bytes collected: {:?}", bytes); // Vec to be returned let mut vec = Vec::new(); let mut current_byte = 0; let num_bytes = bytes.len(); - + // TODO: check logic on empty vec while current_byte < num_bytes { - let elem : T = T::from_bytes(bytes[current_byte..].to_vec()); + // copy the bytes into a new vec + println!("current_byte: {}", current_byte); + let temp_vec = bytes[current_byte..].to_vec(); + let elem : T = T::from_bytes(temp_vec); current_byte += elem.len(); vec.push(elem); } From b487e6a31c2a6a6c575f33b5e27098ef9ded3bd5 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 12:59:26 -0600 Subject: [PATCH 13/74] cleanup logs --- x/programs/examples/counter_test.go | 4 +- x/programs/examples/testdata/token.wasm | Bin 67267 -> 53001 bytes x/programs/examples/token.go | 11 +++--- x/programs/examples/token_test.go | 2 +- x/programs/examples/util.go | 39 +++++++++++--------- x/programs/rust/examples/token/src/lib.rs | 3 +- x/programs/rust/wasmlanche_sdk/src/state.rs | 3 -- x/programs/rust/wasmlanche_sdk/src/types.rs | 2 - 8 files changed, 30 insertions(+), 34 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 6e4aaf9aff..29dd12b3f6 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -60,7 +60,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr, err := newPtr(ctx, aliceKey[:], rt) + alicePtr, err := newPtr(ctx, aliceKey[:], rt, true) require.NoError(err) // create counter for alice on program 1 @@ -96,7 +96,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := newPtr(ctx, aliceKey[:], rt2) + alicePtr2, err := newPtr(ctx, aliceKey[:], rt2, true) require.NoError(err) // initialize counter for alice on runtime 2 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index b1164e7c97509f9ebc639b20164fafbee4a1a09c..b37e7152c751e6c7cfcb7c0866357f64893e3fb1 100755 GIT binary patch delta 15127 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 delta 28799 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, amounts: VecArg) -> bool { assert_eq!(recipients.len(), amounts.len(), "invalid input"); for (recipient, amount) in recipients.as_vec().iter().zip(amounts.as_vec().iter()) { - println!("miniting to {:?} amount {:?}", recipient, amount); mint_to(program, *recipient, *amount as i64); } @@ -115,7 +115,6 @@ pub fn mint_to_many(program: Program, recipients: VecArg
, amounts: VecA /// Gets the balance of the recipient. #[public] pub fn get_balance(program: Program, recipient: Address) -> i64 { - println!("getting balance for {:?}", recipient); program .state() .get(StateKey::Balance(recipient).to_vec()) diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 60a3334a9a..9cb71f5021 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -94,7 +94,6 @@ where V: HostArgument, { let (bytes, _) = bytes_and_length(ptr); - println!("bytes returned: {:?}", bytes); V::from_bytes(bytes) } @@ -103,8 +102,6 @@ where pub fn bytes_and_length(ptr: i64) -> (Vec, i32) { let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; - println!("len: {}", len); let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len + 4) }; - println!("value: {:?}", value); (value[4..].to_vec(), len.try_into().unwrap()) } \ No newline at end of file diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 829ca98882..8d691a90fb 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -193,7 +193,6 @@ where { // we don't know how large each element T is, but we know that each element has a from_bytes method fn from_bytes(bytes: Vec) -> Self { - println!("bytes collected: {:?}", bytes); // Vec to be returned let mut vec = Vec::new(); let mut current_byte = 0; @@ -201,7 +200,6 @@ where // TODO: check logic on empty vec while current_byte < num_bytes { // copy the bytes into a new vec - println!("current_byte: {}", current_byte); let temp_vec = bytes[current_byte..].to_vec(); let elem : T = T::from_bytes(temp_vec); current_byte += elem.len(); From a483cf59a1a92d36a311dd98d9a6dd383447a8eb Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 13:13:43 -0600 Subject: [PATCH 14/74] combine HostArg + Arg --- x/programs/examples/testdata/token.wasm | Bin 53001 -> 52998 bytes x/programs/rust/wasmlanche_sdk/src/state.rs | 4 +- x/programs/rust/wasmlanche_sdk/src/types.rs | 56 ++++++++++++-------- 3 files changed, 36 insertions(+), 24 deletions(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index b37e7152c751e6c7cfcb7c0866357f64893e3fb1..46140cf6797c7c52822a9bac600f525c070e7c61 100755 GIT binary patch delta 292 zcmWlRy-UPE5XC1uw;^OVmp$+!9$qr5D5p8_3W=5poQ16-SPEK5TKn^CL|YfzG?q3> zKrGKfun<8z{|jpiaZ|i`58iLyb%mD|KBVY;*8_ZC@P0k?&)JyW^h`?FXNyZRW1ECc zjxshRNu2zWgsLtk6X@DTWNh2K^p3)Su$V$wMCBTSZku5oiS`x%`GqPeF#GYL$D5&% z4ow{|cX0=01lK-XGdPt_ zm4LV?E}i`I3H%Cv0uj6!&i!3D=fJrw`CZ9peeQf$1OBn%|M^^8v!OHY+O3pDS|U$b z2VHCyD8lk)Gy<)VqsZ7EL1k=*ATzdYU%O{P3%PlN!bC-ngAVLw9Eo5T0GlQ(uw{?p zQ=jT7+t;3*#cQidfoW*hfR@q`1c6FRo};oqapb#ob^$%BlGt(WAlV3LN(R7kY#b;+ z*PbUA<&`yBu}q-O}>g!oy#JY6lf RALv~qT}C1FiBoI7=KqmhIHLdn diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 9cb71f5021..75e827984f 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -4,7 +4,7 @@ use serde_bare::{from_slice, to_vec}; use crate::{ errors::StateError, host::{get_bytes, len_bytes, put_bytes}, - program::Program, types::HostArgument, + program::Program, types::Argument, }; pub struct State { @@ -91,7 +91,7 @@ impl State { pub fn from_raw_ptr(ptr: i64) -> V where - V: HostArgument, + V: Argument, { let (bytes, _) = bytes_and_length(ptr); V::from_bytes(bytes) diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 8d691a90fb..d638137ca2 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -101,6 +101,9 @@ impl From for Bytes32 { pub trait Argument { fn as_bytes(&self) -> Cow<'_, [u8]>; + fn from_bytes(bytes: Vec) -> Self + where + Self: Sized; fn is_primitive(&self) -> bool { false } @@ -116,12 +119,23 @@ impl Argument for Bytes32 { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Borrowed(&self.0) } + fn from_bytes(bytes: Vec) -> Self + where + Self: Sized { + let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); + Self::new(bytes) + } } impl Argument for Address { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Borrowed(self.0.as_bytes()) } + fn from_bytes(bytes: Vec) -> Self { + // get first ADDRESS_LEN bytes from bytes + let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); + Self::new(bytes) + } } impl Argument for i64 { @@ -131,6 +145,10 @@ impl Argument for i64 { fn is_primitive(&self) -> bool { true } + fn from_bytes(bytes: Vec) -> Self { + let bytes = bytes[..8].try_into().unwrap(); + Self::from_be_bytes(bytes) + } } @@ -141,6 +159,10 @@ impl Argument for i32 { fn is_primitive(&self) -> bool { true } + fn from_bytes(bytes: Vec) -> Self { + let bytes = bytes[..4].try_into().unwrap(); + Self::from_be_bytes(bytes) + } } impl Argument for Program { @@ -150,25 +172,9 @@ impl Argument for Program { fn is_primitive(&self) -> bool { true } -} - -pub trait HostArgument { - fn from_bytes(bytes: Vec) -> Self; -} - -impl HostArgument for Address { - fn from_bytes(bytes: Vec) -> Self { - // get first ADDRESS_LEN bytes from bytes - let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); - Self::new(bytes) - } -} - -impl HostArgument for i32 { fn from_bytes(bytes: Vec) -> Self { - - let bytes = bytes[..4].try_into().unwrap(); - Self::from_be_bytes(bytes) + let id : i64 = i64::from_bytes(bytes); + Self::from(id) } } @@ -187,9 +193,9 @@ impl VecArg { } } -impl HostArgument for VecArg +impl Argument for VecArg where - T: HostArgument + Argument, + T: Argument, { // we don't know how large each element T is, but we know that each element has a from_bytes method fn from_bytes(bytes: Vec) -> Self { @@ -200,12 +206,18 @@ where // TODO: check logic on empty vec while current_byte < num_bytes { // copy the bytes into a new vec - let temp_vec = bytes[current_byte..].to_vec(); - let elem : T = T::from_bytes(temp_vec); + let elem : T = T::from_bytes(bytes[current_byte..].to_vec()); current_byte += elem.len(); vec.push(elem); } Self(vec) } + fn as_bytes(&self) -> Cow<'_, [u8]> { + let mut bytes = Vec::new(); + for elem in &self.0 { + bytes.extend_from_slice(&elem.as_bytes()); + } + Cow::Owned(bytes) + } } \ No newline at end of file From 1793386f9d92b1cf5b2d32aaf19056950a8ceab8 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 13:20:40 -0600 Subject: [PATCH 15/74] vec -> &[u8] --- x/programs/rust/wasmlanche_sdk/src/state.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/types.rs | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 75e827984f..e42ef4ef6b 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -94,7 +94,7 @@ where V: Argument, { let (bytes, _) = bytes_and_length(ptr); - V::from_bytes(bytes) + V::from_bytes(&bytes) } #[no_mangle] diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index d638137ca2..404098b8e0 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -101,7 +101,7 @@ impl From for Bytes32 { pub trait Argument { fn as_bytes(&self) -> Cow<'_, [u8]>; - fn from_bytes(bytes: Vec) -> Self + fn from_bytes(bytes: &[u8]) -> Self where Self: Sized; fn is_primitive(&self) -> bool { @@ -119,7 +119,7 @@ impl Argument for Bytes32 { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Borrowed(&self.0) } - fn from_bytes(bytes: Vec) -> Self + fn from_bytes(bytes: &[u8]) -> Self where Self: Sized { let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); @@ -131,7 +131,7 @@ impl Argument for Address { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Borrowed(self.0.as_bytes()) } - fn from_bytes(bytes: Vec) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { // get first ADDRESS_LEN bytes from bytes let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); Self::new(bytes) @@ -145,7 +145,7 @@ impl Argument for i64 { fn is_primitive(&self) -> bool { true } - fn from_bytes(bytes: Vec) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { let bytes = bytes[..8].try_into().unwrap(); Self::from_be_bytes(bytes) } @@ -159,7 +159,7 @@ impl Argument for i32 { fn is_primitive(&self) -> bool { true } - fn from_bytes(bytes: Vec) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { let bytes = bytes[..4].try_into().unwrap(); Self::from_be_bytes(bytes) } @@ -172,7 +172,7 @@ impl Argument for Program { fn is_primitive(&self) -> bool { true } - fn from_bytes(bytes: Vec) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { let id : i64 = i64::from_bytes(bytes); Self::from(id) } @@ -198,7 +198,7 @@ where T: Argument, { // we don't know how large each element T is, but we know that each element has a from_bytes method - fn from_bytes(bytes: Vec) -> Self { + fn from_bytes(bytes: &[u8]) -> Self { // Vec to be returned let mut vec = Vec::new(); let mut current_byte = 0; @@ -206,7 +206,7 @@ where // TODO: check logic on empty vec while current_byte < num_bytes { // copy the bytes into a new vec - let elem : T = T::from_bytes(bytes[current_byte..].to_vec()); + let elem : T = T::from_bytes(&bytes[current_byte..]); current_byte += elem.len(); vec.push(elem); } From d97f27861d0fa0ae11ed90c723cce758ca85de2a Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 13:33:38 -0600 Subject: [PATCH 16/74] avoid reallocation in as_bytes --- x/programs/examples/testdata/token.wasm | Bin 52998 -> 52716 bytes x/programs/rust/wasmlanche_sdk/src/types.rs | 26 ++++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 46140cf6797c7c52822a9bac600f525c070e7c61..55e3174c55261aa213218a9043684d4c616b4952 100755 GIT binary patch delta 8843 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 delta 9096 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 for Bytes32 { } } +/// A trait that represents an argument that can be passed to & from the host. pub trait Argument { fn as_bytes(&self) -> Cow<'_, [u8]>; fn from_bytes(bytes: &[u8]) -> Self @@ -178,10 +179,10 @@ impl Argument for Program { } } +// Represents a vector with types that implement the Argument trait. pub struct VecArg(Vec); impl VecArg { - #[must_use] pub fn new(vec: Vec) -> Self { Self(vec) } @@ -197,24 +198,33 @@ impl Argument for VecArg where T: Argument, { - // we don't know how large each element T is, but we know that each element has a from_bytes method + // Construct a VecArg from bytes fn from_bytes(bytes: &[u8]) -> Self { - // Vec to be returned - let mut vec = Vec::new(); + let mut result_vec = Vec::new(); + + // Current byte we are reading from let mut current_byte = 0; let num_bytes = bytes.len(); + // TODO: check logic on empty vec while current_byte < num_bytes { - // copy the bytes into a new vec + // Convert the bytes to the type T let elem : T = T::from_bytes(&bytes[current_byte..]); current_byte += elem.len(); - vec.push(elem); + // Add the element to the result vec + result_vec.push(elem); } - Self(vec) + Self(result_vec) } + fn as_bytes(&self) -> Cow<'_, [u8]> { - let mut bytes = Vec::new(); + if self.len() == 0 { + return Cow::Owned(Vec::new()); + } + + // avoid reallocation + let mut bytes = Vec::with_capacity(self.len() * self.0[0].len()); for elem in &self.0 { bytes.extend_from_slice(&elem.as_bytes()); } From 96190d4f212a645a7c8e612e611318581114f34e Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 13:44:37 -0600 Subject: [PATCH 17/74] temporary string example/method --- x/programs/examples/testdata/token.wasm | Bin 52716 -> 67229 bytes x/programs/examples/token.go | 13 ++++++++++++- x/programs/rust/examples/token/src/lib.rs | 5 +++++ x/programs/rust/wasmlanche_sdk/src/types.rs | 9 +++++++++ 4 files changed, 26 insertions(+), 1 deletion(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 55e3174c55261aa213218a9043684d4c616b4952..ecb319206bc0a35b11a56789bd78f22a3406f346 100755 GIT binary patch delta 25372 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, amounts: VecA true } +#[public] +pub fn print_name(_: Program, name: String) { + println!("name: {}", name); +} + /// Gets the balance of the recipient. #[public] pub fn get_balance(program: Program, recipient: Address) -> i64 { diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index afc15c441e..b8baeebdfa 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -179,6 +179,15 @@ impl Argument for Program { } } +impl Argument for String { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Owned(self.as_bytes().to_vec()) + } + fn from_bytes(bytes: &[u8]) -> Self { + String::from_utf8_lossy(bytes).to_string() + } +} + // Represents a vector with types that implement the Argument trait. pub struct VecArg(Vec); From 077d36b1eda2cb519d73f0d1bc7e14c0e7deab8a Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 13:48:56 -0600 Subject: [PATCH 18/74] remove VecArg junk --- x/programs/examples/testdata/token.wasm | Bin 67229 -> 67206 bytes x/programs/rust/examples/token/src/lib.rs | 6 ++--- x/programs/rust/wasmlanche_sdk/src/types.rs | 24 ++++---------------- 3 files changed, 8 insertions(+), 22 deletions(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index ecb319206bc0a35b11a56789bd78f22a3406f346..47ce15e629496c7c1cce85d894a3700e06d0f471 100755 GIT binary patch delta 949 zcmZXT&x_MQ6vro-={CtEbuK~BOKS;b@9cLv4o+s!8Q zC;M+KVESt)vTi5{b@DW;aV*TLRg_@@k%3`Yb%Z`P!6n=Fp^%c1rQ4!AI9*kH9r#v4 z_oevgn)ZYcAD2Ie7+;LS^2hMr{YOZ8_UZBz&1MnNBz}Np^QyJXu*F4PIiPI0v3F;MzaME9?BMP89_=9`3^mg*B*t9h|+`AL#W`P zXir`XDV_s<0Y8A$&)_%k|29pCn1#HVx9`pSzu%jEcdjqb_4OOo|8=8&Bv(nI=GW8R z#aH!_+F6#^_Tdaa5tia*rAFPFRG>(SJL4CmYFT^DX5@Qp$nON3AH9Xm|96W%2fsB$5wTv!!TBsdX&d1$9i9gLj@g( z3NBUy#Jhi-S*%JpvyGGTE{EiVAhVY4$a21ml)BIBrgnXs@ynr44P}&u-YM#l+E;Wa z1kM{qvinM`Hpm@pHd&0>KQSKRjvgzUV4hMxQK8cgA5 z!mZp!TypSeMVfrCAf#B4HB|ZnM2n!NR+AYSU$xvY2*`_pKm)4=E*SxvlsD)s|9(B Pd-d<{$?f9L?Zx;nkBXiu diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index df8aeb4270..48cb197b5b 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::{Address, VecArg}}; +use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::Address}; /// The program state keys. #[state_keys] @@ -102,10 +102,10 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i /// Mints tokens to multiple recipients. #[public] -pub fn mint_to_many(program: Program, recipients: VecArg

, amounts: VecArg) -> bool { +pub fn mint_to_many(program: Program, recipients: Vec
, amounts: Vec) -> bool { assert_eq!(recipients.len(), amounts.len(), "invalid input"); - for (recipient, amount) in recipients.as_vec().iter().zip(amounts.as_vec().iter()) { + for (recipient, amount) in recipients.iter().zip(amounts.iter()) { mint_to(program, *recipient, *amount as i64); } diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index b8baeebdfa..4982676514 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -189,21 +189,7 @@ impl Argument for String { } // Represents a vector with types that implement the Argument trait. -pub struct VecArg(Vec); - -impl VecArg { - pub fn new(vec: Vec) -> Self { - Self(vec) - } - pub fn as_vec(&self) -> &Vec { - &self.0 - } - pub fn len(&self) -> usize { - self.0.len() - } -} - -impl Argument for VecArg +impl Argument for Vec where T: Argument, { @@ -224,7 +210,7 @@ where result_vec.push(elem); } - Self(result_vec) + result_vec } fn as_bytes(&self) -> Cow<'_, [u8]> { @@ -233,10 +219,10 @@ where } // avoid reallocation - let mut bytes = Vec::with_capacity(self.len() * self.0[0].len()); - for elem in &self.0 { + let mut bytes = Vec::with_capacity(self.len() * self[0].len()); + for elem in self { bytes.extend_from_slice(&elem.as_bytes()); } Cow::Owned(bytes) } -} \ No newline at end of file +} From ffa1dd9a1ddbb8e1971b8d32116b83ea2d65c468 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 14:21:30 -0600 Subject: [PATCH 19/74] cargo fmt --- x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/sdk_macros/Cargo.toml | 5 +++++ x/programs/rust/sdk_macros/src/lib.rs | 20 ++++++++++---------- x/programs/rust/wasmlanche_sdk/src/state.rs | 13 +++++++++---- x/programs/rust/wasmlanche_sdk/src/types.rs | 13 ++++++------- 5 files changed, 31 insertions(+), 22 deletions(-) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 5109bef11c..5d62a022e6 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::from_raw_ptr}; +use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::Address}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index a16ddcf5a4..47b3c59ddf 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -6,7 +6,12 @@ edition = "2021" [lib] proc-macro = true + + [dependencies] proc-macro2 = "1.0.67" quote = "1.0.33" syn = { version = "2.0.37", features = ["full"] } + +[dev-dependencies] +wasmlanche_sdk = { version = "0.1.0", path = "../wasmlanche_sdk" } \ No newline at end of file diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index dc92712f00..aa5e11e9a4 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -15,7 +15,6 @@ enum ParamKind { Pointer, } - /// An attribute procedural macro that makes a function visible to the VM host. /// It does so by wrapping the `item` tokenstream in a new function that can be called by the host. /// The wrapper function will have the same name as the original function, but with "_guest" appended to it. @@ -59,10 +58,12 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if is_context(ty) { return ( &empty_param, - (parse_str::("i64") - .expect("valid i64 type") - .to_token_stream(), - ParamKind::Program), + ( + parse_str::("i64") + .expect("valid i64 type") + .to_token_stream(), + ParamKind::Program, + ), ); } else { panic!("Unused variables only supported for Program.") @@ -72,7 +73,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { panic!("Unsupported function parameter format."); }); - // Converts the parameters that are pointers to their original type. + // Converts the parameters that are pointers to their original type. let converted_params = full_params.clone().map(|param| { let (param_name, param_type) = param; let (_, param_descriptor) = param_type; @@ -89,19 +90,18 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { #param_name.into() }; } - // only convert from_raw_ptr if not a supported primitive type or Program - ParamKind::Pointer => { + // only convert from_raw_ptr if not a supported primitive type or Program + ParamKind::Pointer => { return quote! { from_raw_ptr(#param_name) }; } } }); - + // Collect all parameter names and types into separate vectors. let (param_names, param_types): (Vec<_>, Vec<_>) = full_params.unzip(); let param_types = param_types.iter().map(|(param_type, _)| param_type); - // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index e42ef4ef6b..680ceaa67e 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -4,7 +4,8 @@ use serde_bare::{from_slice, to_vec}; use crate::{ errors::StateError, host::{get_bytes, len_bytes, put_bytes}, - program::Program, types::Argument, + program::Program, + types::Argument, }; pub struct State { @@ -84,24 +85,28 @@ impl State { // pub fn from_raw_ptr(ptr: i64) -> V // where // V: serde::de::DeserializeOwned, -// { +// { // let (bytes, _) = bytes_and_length(ptr); // from_slice(&bytes).expect("failed to deserialize") // } +// Converts a raw pointer to a type that implements the Argument trait. +// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, +// with the subsequent [length] bytes comprising the serialized data. pub fn from_raw_ptr(ptr: i64) -> V where V: Argument, -{ +{ let (bytes, _) = bytes_and_length(ptr); V::from_bytes(&bytes) } #[no_mangle] // TODO: move this logic to return a Memory struct that conatins ptr + length +/// Returns a tuple of the bytes and length of the argument. pub fn bytes_and_length(ptr: i64) -> (Vec, i32) { let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len + 4) }; (value[4..].to_vec(), len.try_into().unwrap()) -} \ No newline at end of file +} diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 4982676514..16ae2c68de 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -56,7 +56,7 @@ impl Bytes32 { // pub trait HasLen { // fn len(&self) -> usize; // } -// impl From for VecArg +// impl From for VecArg // where T: From { // fn from(value: i64) -> Self { // let (bytes, len) = bytes_and_length(value); @@ -68,7 +68,6 @@ impl Bytes32 { // } // } - /// Implement the Display trait for Bytes32 so that we can print it. /// Enables `to_string()` on Bytes32. impl std::fmt::Display for Bytes32 { @@ -121,8 +120,9 @@ impl Argument for Bytes32 { Cow::Borrowed(&self.0) } fn from_bytes(bytes: &[u8]) -> Self - where - Self: Sized { + where + Self: Sized, + { let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); Self::new(bytes) } @@ -152,7 +152,6 @@ impl Argument for i64 { } } - impl Argument for i32 { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Owned(self.to_be_bytes().to_vec()) @@ -174,7 +173,7 @@ impl Argument for Program { true } fn from_bytes(bytes: &[u8]) -> Self { - let id : i64 = i64::from_bytes(bytes); + let id: i64 = i64::from_bytes(bytes); Self::from(id) } } @@ -204,7 +203,7 @@ where // TODO: check logic on empty vec while current_byte < num_bytes { // Convert the bytes to the type T - let elem : T = T::from_bytes(&bytes[current_byte..]); + let elem: T = T::from_bytes(&bytes[current_byte..]); current_byte += elem.len(); // Add the element to the result vec result_vec.push(elem); From 21f1d81aa7d724541371a0c41d9b48954740d5e5 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 21 Nov 2023 14:26:36 -0600 Subject: [PATCH 20/74] lint --- x/programs/rust/sdk_macros/src/lib.rs | 14 ++++++-------- x/programs/rust/wasmlanche_sdk/src/state.rs | 7 ++++++- x/programs/rust/wasmlanche_sdk/src/types.rs | 21 ++------------------- 3 files changed, 14 insertions(+), 28 deletions(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index aa5e11e9a4..7cabe2163d 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -80,21 +80,21 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { match param_descriptor { // return the original parameter if it is a supported primitive type ParamKind::SupportedPrimitive => { - return quote! { + quote! { #param_name - }; + } } // use the From trait to convert from i64 to a Program struct ParamKind::Program => { - return quote! { + quote! { #param_name.into() - }; + } } // only convert from_raw_ptr if not a supported primitive type or Program ParamKind::Pointer => { - return quote! { + quote! { from_raw_ptr(#param_name) - }; + } } } }); @@ -106,8 +106,6 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; let output = quote! { - // include conversion function - // #conversion_function // Need to include the original function in the output, so contract can call itself #input #[no_mangle] diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 680ceaa67e..079f72dd69 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -93,6 +93,7 @@ impl State { // Converts a raw pointer to a type that implements the Argument trait. // Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, // with the subsequent [length] bytes comprising the serialized data. +#[must_use] pub fn from_raw_ptr(ptr: i64) -> V where V: Argument, @@ -101,9 +102,13 @@ where V::from_bytes(&bytes) } -#[no_mangle] // TODO: move this logic to return a Memory struct that conatins ptr + length /// Returns a tuple of the bytes and length of the argument. +/// # Panics +/// Panics if the value cannot be converted from i32 to usize. +/// # Safety +/// This function is unsafe because it dereferences raw pointers. +#[must_use] pub fn bytes_and_length(ptr: i64) -> (Vec, i32) { let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 16ae2c68de..3e32d9b0ec 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; use std::borrow::Cow; -use crate::{program::Program, state::bytes_and_length}; +use crate::program::Program; pub const ADDRESS_LEN: usize = 32; /// A struct that enforces a fixed length of 32 bytes which represents an address. @@ -51,23 +51,6 @@ impl Bytes32 { } } -// pub struct VecArg(Vec); -// // TODO: this should be size & not length -// pub trait HasLen { -// fn len(&self) -> usize; -// } -// impl From for VecArg -// where T: From { -// fn from(value: i64) -> Self { -// let (bytes, len) = bytes_and_length(value); -// let len = len as usize; -// let mut vec = Vec::new(); - -// vec.push(value.into()); -// Self(Bytes32::from(value)) -// } -// } - /// Implement the Display trait for Bytes32 so that we can print it. /// Enables `to_string()` on Bytes32. impl std::fmt::Display for Bytes32 { @@ -213,7 +196,7 @@ where } fn as_bytes(&self) -> Cow<'_, [u8]> { - if self.len() == 0 { + if self.is_empty() { return Cow::Owned(Vec::new()); } From 67b69c494db3ccae9885685144fa779b34a8926c Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 01:43:19 -0600 Subject: [PATCH 21/74] flatten out tuple --- x/programs/rust/sdk_macros/Cargo.toml | 1 + x/programs/rust/sdk_macros/src/lib.rs | 13 ++++++------- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index 47b3c59ddf..969156ae57 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -12,6 +12,7 @@ proc-macro = true proc-macro2 = "1.0.67" quote = "1.0.33" syn = { version = "2.0.37", features = ["full"] } +unzip-n = "0.1.2" [dev-dependencies] wasmlanche_sdk = { version = "0.1.0", path = "../wasmlanche_sdk" } \ No newline at end of file diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 7cabe2163d..b55232eca4 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -8,6 +8,8 @@ use quote::{quote, ToTokens}; use syn::{ parse_macro_input, parse_str, Fields, FnArg, Ident, ItemEnum, ItemFn, Pat, PatType, Type, }; +use unzip_n::unzip_n; +unzip_n!(3); enum ParamKind { SupportedPrimitive, @@ -51,19 +53,18 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { .expect("valid i64 type") .to_token_stream() }; - return (param_name, (param_type, param_descriptor)); + return (param_name, param_type, param_descriptor); } // add unused variable if let Pat::Wild(_) = **pat { if is_context(ty) { return ( &empty_param, - ( parse_str::("i64") .expect("valid i64 type") .to_token_stream(), ParamKind::Program, - ), + ); } else { panic!("Unused variables only supported for Program.") @@ -75,8 +76,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { // Converts the parameters that are pointers to their original type. let converted_params = full_params.clone().map(|param| { - let (param_name, param_type) = param; - let (_, param_descriptor) = param_type; + let (param_name, _, param_descriptor) = param; match param_descriptor { // return the original parameter if it is a supported primitive type ParamKind::SupportedPrimitive => { @@ -100,8 +100,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { }); // Collect all parameter names and types into separate vectors. - let (param_names, param_types): (Vec<_>, Vec<_>) = full_params.unzip(); - let param_types = param_types.iter().map(|(param_type, _)| param_type); + let (param_names, param_types, _) = full_params.unzip_n_vec(); // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; From 378d578ba37c39ea0c7ec71481d2aeff4290290a Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 12:41:57 -0600 Subject: [PATCH 22/74] simplify ParamKind logic --- x/programs/examples/testdata/token.wasm | Bin 67206 -> 67173 bytes x/programs/rust/sdk_macros/src/lib.rs | 76 +++++++++++++----------- 2 files changed, 42 insertions(+), 34 deletions(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 47ce15e629496c7c1cce85d894a3700e06d0f471..522d16b32659a75e2d027408fa85ae4bbf687292 100755 GIT binary patch delta 645 zcmY+7O=uHQ6ou!^jETmiPMWka5=m|RE21J5M1#mEVl6HBgJ3BVrp;JWGLtYfRlCuK z(i*e{@o8#ML0!2JY<-GV!PHo*E(>n$PFxk#RacGgX(IaICw`f*;{kxutH0xGrhtG zxRd&y@*`GtK~S+;Rd*g-w`0$l^ZSmrpYA%G7)IL&?xMT?4wMOy4r#Zy0ME;3QW*~b ziA;6|>3!*fC@u}ruxq;k8~S6RHR}6snCx1<;l@J2-d1c=9 E3qIPvS^xk5 delta 704 zcmZ9KPiPZC6vpT6u1S+L?WT5H3bBn%X)RI&E0j`ER}UqJQV@EO9^$rH^M_<2n^DL` z6NGBif;bu*?L`m?Dp(m0MFguc{s9jaM7-FW2R#%74>?HUjBb=V@Z-Jrz3OOR5~W_bKL-U^|4%m+jQls z#tL#)k}l+#;uulc zWLHY}j(9vMfC8YlsLz0of8HDqA%q4v+c_#n;dF8|jyS;S;)q%71l?k$$2Zcj&ek_Z z`@CDsRIQ))#kpmY^B|z2-Ml7fxjx}5h#;qCt9R&+`VeT;-w4k9|AP=dZ6xE7!{S{{ jlbC7Q+2$n<@>!2WEHjhYa=AlX{~a3Li!^qv@!s(Z1bofy diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index b55232eca4..1431ebb7ae 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -17,6 +17,44 @@ enum ParamKind { Pointer, } +impl From<&Box> for ParamKind { + fn from(ty: &Box) -> Self { + if is_supported_primitive(ty) { + ParamKind::SupportedPrimitive + } else if is_context(ty) { + ParamKind::Program + } else { + ParamKind::Pointer + } + } +} + + +impl ParamKind { + fn converted_param_tokenstream(&self, param_name: &Ident) -> proc_macro2::TokenStream { + match self { + // return the original parameter if it is a supported primitive type + ParamKind::SupportedPrimitive => { + quote! { + #param_name + } + } + // use the From trait to convert from i64 to a Program struct + ParamKind::Program => { + quote! { + #param_name.into() + } + } + // only convert from_raw_ptr if not a supported primitive type or Program + ParamKind::Pointer => { + quote! { + from_raw_ptr(#param_name) + } + } + } + } +} + /// An attribute procedural macro that makes a function visible to the VM host. /// It does so by wrapping the `item` tokenstream in a new function that can be called by the host. /// The wrapper function will have the same name as the original function, but with "_guest" appended to it. @@ -39,13 +77,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if let Pat::Ident(ref pat_ident) = **pat { let param_name = &pat_ident.ident; - let param_descriptor = if is_supported_primitive(ty) { - ParamKind::SupportedPrimitive - } else if is_context(ty) { - ParamKind::Program - } else { - ParamKind::Pointer - }; + let param_descriptor = ty.into(); let param_type = if is_supported_primitive(ty) { ty.to_token_stream() } else { @@ -74,33 +106,9 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { panic!("Unsupported function parameter format."); }); - // Converts the parameters that are pointers to their original type. - let converted_params = full_params.clone().map(|param| { - let (param_name, _, param_descriptor) = param; - match param_descriptor { - // return the original parameter if it is a supported primitive type - ParamKind::SupportedPrimitive => { - quote! { - #param_name - } - } - // use the From trait to convert from i64 to a Program struct - ParamKind::Program => { - quote! { - #param_name.into() - } - } - // only convert from_raw_ptr if not a supported primitive type or Program - ParamKind::Pointer => { - quote! { - from_raw_ptr(#param_name) - } - } - } - }); - - // Collect all parameter names and types into separate vectors. - let (param_names, param_types, _) = full_params.unzip_n_vec(); + let (param_names, param_types, converted_params) = full_params.map(|(param_name, param_type, param_kind)| { + (param_name, param_type, param_kind.converted_param_tokenstream(param_name)) + }).unzip_n_vec(); // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; From dd66f33b9b29387bf3ac3cd6e21dbbe7c204b433 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 15:55:27 -0600 Subject: [PATCH 23/74] borsh serialization working(go/rust) --- go.mod | 1 + go.sum | 2 + x/programs/examples/testdata/token.wasm | Bin 67173 -> 73151 bytes x/programs/examples/token.go | 43 +++++----- x/programs/examples/util.go | 22 +++--- x/programs/rust/examples/token/Cargo.toml | 1 + x/programs/rust/sdk_macros/Cargo.toml | 5 +- x/programs/rust/wasmlanche_sdk/Cargo.toml | 2 +- x/programs/rust/wasmlanche_sdk/src/state.rs | 20 +---- x/programs/rust/wasmlanche_sdk/src/types.rs | 82 +++----------------- 10 files changed, 56 insertions(+), 122 deletions(-) diff --git a/go.mod b/go.mod index 80161a9918..e0ff6bc519 100644 --- a/go.mod +++ b/go.mod @@ -93,6 +93,7 @@ require ( github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect + github.com/near/borsh-go v0.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/openzipkin/zipkin-go v0.4.1 // indirect github.com/otiai10/copy v1.11.0 // indirect diff --git a/go.sum b/go.sum index f5e68bbe73..05cf428037 100644 --- a/go.sum +++ b/go.sum @@ -439,6 +439,8 @@ github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxzi github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d h1:AREM5mwr4u1ORQBMvzfzBgpsctsbQikCVpvC+tX285E= github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU= +github.com/near/borsh-go v0.3.1 h1:ukNbhJlPKxfua0/nIuMZhggSU8zvtRP/VyC25LLqPUA= +github.com/near/borsh-go v0.3.1/go.mod h1:NeMochZp7jN/pYFuxLkrZtmLqbADmnp/y1+/dL+AsyQ= github.com/neilotoole/errgroup v0.1.6 h1:PODGqPXdT5BC/zCYIMoTrwV+ujKcW+gBXM6Ye9Ve3R8= github.com/neilotoole/errgroup v0.1.6/go.mod h1:Q2nLGf+594h0CLBs/Mbg6qOr7GtqDK7C2S41udRnToE= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 522d16b32659a75e2d027408fa85ae4bbf687292..16820e73bac4c2a77dca3846ae2fabac60123b3d 100755 GIT binary patch delta 26832 zcmb__3w#vS+5Vi_OE%fvWCBS@2qCizNVo(7Vn9U5L;^uT5bt*a36KR6NP>b=cR^4< zZh8=@MTJkOXi*R>-cW<0V#R7(si0ZnW;Pd~|9=19hdr4&_xHT# zy`MANPgZ(ge!*LyRW;5Qnx=_;qF}No9*>LoWL^CgaqXUh(x4Az@wkS%+wZyY(x6}i zzbd=u`GgSi0?`|Pr-^7>_k1iq5~-=)v|z}qhtov5&~#l-%SaPmp$W}vWEyz!dehQ6 zbj(W2&hch1pv;2@TIG3#o|mWV0<|Jj z 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 delta 21569 zcmch933yc1+5bIvW-^mmlA9193rX$_TL@c33=}DFP<8|tu(*N9qJ%xf1x031R8XkM zL4%5dhy?)^1qCZADk^Pl3y4Zv_iBs%tWveDU$y%G{m!{}5FL39c{k;2m z&wI|y^Unl7UKT93CeE8FEXxuvi1JHC+PXB5PNzlsQk$Q5l-I@r>4hi_p)`HR_;X@8 zOz0Nkj-O|Qtxgx!_?#+IX)CZ-yeM*Wqp_eBPekoJE1Dk-It4*n1cTAS7DdsPt%5CE z2cwn<7T9*N9SH`5j%`KlP)S}i8ntacj&0i_4-fvwT`h6$HVoH23MB){+#5t=w-#_UPf zt0Fvkib?Jhxfcjair9E5yALew*6Wh1`V1RB?t(!RZWKdr5^Kaoh4%`lQCx9{7;)C9 z3rC-Q&c!ol&AxtN`lsS{u|mupJgsi}jBBr3aOHBbO57@L6U)R(p~U!!m#!9fiRjZi z0xyaOga{}(z9{VqXGtcLvFrh^U1dj70a^1Kr7W^y@2X{?pOiWG zF=rsi;VX!S!8$kO>|B}CYru*Z&_lM7hxvBao1XIRJuK~v86tJ^HJv%48!R^s@&UXn zT-({Bs&i-L-$!^-;e?Qm3_7=|hjP2MTBfH3-TPRUn=>dOVs6k`t3Jt14fDV!rdjYa z8P3>3qbtAGnIrskycvNvW^|r3^DlI+ ziu8*-WT1On-5ssXDXxZMU)!MgnoF?05l&1IFY7F_qtL`=RP2#442Ki)+PF7C^JQq9Yif$&5G1 z+(eYvwQ7HLEA_tfxlRxiT1TEwzR$k39TQ0lBw{R+;A99_bhzgVJ{7W~9Mv{daV z?5J`JQ{o}jrSO9AjRdpSR`(Zlu(z@DJfE!oJhEz2(;R*ha~!%^&tZ7*7a@Xab;pJl zs$1);?8b~LTPbsIGj+~tb+q-=R!=aO48(&F7f262LG{PgjN;|hw_v1N+X1FaHtJ+C zk|>F2+~p3|JDS_-`;t{B4*y;l>I@7McdzLvo0uZPz#eC!JnTcyCMBXvOUt@ zBuf&8D@ni*jJ>HoPMs$1Q)O*C>(6A2$`iL^QaCJ4rfufQL78l>*N_mfCK;4gGL!|> z4c0=}!HQaly^sQ$0aga2JA$l~7KXT=6d+q8?5Bs|*q~)`T`GW1#xw<>CoFVS%XZxY zK{uoZw>xb}pi{tDF$hdj3n*IEG-))ZbUcE~lca}3^3|Sp#Wm1uV?%7MvDuE!YQr(0 zVH<1&u!()B`lhc40A95@T}tY|l9rWO=6YR#sjp$5g+xd#t7wnx?)2XFw)x7sdrnkDGs(XtyS`0M3 zsaM5y&aG;1RgV%jk)_Rhtyru9R{5P4d%Xe_CtAk{d;P3aZ!8V(bvhTa*rU1=(Gtysn?NQ^w6qM-b0kv0KU~k2iJ|a7G>3TJ`Tc3Vh24pejZ|by7FAZKN)PSE0 z@LIAFO>6CIkc7@R;FY;a{kmI)Q0mieZdZ1ywdWk$5G7ZjgkvApqk1G!qFcKkf_K9) z@Mf5kNqIzfU9XmRKQ+CEYgH{2+4cd7APMg6q7+!MPr@SZdj$L85d_+yJVOrGKpl-Q z2&+t=3&S{WU?A(AUV(@U`_&U>7q6OR4y}j(k43#xVd{H2oQz13%*7B<*r*7-NgEit zbtxllf6@U2}=f(xv;F71$oIBXc&`$vl2lURH>`7Kvs+w^wv^z(i31|0X?I& zmPNlz8{Vwd4Z?RuC1@W4CdCc-$b1)=Dkhm#L)nY?ckSXfi z?Gx1{HPNO`iX^og>S)M7d}KhTbcCqJ3xWnm#C2!*HpW~o^Y2R z&?rSAo0x)R0=N;Gu1iHc#sZLH@;29l*$~G-l|@7Dx9W@zNs%8*OBZ8oco9nI?`pDU zWyK9FUC&vqn1l$)9sju<(1G-viPsWiUq}bom%e!IH#ViWX;Xt&Rf_wsF8rvebM7=# zW#Evd?S*ZTgSmKL{Wj1woeFU+f@X3pvbB+=FXU`u8>82B(T1jSAd*%xY-Ug9XkV_% z9+`wMUuBO0b+Sevgq9*1VT+JVkA&KXJRb=Z(-NJFnScyjmoypP7xM#*-Y9@ap?96K zcb&A{u=6m%;0(QCaPaC2HNtB^GB@T%+}t`h2aUY_h7H{g*QLT3nEzl_!qcVA;UXTq z7}X8SK+~vw(@DLv9FPoC)1n-%E)|kicWdu0d$2Q%oo+#;r44AhTCeD$IJbp1$3aVt zglp511mG@t^mDTGBd|kLloZG<(qodjwodeRL(@@^wnwJIqXD8#*Z^@e*nH4JF@P1S z1HR2rMN>09hRfB|=kOd=+H{l6c*o#++<2+58#_G>T*5%l^{@*0SkartdWugU84nez zgq{jEH76O4V-p){@|S(L7XkocqDeRj@VV|#2z+Kn3>V{W&JgbA7lFqFjzUn3S5B>6 zgcl^k0d`SfLkxkv*@2=gz&tkP?8)I5tA(eRrPn+GmcfkJ1IVp?2auD2!I~JGn5ngg zVpvk9)*gvB@N+g3CfFGNpTuTDH`GU_cjOuy7x%w;N8_C_QqP znM3#1mb=Q{$|9P>5VvWNXke(zFuMm5wGL{0v9u}S5}SoFczt@an$Wjfdee6FN0yLo zA*58du2ye<*>!13L602yy_hS5Fw=4|yF4<`y*ZhHx>GcF2-xg zMxb45k3$mFBndxyMwgsz+JN)aFhk0%B&8K|9x-q5G2sd~^vJ;P#f^&>!<{hgr0UhL zEO8SXab>gRw~wm{{eGNYMmaN^Xe+ikD8gK9vB3$N4HQz?oWq<1_4W*2U>)g&HgH$C zJxk^6Nde)Zz$}yug4Dk7nK!t(_;$>|rgC9jUceGI%v}IBK%-fUZmvD7jMaO<_KX;k zh+y5av2Mk4nl<#=b+PChlm}M&CI#lkX0L3Wm_cHo`$G&1nW5#zk*%bCABL*mm;Dvz6V%_l}tsm<8#Ex=U z+6+Qzj5tBO-2g4RFxp>mgBq3BfT++*d9%dLsz?3>_*|Ah0MVjf=Z`{p8z)t|uqpls zI@ktMAch^_^Jfk$-%5ay4c19N2`Dz~CitsV#h~`d4TQ+VvD(y8$3c17E}PoDSxp|) zqwLdWaK{>BBG)JWwut&$sze=qG?<3oLg;VGCeq%1AAZvU<7P+ zfo$Y*=E# zZeUmC{8!4jUH2*H3H#di~uH$WX%AaDX#2s2zXQu z7>ad|IY1C?vIxTvOlK)3kHRX9^t!|$yYL6n5MT}K=!7?Yn80a01r^{mV9oX#c+mR| zMuOTI_!N3{pcyrmVXy}Ub|X<(hoRo|xv;8$yqSg2`816L7de8cy8sOXFl=lTaQFa6 zNJt-6F3ljM56WhS6Y7!{_@+sXR1SA<9>ddmL6w&Z;A+VX_JJB$`VVk>Nh2+{wf1WG!q_Y2*4Nr=BF#=dRzr0@qJqn>_?Znn zK|)7&GoGlCJ`x^6Omj#CoQTR5D7P=^gPwbDe9>k6SolGp-B?PfHi6Ff(f38Rrrna58glP2(q zbfSBu_p*3rqXo9y7V*}T7OoX5!bIe^&vZ3$NIx$!Xarlsh3MN8Ll_zSuOZ#i579<) zB{ZAA*a%V&xWk5+gri%eY$zk!fgYFxL21ZdnMW+hrSbdR07n85*K^bu)$A8?Yv0r|cO z&>^zM*%=*Ls$%`CTbo5URsa-F!)X^MeFmtgn?}{yU)-wxhQaVE8a;upD@S+YYu)Io zR!j7n&yle$#yZ*&UWv0?y*v7yqGw48V4VxU2EiY&xnPm{?b(yPir}#oL(aJfOZS84 zbjbFDIcnWjo~_1m!%y-f9P5)pdie}(Oa>31El_md4LnX1>_uF|bU(r~AEe6bL}Qm0Iq z8sEK)h|thFTh!MJT>DoUReJq*y0%DlU3fud^A;R8DbU>azg?l;n|RTMhA59|q6A3} zob;5rIX(tHngYQc8eR`Tz4e9}3Ti8f)|Pz4gEiY#t-7oek$?WOD=M>SF-Dn13mJo! z8a$~guLVpAn9DUP=p0g&Q&r{SJAfjhHxTBKi{-J1ekU{%-bD_5@&i+g#OvGtG_}|k zOV#&Rv}il*V^*cyO?;)cHRO^>bmK# zmh5Vd1_I(iX-bx=i)Jj$t{VGvtM%&0jIQEk)oNx%e{I>}>p*F=L!`rF@-MMoPD zHupt}AZ_*_&NfhQ&l^~uXT$;GB3B^dWd*p@pXh9=7EQEP5}Dvrcn#Bu`|0H-_HRo#F*ZeU%K)OXg!sB)_uE`wPAizWI!Ac$9Ix zu%TO|!C(%f7_}4_xY;0VDsXB;(h8ul8{yLgR#rU2%A~+f7CS%-=c%Y?9F{K~yW(pw z0EUABFIw-hvC|Ebcu~_1dshaR@M3U{qGSREdJhb|aKej@9DaJ5>sHf6EE!57GEbJf zPO`ui$%KaqNRk8y{y#uzAkG8Cc!rhb@iM5Tx3Z4>Hzg?Hv%xK(nB?UIb3&G|K`T4y z$Zt%OH1UuD6#U)mLt+Mz=Y$*sMAb}A3O64m1xd%v*9Aiuco!&!5Qt$3L??Cn`}`3J zeSxY#qDL7C@d9j~8Qzfgmo4`!9ePfYCzgtxr^bO}E3WVB9upCV^XI zXBvDW+?uBW!z;s69j|a9%UsIMNZ8S8CsVJ5IABDjVWz0VOk(;myyTLd%3@(|bN#~> z0Y7e*5scQUTW6p8f4?;R@~R%)jyw#aaFw(CefqH%+K#f`kHvqZ3eIb-SC=KcgCv+wY=BkEYkH#mg%xG3y>ePf@BAT_ zYdJqt3$Bs&w$1AKYi<^QR)gmcYV-J_3?qiZg%2O0f+NZ;-`+&nma2{Oe6kya1BnX=56N~4zUvphTh`(qjchApAp=M6*UyPH>TJ7XkHE%(P zA%C{at|lTDhYwX{e|11Ty0BH*mlR$ZGT|TywUD3d5(J3UdkecFCXh&X#OG=0+wHG( z0KD0qMkg~2-r$9qRMOvGLzo4FbP~KJX}w!!xJ-CoW^S25I2)9}t`Do3nOePbb9>S# zcnfKC#VyrgANRX&DYv_QuXg!yV(ECsLr?b6+6`xw^f*KZV+oy3g!xC z7N-liMSwxq-ge!IgT{ECjRR42>ar2}OE(hKw(_gZgb$Z`mNgKX!1AA9@QaqW!?J%w^B)c*S|&?Q`OX zo6E(SE6zCC_-fcsE8^VZlN!SLCZn7?E;+XM{5#f>*SNpx-lhSF`NzY}1c?guaYijz zc?!-m9$i_{awGYT9iqN-Xb+%_9eG22urm3RFFAPv|G~u8!rU&E$`!W;kNrgbE9DQj$AvUJ}wW=SOUVUeo&vf9aM&H@q6#ACK9G$BB?mR8O zSu8*Y0zSBNBm)86@2UXYqwea~V*de5jk~znQ||o-)a`e*Dm=_``91!^b0Id)(Tv)8 zS9uFB65A|_vqJs(t}dtlk!%8SapnykRM{tXM?I@}kbZz;V~yf5Fs2*TSXz`NU%*f| zfTLWsps_fy)d*1xLgy?|4>S(u{lQNfPqTMCt=!ecrAsL};63aVBdZW0eNrda>1xn- z`s((18k!XNi74vf1M2?OeOfR6Ibh&5n2^85aDRJ;`h0cIF8fT~*(gAhp;+@nxXQ?b zW?nY;IHGsGV9Dsa`+)j2>&p6gdYEHOG6Y;hMl@+LF&$5A0HscYxj0}2xK;L{1M0oI z&!}E(R=sAs?Hf6Q-lxm`JQb_82@>!hdC#dWG{rSw&PQxVg<5$}TLVjx2Ma}R$1(F@g&KEng&Dix1U%J)_j>cTZJM{IAp?{V zvW1gxsuO4kWJ7DJxq_Usrnvkyk|ht{*bz84m4DXOuSy=~LJsRUbxpF}&9sEQ#3%r2 zb+R%#7XV8zpou%=JFluOYf|o}C($qoVxMB|Vsc>c9Qa#|b?BQEkEy?|Dd}v^@O0oC zm%VgMA4kX8m_DwYgb)|S$EJafwkMny+WaMoeTn!!>u;OY?M(L>fd`w28z zI*#aBKN$c_w!UiQg1oOCP*2`hYwz2s{(9e(_MZ}ctra-$&>4FGCE_T{QvuYtSpBZP zzjFBdEYY_rqXWf)RP1bh3JD$R6wp@(#THoSlP+4hfD$>!ns-f&TnhXGrX!MK>`ET zXhPs*mBwSu0oCV$Wa0>8?pfuy;(p^adNF(@;{lk?@2ZClLx&yd!L|@S;OSw8$bRU z{h={dPR5v1!gc9}wpgSVZy1+*RJ#WO7`u-*obP>oik@0re|>8BL#~~9TFrQ9QnQAK zP2s;D8exB_za$ibfre6D`m=NFMT^vTE#FsaW0|QdgKzWN#;fCI8gGdlz3E3kHea&f zOz_}+P>rQWG{t;X#F8tF{lc=&pr$^yVxf9@Q!2KY=r}jV}8wPdA}k+z9bYHAQfRi@Qv$jwVtPk&9@iF$CK&Ucx|q_sty{n;o}#bng$? zEumeNrqC=FWD}azW5VCi+f#Gl$^`5_Q15MS+hs4KKOT6;fMKFKd#t*47$JkTF!qI- zKfA9wYiuN!2SqS^aa)ZaJ0`-fl?iFiGIIUn3xTRqb$WdlRepZrm?r(bCMU-5{=<2P z#-!;>UY!oTM9{r2dA-eybB6&;yD?d~YgM-`Wj3tZSzFpijBLhURF(Lu*zH@o_S~RH zL97;3kz1RMBJ?>lXd+kZCRpkHsF*ssrFHtN7dd?aI>N_aa!f}!@Q8Wo#fSdE?{!NA zKp3(9h#3!1Zq7B6(Mx7B@It)cGF$A`EfDd_Lb-8k zg}7h6vNf4raS)U8xX~V9YjeM!PAqShz^K6}F{iJHNo!!bm;E;LNMyom{T zW#xB>DPbmlGmFPlyS))~eXYIg*z6KwVHTA&CMmIqt!6R+CtL1d3WqRqlTHvitU$=G zGkM$x#AZZpJvdyq^Rm1BUfY_r!oJ!x-s{)yGPT~AUf(?j)j5wAx6jTPutZ%}Dm0yV1bWn|Wteh2f zj}5jn2h|ggE%objG@5GYwo2Ad+crASbmYy^Dtp;M^~$y+Yd+c5w`7?&BY@5@8RsRL zD*M|5s^8<6+nWxljgP18B?nd26F0H&u_qc)xP9pMHiDH?cTD8mzu3`7&ro5%)j-?zHPmUDG<7njsd=a8pMqldjLULd{D)nYL_r{(B1+{ z`aV@TUQ3nl*pr0#8Y1s>|0n5$f@P)iCf>?7R2w+8|v2WQk27WxS1P-<>ftc z+&gzRsRwrT=;T3$3pzT5__xIE+wa5h_7MiqBP1bxX#MT3QwHn#IXi?=r-6#z*={9Z zynChPROi4a^N)ZVE251Cu%7pHOiHfVD=K203kcMT3^8C`kpUlhh8(sYu(KKuhqJ>TKV%Hl_%F?%$?&r z%^->NV7PHXwwW}J;t<2f<`c^Zc!(VjbrD411#N9lvkF*c6wvDqbw05B?5^t!`K-aE z?2TmyUun(JeL2$C+EZQV=3YIwmX>7Hvp=Ufh(1@I|E*V*!zx&e+UFi9G=n8^Kww0l zw&%GrcFcKxyR+#KdBgkU92#AI@q8s;e|i4P^vOx=n@GqrHo;aWdk=*IK}QrIr$wok zjUyuDd0k0YBlp7+=L;1Yw}TN1P`1!gUHrn(?jH2PCg?E{x9=|Q30{S(Wpg!2b6gAb z22QWP@B=vA^`gdU=Zk;os~JQSsnsc~I*8{%=TSTzUqsWa1GGLrk%Y`ZP~Ledi73;` zy%nUlySF_FHDvEzpTy08ROK&g68Cv|JKKK#ayzzd`N~_&efCOQ=32b^!YLkl-r4}v z%-3;&UPPmZFHjf+kuV5`_MMjSq=!o(BxcCIO0iB|zHdaCr}emjNjC>44-g+6R)E?6 z^}dw7?x6bHzBc*30EIjOYV!*%K$+K?1SseUQ1F)-PI2=u2N+ky2rzu>6XYN24n7+B zCv!9r{n>%okVL>ZBN+;}NoqXusUoO5Mny2gaViqU`lY7;IHP|heI3csI>Nwx3jX>D zI^v`F?63NBk^Jsg88YC9Fx~pvd`C}-qZu$9xL~5we%;e&uH7Vo>bhTR=C1zr6NR4s zWLXcsUi=#^ZP)+inHJgw;;9i1L|suvpGb}P?aVhk~|N6z(A{{iViHzN*efqlFbK(_;imn*(Ny0C(u3SiB`oy zP4@{0HQhfr*d$?^GoV)D^}YGcVFs4!{nu+^=37CKBxju}J2Zlx%N2*T2roNSdV&Z) zd8mr~eeaN-XW|=8^Z1gy{0%M1`EQ=lT$1$y;K`$J$q|_Yx<-=eSQ|;!RPiYE|C40< zI7!9~CrYxJ0u=qjo03{t@z#l2IqWS>y7vy1s0ZKD-rx_R)%)-fl>T>18R z@t~UUc1hY3N|yqC0~7*lo1696 zpt*vV0;mi-*c?9-V%$@{4X<`Fh< z9?+QJqA0*L`&apjVj6B^s*n-45bu_1wDy%5@Y|1KAunSbxm4b9>o)%X7qb_3+0d#8cb< z{_*?aOP6pbq%l2eFa=F@3cew$=)U5ge9anx>jk($u^)wX-GwDTdx%bMUO@6|$7z{WVI6wYovD55rb zxK_!u`NRPcCa83t7bfL0rDcOuZOfd0(-a4C?U0|)RNaBqJTSoc9h;?VnC6n=+%1^& zK)6R|V!O`4ww?Ry*gfY=nmy~PDfRQF&7S2>t)D&9opx#u^}^?^)mfkSJFA7|SYs{A z8jhzOo)&ocC-4;EX^F?d6U5UB59^uc)B3o4v3l( zJ8jmSD;tpCgYgo0`|U;|&GG#FIHdFN_pGs;FA`k5D(Z_l2(l=}TrzyR3d<{rv8eX4g;YKCgaK_o*`*y3e|DCPZ&gNWK1# z-?wburIJJANvaqB*|Bg;j-w~tlxtZWY)p>&=AS)M_n?@K=Helt{QPZ5m+HJ4{q?}= zPtlBI_zv$B-uNZ8%crIz~Pr1ge2|HSEzROY1d|e$q8(FH))bRGtzs?bA%D<`# zmqr{5ieRn6n|1qxYVE(OOZOs6F*%4gk$n?y@)Xs7{8yip-z$=9M7FMH?@T;P}&})ltWT?Meg=3-@F(~G$%`{@me7|7mmqytSU4)8xP-O@^|hO zqAoC~dE2(AXorVmHZP~rky`B7yqp?dji+#@RXI!sz43d91 zxl`)vXV<%&(U-HikTX(vL2={SsA#3-2U#tPa9Ay0eC9Pw*3vU=c6TJF&8FqrRowW; zsOV7m5yqg=^JNz0WiipsPL(u{h>7a4BTI}v60WJU>t{}EXqZxOV6hrdmydE%g*xiX zdUvF2@SJj7c@N}I#nZF#moZUh?t>-b02+Jv%s4HG9#hpC%19Y6FpX-Xdo!Jg8__u^u_{dQ?%|Agpa_bqFjhj;WE z*a6!5wTU?Vc5l z=|a)Z9#_%$e4!`}tgdhxkH$pnnt9!?o;Yt>_t|C%+fm_Y)FcMvV$d9=A0xk`qOolY z@kDweB;{;8{qS_dQ-LRj=f7J!)~9&h#q$e1&*FIk&wY57;F*tSI-YTOdf@q2E64f( z&oA*jhv!K=TkzbAXEC1XcrL+nHlDtCdg3W*<@B&(NPGh|`54cBJTK#U49|Kzjd&L0 zp(yi@#4Kw3O-pfVf6V5IlaKs~{CvUHW<34%ub>Yp?Y+sG-#O`IXE! zPHiRHra2Lr%%>loVPWqm{|_S81mOSx diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index bfce068ec1..647dd6b59d 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -87,34 +87,26 @@ func (t *Token) Run(ctx context.Context) error { if err != nil { return err } + var aliceKeyBytes [32]byte + copy(aliceKeyBytes[:], aliceKey[:]) // write alice's key to stack and get pointer - alicePtr, err := newPtr(ctx, aliceKey[:], rt, true) + alicePtr, err := newPtr(ctx, aliceKeyBytes, rt, true) if err != nil { return err } // generate bob keys _, bobKey, err := newKey() - if err != nil { - return err - } + var bobKeyBytes [32]byte + copy(bobKeyBytes[:], bobKey[:]) - // write bob's key to stack and get pointer - bobPtr, err := newPtr(ctx, bobKey[:], rt, true) if err != nil { return err } - // combine alice and bobs addresses - addresses := append(aliceKey[:], bobKey[:]...) - addressesPtr, err := newPtr(ctx, addresses, rt, true) - if err != nil { - return err - } - - mintValues := intsToBytes(4, 12) - mintValuesPtr, err := newPtr(ctx, mintValues, rt, true) + // write bob's key to stack and get pointer + bobPtr, err := newPtr(ctx, bobKey, rt, true) if err != nil { return err } @@ -196,6 +188,19 @@ func (t *Token) Run(ctx context.Context) error { zap.Uint64("unit", rt.Meter().GetBalance()), ) + // combine alice and bobs addresses + addresses := [][32]byte{aliceKeyBytes, bobKeyBytes} + addressesPtr, err := newPtr(ctx, addresses, rt, true) + if err != nil { + return err + } + + mintValues := []int32{4, 12} + mintValuesPtr, err := newPtr(ctx, mintValues, rt, true) + if err != nil { + return err + } + // perform bulk mint _, err = rt.Call(ctx, "mint_to_many", programIDPtr, addressesPtr, mintValuesPtr) if err != nil { @@ -225,7 +230,7 @@ func (t *Token) Run(ctx context.Context) error { // call example string function - name := []byte("Alice") + name := "hello world" namePtr, err := newPtr(ctx, name, rt, true) if err != nil { return err @@ -235,9 +240,9 @@ func (t *Token) Run(ctx context.Context) error { return err } - t.log.Debug("remaining balance", - zap.Uint64("unit", rt.Meter().GetBalance()), - ) + // t.log.Debug("remaining balance", + // zap.Uint64("unit", rt.Meter().GetBalance()), + // ) return nil diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index aa130b74fd..1d3963710f 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -13,12 +13,19 @@ import ( "github.com/ava-labs/hypersdk/crypto/ed25519" "github.com/ava-labs/hypersdk/state" "github.com/ava-labs/hypersdk/x/programs/runtime" + "github.com/near/borsh-go" ) // newPtr allocates memory and writes [bytes] to it. // If [prependLength] is true, it prepends the length of [bytes] as a uint32 to [bytes]. // It returns the pointer to the allocated memory. -func newPtr(ctx context.Context, bytes []byte, rt runtime.Runtime, prependLength bool) (int64, error) { +func newPtr(ctx context.Context, item interface{}, rt runtime.Runtime, prependLength bool) (int64, error) { + bytes, err := serializeToBytes(item) + + if err != nil { + return 0, err + } + amountToAllocate := uint64(len(bytes)); writeBytes := bytes @@ -41,6 +48,10 @@ func newPtr(ctx context.Context, bytes []byte, rt runtime.Runtime, prependLength return int64(ptr), err } +func serializeToBytes(obj interface{}) ([]byte, error) { + return borsh.Serialize(obj) +} + // marshalArg prepends the length of [arg] as a uint32 to [arg]. func marshalArg(arg []byte) []byte { // add length prefix to arg as big endian uint32 @@ -51,15 +62,6 @@ func marshalArg(arg []byte) []byte { return bytes } -// intsToBytes converts a slice of ints to a slice of bytes. -func intsToBytes(ints ...int64) []byte { - bytes := make([]byte, consts.Uint32Len * len(ints)) - for i, val := range ints { - binary.BigEndian.PutUint32(bytes[i * consts.Uint32Len:], uint32(val)) - } - return bytes -} - func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { priv, err := ed25519.GeneratePrivateKey() if err != nil { diff --git a/x/programs/rust/examples/token/Cargo.toml b/x/programs/rust/examples/token/Cargo.toml index 15b561a8d8..960ba63bbf 100644 --- a/x/programs/rust/examples/token/Cargo.toml +++ b/x/programs/rust/examples/token/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" wasmlanche_sdk = { version = "0.1.0", path = "../../wasmlanche_sdk" } serde_bytes = "0.11.5" serde ={ version = "1.0.130", features = ["derive"] } +borsh = { version = "1.2.0", features = ["derive"] } [dev-dependencies] wasmlanche_sdk = { version = "0.1.0", path = "../../wasmlanche_sdk", features = ["simulator"] } diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index 969156ae57..528f971cb1 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -12,7 +12,4 @@ proc-macro = true proc-macro2 = "1.0.67" quote = "1.0.33" syn = { version = "2.0.37", features = ["full"] } -unzip-n = "0.1.2" - -[dev-dependencies] -wasmlanche_sdk = { version = "0.1.0", path = "../wasmlanche_sdk" } \ No newline at end of file +unzip-n = "0.1.2" \ No newline at end of file diff --git a/x/programs/rust/wasmlanche_sdk/Cargo.toml b/x/programs/rust/wasmlanche_sdk/Cargo.toml index 329cd60035..2f34a539dc 100644 --- a/x/programs/rust/wasmlanche_sdk/Cargo.toml +++ b/x/programs/rust/wasmlanche_sdk/Cargo.toml @@ -10,7 +10,7 @@ thiserror = "1.0.46" serde = { version = "1.0.185", features = ["derive"] } serde_bare = "0.5.0" sdk_macros = { version = "0.1.0", path = "../sdk_macros" } - +borsh = { version = "1.2.0", features = ["derive"] } # simulator serde_json = { version = "1.0.107", optional = true } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 079f72dd69..7834314c4a 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -1,11 +1,10 @@ use serde::{de::DeserializeOwned, Serialize}; use serde_bare::{from_slice, to_vec}; - +use borsh::{BorshDeserialize, from_slice as borsh_from_slice}; use crate::{ errors::StateError, host::{get_bytes, len_bytes, put_bytes}, program::Program, - types::Argument, }; pub struct State { @@ -82,26 +81,15 @@ impl State { /// Converts a raw pointer to a deserialized value. /// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, /// with the subsequent [length] bytes comprising the serialized data. -// pub fn from_raw_ptr(ptr: i64) -> V -// where -// V: serde::de::DeserializeOwned, -// { -// let (bytes, _) = bytes_and_length(ptr); -// from_slice(&bytes).expect("failed to deserialize") -// } - -// Converts a raw pointer to a type that implements the Argument trait. -// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, -// with the subsequent [length] bytes comprising the serialized data. -#[must_use] pub fn from_raw_ptr(ptr: i64) -> V where - V: Argument, + V: BorshDeserialize, { let (bytes, _) = bytes_and_length(ptr); - V::from_bytes(&bytes) + borsh_from_slice::(&bytes).expect("failed to deserialize") } + // TODO: move this logic to return a Memory struct that conatins ptr + length /// Returns a tuple of the bytes and length of the argument. /// # Panics diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 3e32d9b0ec..169a6fe745 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -1,28 +1,25 @@ use serde::{Deserialize, Serialize}; use std::borrow::Cow; - +use borsh::{BorshDeserialize, BorshSerialize}; use crate::program::Program; pub const ADDRESS_LEN: usize = 32; /// A struct that enforces a fixed length of 32 bytes which represents an address. -#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct Address(Bytes32); + +#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Debug, BorshSerialize, BorshDeserialize)] +pub struct Address([u8; Self::LEN]); + impl Address { + pub const LEN: usize = 32; // Constructor function for Address #[must_use] pub fn new(bytes: [u8; ADDRESS_LEN]) -> Self { - Self(Bytes32::new(bytes)) + Self(bytes) } #[must_use] pub fn as_bytes(&self) -> &[u8] { - self.0.as_bytes() - } -} - -impl From for Address { - fn from(value: i64) -> Self { - Self(Bytes32::from(value)) + &self.0 } } @@ -31,53 +28,7 @@ impl IntoIterator for Address { type IntoIter = std::array::IntoIter; fn into_iter(self) -> Self::IntoIter { - IntoIterator::into_iter(self.0 .0) - } -} - -/// A struct representing a fixed length of 32 bytes. -/// This can be used for passing strings to the host. It caps the string at 32 bytes, -#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Debug)] -pub struct Bytes32([u8; Self::LEN]); -impl Bytes32 { - pub const LEN: usize = 32; - #[must_use] - pub fn new(bytes: [u8; Self::LEN]) -> Self { - Self(bytes) - } - #[must_use] - pub fn as_bytes(&self) -> &[u8] { - &self.0 - } -} - -/// Implement the Display trait for Bytes32 so that we can print it. -/// Enables `to_string()` on Bytes32. -impl std::fmt::Display for Bytes32 { - fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { - // Find the first null byte and only print up to that point. - let null_pos = self.0.iter().position(|&b| b == b'\0').unwrap_or(Self::LEN); - String::from_utf8_lossy(&self.0[..null_pos]).fmt(f) - } -} - -impl From for Bytes32 { - fn from(value: String) -> Self { - let mut bytes: [u8; Self::LEN] = [0; Self::LEN]; - bytes[..value.len()].copy_from_slice(value.as_bytes()); - Self(bytes) - } -} - -impl From for Bytes32 { - fn from(value: i64) -> Self { - let bytes: [u8; Self::LEN] = unsafe { - // We want to copy the bytes here, since [value] represents a ptr created by the host - std::slice::from_raw_parts(value as *const u8, Self::LEN) - .try_into() - .unwrap() - }; - Self(bytes) + IntoIterator::into_iter(self.0) } } @@ -98,22 +49,9 @@ pub trait Argument { } } -impl Argument for Bytes32 { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Borrowed(&self.0) - } - fn from_bytes(bytes: &[u8]) -> Self - where - Self: Sized, - { - let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); - Self::new(bytes) - } -} - impl Argument for Address { fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Borrowed(self.0.as_bytes()) + Cow::Borrowed(self.as_bytes()) } fn from_bytes(bytes: &[u8]) -> Self { // get first ADDRESS_LEN bytes from bytes From 6c45d95a79b8977ad62514d1ac02f7ee11f1b040 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 16:11:10 -0600 Subject: [PATCH 24/74] move all from serde -> borsh(except simulator) --- x/programs/examples/testdata/token.wasm | Bin 73151 -> 72853 bytes x/programs/rust/examples/verify/Cargo.toml | 8 ++++++++ x/programs/rust/examples/verify/src/main.rs | 3 +++ x/programs/rust/sdk_macros/Cargo.toml | 2 -- x/programs/rust/wasmlanche_sdk/Cargo.toml | 7 +++++-- x/programs/rust/wasmlanche_sdk/src/program.rs | 5 ++--- x/programs/rust/wasmlanche_sdk/src/state.rs | 10 ++++------ x/programs/rust/wasmlanche_sdk/src/types.rs | 3 +-- 8 files changed, 23 insertions(+), 15 deletions(-) create mode 100644 x/programs/rust/examples/verify/Cargo.toml create mode 100644 x/programs/rust/examples/verify/src/main.rs diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 16820e73bac4c2a77dca3846ae2fabac60123b3d..c3d9ddd89c84d22c4e8253f8b2d7b8c97bf05791 100755 GIT binary patch delta 7677 zcmai3349bq*6-KT!%Su}Ne7aUgOHvHkU+ReARIv&2;mYCL2gMvK!zKF5KtzBOF0Bm zAcrC#$Sn&y%Ap7m74Sk)L6lSRSVe)~vfuvvR@eRhuet}KeEt?lrMl|9SFhe(k7KWC zs}E~wO7XM_q$mo#L1{%4Qi>d*P>4cBDv$fq(uh>imKtCjO@WZ&xJF-6RFvlNMr(@C z<56Q&V0&Ucs-}`kny$s^m}#EsHR3%9iCRKUkH+3QV}OFYDRlsHWpreF*IYN?7xS3pVr@#wm>9EVdh)uSk0 zMbjKubKsYzFi^6lCMPSH0x3>S1_Mf5TyipQ$7c~GVndIV%b@x)Sl^&07ur!wZm;t8YdwXZ2|%&3y# zBZ|itPaGLp{Dz#xG3bq!?jb>N@~7FF{|hRRqr193ymB#dfJ#r$4;M5 z3uqxdOV7~;+CwkVUV4&-meE`)r+KuN*3o)eO1tT=w1aliF4{-?Y33_*$V~^yv*%OC zm*HcMMMOtMp>t!(in6jY#Za?U#b1qoX@8?)a!;)1F=Lo`R^MrDeDQQ099Q7SIw&Qmf#9}TC_u?c>)~_#c%`O zbopI?FkFC8!E^yw*7T!%X|EJ@0iW%RtT;?PSO>Jr6p#G;Ss?Ajud=4eB)w9ak_uV+NG@z)(u!B#YW+5#mzJ<( zNUWu*c)JmWaE55KElJ%~CiZQQPXw2iL8bu6VW`2Ds@vO57*8aK%ieSn;x})5nk(|7 z>(F&EBDw_g&!TH%{ActuS}lUUlWE`qXZkd-1m>l+ffp@^kGOKtD+V~>H)EoR%Ebq< zy?|Ov&we-%XM*8&le+VWKyNLGBq*0sYW8H z`bu#$K8Icux8v(3+INN%Myw|m0uYT8f(=$PYku4@B18znTSGBm1DN6JQgNo@JpkGX z;V%+=ly0p-q<6?+Uk8qbAYyBtkGdmfajWLcRJBbp^p;Da`p@-ZI_F>UiV#{8_mF6O`Zlf9Ol z{WwJv*8;8Rh)B)ImZRTGu%>9$3zOhgzgU$~omPnL8SQD8_%`Ekn$57uMsv?xq}R=W zEIZY$8;Z#Ct|ziArGmY?G;&6q<*G6+K(@D#skBk@pz^FBhPOEL?nth zAnY&CukxW;YOMf5R+eh;&@Q0yuMU>yap*PFs-cMKW~oU9z7Whe;&@K!QtDmis`7?# zUnN9TCjnL~YvrCw}kt#DiOImvf&Rlq}k1Z24PC0ruIg{NhW<2-t$ z{tntJo@}r&;=y_B*`gpjmR=J5vj@|e@V@MpfDC`vZ~_6ef8$Fo+t~#*ZY3r+sfE>L zO?uKt;)^EJkw^P9ofz|$40BN&^<4Uq@cT_?$)w%94vrk(ygkO<%?AM1(c)1X*2l2b z;0&cLrefpA7MZk7#OFK)&?Pwr#yvTVc0Fe{7#owD8D~Wz7=nilBT7FiHs+@IBJNO4 zCg&5mZ-Un1mPK%_>n-QNwSujh&}U+Os|B$y+d_;sJitCD8t1(Ls55yJfN@{zQk-?T zbs%C|KAHBsIOKZk^!l$@sOAbwLFTWln@EX)Fmy@@8ZKPsfN0TXwD%xG`y5<5h^=jM z5)bh=8+4Z1hgrw(ejt3KO)IColPGpJ5dGTnou{`QNQcGgw(lWuuWwgQWg;y<-FG(| zw*y|c{9b@uo8OwYh>!F0qh7U`(_a%w?H40D&*|4+{MdkrP}SX}OXDgG0tf#?^7Qpag{AosYr;=?|V*c;mKHwqsZ0)DqV zQ11>NDxtf0mmX+}?U=p~(kEg>-z?0R^i4xX+u650=6~z!$DEC7_=EQv)j7GN_REK1 zbm*5TlqOl8j4v) z=Dy{Xa5LNaezznhKhy}Cc>bZ*M6ZbR1DbH9|mbStI$7E+eNCy)2GAQWxV_k9FNkRqa&Uni6N=$?o{8;UKUs1W zaT9BZ5fcw%uhyg<7$2R~ALes((kv*h_2g2F;mH~C5p!`=u^{ooOW@9E3lg$~Xzrnx}lt446M}<=aL6P%z**?_1 zV&UVqtzw@1#D934GZXw)%xP0&2g^v-ILFv*k&SnVD{~ql;QKNEaE6RagYV0pX7W* zCq;{Sxe)ExdHpdSo0qFg^YgQ#$^?5_X!HHu?kvKbto3DlZxDO`KqZ9Yl7?mqX3C;oo(j;)(O?1QBzphxQ285T@5)Nj{wuk1nZg!5dm5MG1IK zt;;$S)x(`|DYXOl4Kz!UoWJpPr~QFmhB&o+Hb{0}(dkb}if&KWmI+cC zguYJ1uH-ycx^fe|CZ(dIu|=M9=cQLAjIihbyG%S@(G0cQ-iq3ELVQq>o3L1#16xeM zs?Y+OenQj~b!uDg&2P~%?e1ffuV5(pSuseY)sY}3`JG&(<2EL;j9$qs1e~~CHCYs{ z7Y~BP8=?SX&Z>HF&mpUpV}5;Adx)&T>ePtHAPLcXbzN&Q5_`Z|Jk~d?-UpOk&y1l( z;=nV*qJQB-zzcU>#O7z>v7ED}$Y&S1UO11wO>ADXhPI2=Ynx#lxAqzc^j_BnYZhg4fpr^#G&2wx~E_>n6MS1>(dvyX)-qlGzNu=GM>f-w?Hi5jm zO1(<}szu#mpdAtMr+=|EpnLQ@AA#Rce9_hn*z)|XML6o4tq<9+q`Mv9?k_IG&iNN7 z&|>kI?FmjqRH&+G+XL!GB>RM`LTpc!TeT2N-rrsh;NCl0S0Uq;Z`CzB`oz8Ye{79_T%Mz|L(ex?%;8ej&9`g z-5t=4{AhPNj=8nFK}hBvgnQ&(Jm6rUExEmJ-r)Yc=|KdG4w{>|BdLv$KF98g{lpV;%72bs70 z;1hJR;!qt->mC}Gev%hx&LWj2}gaelq;)p z3y(R~(3ST(;|8p^ocVZ=z1A^>eIB5&7g@xlz@5F{yUEKfUj=)lzb@YU@EtlHUj0!! zN9=K?VW6tQHg8@1q^Z~XuL%Oz$HJ+fR(H|sqVa_@biCr?!*pB>znJWkC(9=>cQqGW ztV17)T^DQBkZ}iEFsKK!0VX~XpI;n7Z;N)9+NQqCXDQxfMeSgsfLV2^lCO^TpZOLE$ZHoROH+L3-`#G`+nmWjzeSaKd!9>! zJWM>bS$Gv6qWaBw&H;*|q>1%6)2T50>do6K)f9XG-h$G^SAWl@3=wlXJFYQ6Jop*x z&=vfLlhRgnznw|##MImOQD^a2%)5&(ZfC~z#GbPX+(1$NA8nfr#!6M}B7DbGfg16L x{a|>`KMMVjm!j}be??hSnLtk^M`!9vHWo(Vrw~7p@6l^UBvR(Vb%|8Z^?&9Ibr=8u delta 7665 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 X-!+~x_1c(n+JAZTV-w@4ZrFbV$6si^ diff --git a/x/programs/rust/examples/verify/Cargo.toml b/x/programs/rust/examples/verify/Cargo.toml new file mode 100644 index 0000000000..813ce7aa4b --- /dev/null +++ b/x/programs/rust/examples/verify/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "verify" +version = "0.1.0" +edition = "2021" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] diff --git a/x/programs/rust/examples/verify/src/main.rs b/x/programs/rust/examples/verify/src/main.rs new file mode 100644 index 0000000000..e7a11a969c --- /dev/null +++ b/x/programs/rust/examples/verify/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index 528f971cb1..93fb1a35cb 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -6,8 +6,6 @@ edition = "2021" [lib] proc-macro = true - - [dependencies] proc-macro2 = "1.0.67" quote = "1.0.33" diff --git a/x/programs/rust/wasmlanche_sdk/Cargo.toml b/x/programs/rust/wasmlanche_sdk/Cargo.toml index 2f34a539dc..44bfc8b414 100644 --- a/x/programs/rust/wasmlanche_sdk/Cargo.toml +++ b/x/programs/rust/wasmlanche_sdk/Cargo.toml @@ -7,10 +7,13 @@ edition = "2021" [dependencies] thiserror = "1.0.46" -serde = { version = "1.0.185", features = ["derive"] } -serde_bare = "0.5.0" sdk_macros = { version = "0.1.0", path = "../sdk_macros" } borsh = { version = "1.2.0", features = ["derive"] } + +# TODO: delete serde dependencies(simulator needs update) +serde = { version = "1.0.185", features = ["derive"] } +serde_bare = "0.5.0" + # simulator serde_json = { version = "1.0.107", optional = true } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 97bcfc5639..9f7a7b463b 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,9 +1,8 @@ use crate::{host::call_program, state::State, types::Argument}; -use serde::{Deserialize, Serialize}; - +use borsh::{BorshSerialize, BorshDeserialize}; /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. -#[derive(Clone, Copy, Serialize, Deserialize)] +#[derive(Clone, Copy, BorshSerialize, BorshDeserialize)] pub struct Program { id: i64, } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 7834314c4a..8e818a4343 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -1,6 +1,4 @@ -use serde::{de::DeserializeOwned, Serialize}; -use serde_bare::{from_slice, to_vec}; -use borsh::{BorshDeserialize, from_slice as borsh_from_slice}; +use borsh::{BorshSerialize, BorshDeserialize, to_vec, from_slice}; use crate::{ errors::StateError, host::{get_bytes, len_bytes, put_bytes}, @@ -24,7 +22,7 @@ impl State { /// serialized or if the host fails to handle the operation. pub fn store(&self, key: K, value: &V) -> Result<(), StateError> where - V: Serialize, + V: BorshSerialize, K: AsRef<[u8]>, { let value_bytes = to_vec(value).map_err(|_| StateError::Serialization)?; @@ -55,7 +53,7 @@ impl State { pub fn get(&self, key: K) -> Result where K: AsRef<[u8]>, - T: DeserializeOwned, + T: BorshDeserialize, { let key_ptr = key.as_ref().as_ptr(); let key_len = key.as_ref().len(); @@ -86,7 +84,7 @@ where V: BorshDeserialize, { let (bytes, _) = bytes_and_length(ptr); - borsh_from_slice::(&bytes).expect("failed to deserialize") + from_slice::(&bytes).expect("failed to deserialize") } diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 169a6fe745..40d44a0d7f 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -1,4 +1,3 @@ -use serde::{Deserialize, Serialize}; use std::borrow::Cow; use borsh::{BorshDeserialize, BorshSerialize}; use crate::program::Program; @@ -6,7 +5,7 @@ use crate::program::Program; pub const ADDRESS_LEN: usize = 32; /// A struct that enforces a fixed length of 32 bytes which represents an address. -#[derive(Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Debug, BorshSerialize, BorshDeserialize)] +#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub struct Address([u8; Self::LEN]); From 033004acd7a85583ba1ab8add3e0e0bd05d184b7 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 17:00:27 -0600 Subject: [PATCH 25/74] call_program function --- x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/sdk_macros/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/program.rs | 34 +++-- x/programs/rust/wasmlanche_sdk/src/types.rs | 118 +----------------- 4 files changed, 29 insertions(+), 127 deletions(-) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 5d62a022e6..af7cfe847c 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 1431ebb7ae..bc473f732f 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -48,7 +48,7 @@ impl ParamKind { // only convert from_raw_ptr if not a supported primitive type or Program ParamKind::Pointer => { quote! { - from_raw_ptr(#param_name) + wasmlanche_sdk::state::from_raw_ptr(#param_name) } } } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 9f7a7b463b..4d7908c551 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,5 +1,6 @@ -use crate::{host::call_program, state::State, types::Argument}; -use borsh::{BorshSerialize, BorshDeserialize}; +use crate::{host::call_program, state::State, types::is_primitive}; +use borsh::{BorshSerialize, BorshDeserialize, to_vec}; + /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. #[derive(Clone, Copy, BorshSerialize, BorshDeserialize)] @@ -25,13 +26,15 @@ impl Program { /// # Safety /// The caller must ensure that `function_name` + `args` point to valid memory locations. #[must_use] - pub fn call_program( + pub fn call_program( &self, target: &Program, max_units: i64, function_name: &str, - args: &[Box], - ) -> i64 { + args: &[Box], + ) -> i64 + where + T: BorshSerialize { call_program( self, target, @@ -55,23 +58,32 @@ impl From for Program { } /// Marshals arguments into byte slice which can be unpacked by the host. -fn marshal_args(args: &[Box]) -> Vec { +/// Every argument is first prepended with its length and a flag indicating if +/// it is a primitive type. +fn marshal_args(args: &[Box]) -> Vec +where T: BorshSerialize { use std::mem::size_of; // Size of meta data for each argument const META_SIZE: usize = size_of::() + 1; // Calculate the total size of the combined byte slices - let total_size = args.iter().map(|cow| cow.len() + META_SIZE).sum(); + let total_size = args.iter().map(|cow| to_vec(&cow).expect("Unable to Serialize").len() + META_SIZE).sum(); // Create a mutable Vec to hold the combined bytes let mut bytes = Vec::with_capacity(total_size); for arg in args { // if we want to be efficient we dont need to add length of bytes if its an int - let len = i64::try_from(arg.len()).expect("Error converting to i64"); - bytes.extend_from_slice(&len.as_bytes()); - bytes.extend_from_slice(&[u8::from(arg.is_primitive())]); - bytes.extend_from_slice(&arg.as_bytes()); + let arg_bytes = to_vec(&arg).expect("Unable to Serialize"); + let len = arg_bytes.len() as i64; + bytes.extend_from_slice(len.to_be_bytes().as_ref()); + + // TODO: check if type of arg is a primitive. Don't think this is a good way to do it, especially + // because some types can be 4 or 8 length + bytes.extend_from_slice(&[u8::from(is_primitive::())]); + + // Add the bytes of the argument + bytes.extend_from_slice(arg_bytes.as_slice()); } bytes } diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 40d44a0d7f..b2c0e15051 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -31,117 +31,7 @@ impl IntoIterator for Address { } } -/// A trait that represents an argument that can be passed to & from the host. -pub trait Argument { - fn as_bytes(&self) -> Cow<'_, [u8]>; - fn from_bytes(bytes: &[u8]) -> Self - where - Self: Sized; - fn is_primitive(&self) -> bool { - false - } - fn len(&self) -> usize { - self.as_bytes().len() - } - fn is_empty(&self) -> bool { - self.len() == 0 - } -} - -impl Argument for Address { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Borrowed(self.as_bytes()) - } - fn from_bytes(bytes: &[u8]) -> Self { - // get first ADDRESS_LEN bytes from bytes - let bytes = bytes[..ADDRESS_LEN].try_into().unwrap(); - Self::new(bytes) - } -} - -impl Argument for i64 { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } - fn from_bytes(bytes: &[u8]) -> Self { - let bytes = bytes[..8].try_into().unwrap(); - Self::from_be_bytes(bytes) - } -} - -impl Argument for i32 { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } - fn from_bytes(bytes: &[u8]) -> Self { - let bytes = bytes[..4].try_into().unwrap(); - Self::from_be_bytes(bytes) - } -} - -impl Argument for Program { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.id().to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } - fn from_bytes(bytes: &[u8]) -> Self { - let id: i64 = i64::from_bytes(bytes); - Self::from(id) - } -} - -impl Argument for String { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.as_bytes().to_vec()) - } - fn from_bytes(bytes: &[u8]) -> Self { - String::from_utf8_lossy(bytes).to_string() - } -} - -// Represents a vector with types that implement the Argument trait. -impl Argument for Vec -where - T: Argument, -{ - // Construct a VecArg from bytes - fn from_bytes(bytes: &[u8]) -> Self { - let mut result_vec = Vec::new(); - - // Current byte we are reading from - let mut current_byte = 0; - let num_bytes = bytes.len(); - - // TODO: check logic on empty vec - while current_byte < num_bytes { - // Convert the bytes to the type T - let elem: T = T::from_bytes(&bytes[current_byte..]); - current_byte += elem.len(); - // Add the element to the result vec - result_vec.push(elem); - } - - result_vec - } - - fn as_bytes(&self) -> Cow<'_, [u8]> { - if self.is_empty() { - return Cow::Owned(Vec::new()); - } - - // avoid reallocation - let mut bytes = Vec::with_capacity(self.len() * self[0].len()); - for elem in self { - bytes.extend_from_slice(&elem.as_bytes()); - } - Cow::Owned(bytes) - } -} +pub fn is_primitive() -> bool { + // Check if the type is a supported primitive (i64 or i32 or bool) + std::mem::size_of::() == std::mem::size_of::() || std::mem::size_of::() == std::mem::size_of::() || std::mem::size_of::() == std::mem::size_of::() +} \ No newline at end of file From 4c15795d89733a95af9c75199757600cce408581 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 17:07:03 -0600 Subject: [PATCH 26/74] re added arg types, going to address call_program in another pr --- x/programs/rust/wasmlanche_sdk/src/program.rs | 36 +++++------- x/programs/rust/wasmlanche_sdk/src/types.rs | 56 +++++++++++++++++-- 2 files changed, 65 insertions(+), 27 deletions(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 4d7908c551..60757cd3de 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,9 +1,10 @@ -use crate::{host::call_program, state::State, types::is_primitive}; -use borsh::{BorshSerialize, BorshDeserialize, to_vec}; +use borsh::{BorshDeserialize, BorshSerialize}; + +use crate::{host::call_program, state::State, types::Argument}; /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. -#[derive(Clone, Copy, BorshSerialize, BorshDeserialize)] +#[derive(Clone, Copy, BorshDeserialize, BorshSerialize)] pub struct Program { id: i64, } @@ -26,15 +27,13 @@ impl Program { /// # Safety /// The caller must ensure that `function_name` + `args` point to valid memory locations. #[must_use] - pub fn call_program( + pub fn call_program( &self, target: &Program, max_units: i64, function_name: &str, - args: &[Box], - ) -> i64 - where - T: BorshSerialize { + args: &[Box], + ) -> i64 { call_program( self, target, @@ -58,32 +57,23 @@ impl From for Program { } /// Marshals arguments into byte slice which can be unpacked by the host. -/// Every argument is first prepended with its length and a flag indicating if -/// it is a primitive type. -fn marshal_args(args: &[Box]) -> Vec -where T: BorshSerialize { +fn marshal_args(args: &[Box]) -> Vec { use std::mem::size_of; // Size of meta data for each argument const META_SIZE: usize = size_of::() + 1; // Calculate the total size of the combined byte slices - let total_size = args.iter().map(|cow| to_vec(&cow).expect("Unable to Serialize").len() + META_SIZE).sum(); + let total_size = args.iter().map(|cow| cow.len() + META_SIZE).sum(); // Create a mutable Vec to hold the combined bytes let mut bytes = Vec::with_capacity(total_size); for arg in args { // if we want to be efficient we dont need to add length of bytes if its an int - let arg_bytes = to_vec(&arg).expect("Unable to Serialize"); - let len = arg_bytes.len() as i64; - bytes.extend_from_slice(len.to_be_bytes().as_ref()); - - // TODO: check if type of arg is a primitive. Don't think this is a good way to do it, especially - // because some types can be 4 or 8 length - bytes.extend_from_slice(&[u8::from(is_primitive::())]); - - // Add the bytes of the argument - bytes.extend_from_slice(arg_bytes.as_slice()); + let len = i64::try_from(arg.len()).expect("Error converting to i64"); + bytes.extend_from_slice(&len.as_bytes()); + bytes.extend_from_slice(&[u8::from(arg.is_primitive())]); + bytes.extend_from_slice(&arg.as_bytes()); } bytes } diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index b2c0e15051..e6cd135a8f 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -31,7 +31,55 @@ impl IntoIterator for Address { } } -pub fn is_primitive() -> bool { - // Check if the type is a supported primitive (i64 or i32 or bool) - std::mem::size_of::() == std::mem::size_of::() || std::mem::size_of::() == std::mem::size_of::() || std::mem::size_of::() == std::mem::size_of::() -} \ No newline at end of file +/// A trait that represents an argument that can be passed to & from the host. +pub trait Argument { + fn as_bytes(&self) -> Cow<'_, [u8]>; + fn is_primitive(&self) -> bool { + false + } + fn len(&self) -> usize { + self.as_bytes().len() + } + fn is_empty(&self) -> bool { + self.len() == 0 + } +} + +impl Argument for Address { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Borrowed(self.as_bytes()) + } +} + +impl Argument for i64 { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Owned(self.to_be_bytes().to_vec()) + } + fn is_primitive(&self) -> bool { + true + } +} + +impl Argument for i32 { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Owned(self.to_be_bytes().to_vec()) + } + fn is_primitive(&self) -> bool { + true + } +} + +impl Argument for Program { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Owned(self.id().to_be_bytes().to_vec()) + } + fn is_primitive(&self) -> bool { + true + } +} + +impl Argument for String { + fn as_bytes(&self) -> Cow<'_, [u8]> { + Cow::Owned(self.as_bytes().to_vec()) + } +} From 8dd98dc2557a05051cab09ca505b4f456eb0b6b5 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 17:25:57 -0600 Subject: [PATCH 27/74] unsafe + temp removal --- x/programs/examples/token.go | 12 ------------ x/programs/rust/examples/token/src/lib.rs | 7 +------ x/programs/rust/sdk_macros/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/state.rs | 15 +++++++++++---- 4 files changed, 13 insertions(+), 23 deletions(-) diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index 647dd6b59d..d376c554d3 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -228,18 +228,6 @@ func (t *Token) Run(ctx context.Context) error { } t.log.Debug("balance", zap.Int64("bob", result[0])) - - // call example string function - name := "hello world" - namePtr, err := newPtr(ctx, name, rt, true) - if err != nil { - return err - } - _, err = rt.Call(ctx, "print_name", programIDPtr, namePtr) - if err != nil { - return err - } - // t.log.Debug("remaining balance", // zap.Uint64("unit", rt.Meter().GetBalance()), // ) diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 48cb197b5b..ade0ad7992 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state::from_raw_ptr, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; /// The program state keys. #[state_keys] @@ -112,11 +112,6 @@ pub fn mint_to_many(program: Program, recipients: Vec
, amounts: Vec i64 { diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index bc473f732f..26dbe34f23 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -48,7 +48,7 @@ impl ParamKind { // only convert from_raw_ptr if not a supported primitive type or Program ParamKind::Pointer => { quote! { - wasmlanche_sdk::state::from_raw_ptr(#param_name) + wasmlanche_sdk::state::from_raw_ptr(#param_name) } } } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 8e818a4343..4379663406 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -79,11 +79,13 @@ impl State { /// Converts a raw pointer to a deserialized value. /// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, /// with the subsequent [length] bytes comprising the serialized data. +/// Safety +/// This function is unsafe because it dereferences raw pointers. pub fn from_raw_ptr(ptr: i64) -> V where V: BorshDeserialize, { - let (bytes, _) = bytes_and_length(ptr); + let (bytes, _) = unsafe { bytes_and_length(ptr) }; from_slice::(&bytes).expect("failed to deserialize") } @@ -95,9 +97,14 @@ where /// # Safety /// This function is unsafe because it dereferences raw pointers. #[must_use] -pub fn bytes_and_length(ptr: i64) -> (Vec, i32) { +pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { + type LenType = u32; + let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; - let len = u32::from_be_bytes(len.try_into().unwrap()) as usize; + + assert_eq!(len.len(), std::mem::size_of::()); + let len = LenType::from_be_bytes(len.try_into().unwrap()) as usize; + let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len + 4) }; - (value[4..].to_vec(), len.try_into().unwrap()) + (value[4..].to_vec(), len) } From 754c7bc0a6a0416bbda1f45840abee44c3b1692a Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 17:30:47 -0600 Subject: [PATCH 28/74] lint --- x/programs/rust/examples/verify/Cargo.toml | 8 -------- x/programs/rust/examples/verify/src/main.rs | 3 --- x/programs/rust/sdk_macros/src/lib.rs | 22 ++++++++++++--------- x/programs/rust/wasmlanche_sdk/src/state.rs | 10 +++++----- x/programs/rust/wasmlanche_sdk/src/types.rs | 5 ++--- 5 files changed, 20 insertions(+), 28 deletions(-) delete mode 100644 x/programs/rust/examples/verify/Cargo.toml delete mode 100644 x/programs/rust/examples/verify/src/main.rs diff --git a/x/programs/rust/examples/verify/Cargo.toml b/x/programs/rust/examples/verify/Cargo.toml deleted file mode 100644 index 813ce7aa4b..0000000000 --- a/x/programs/rust/examples/verify/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "verify" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/x/programs/rust/examples/verify/src/main.rs b/x/programs/rust/examples/verify/src/main.rs deleted file mode 100644 index e7a11a969c..0000000000 --- a/x/programs/rust/examples/verify/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 26dbe34f23..b659fd6354 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -29,7 +29,6 @@ impl From<&Box> for ParamKind { } } - impl ParamKind { fn converted_param_tokenstream(&self, param_name: &Ident) -> proc_macro2::TokenStream { match self { @@ -92,11 +91,10 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if is_context(ty) { return ( &empty_param, - parse_str::("i64") - .expect("valid i64 type") - .to_token_stream(), - ParamKind::Program, - + parse_str::("i64") + .expect("valid i64 type") + .to_token_stream(), + ParamKind::Program, ); } else { panic!("Unused variables only supported for Program.") @@ -106,9 +104,15 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { panic!("Unsupported function parameter format."); }); - let (param_names, param_types, converted_params) = full_params.map(|(param_name, param_type, param_kind)| { - (param_name, param_type, param_kind.converted_param_tokenstream(param_name)) - }).unzip_n_vec(); + let (param_names, param_types, converted_params) = full_params + .map(|(param_name, param_type, param_kind)| { + ( + param_name, + param_type, + param_kind.converted_param_tokenstream(param_name), + ) + }) + .unzip_n_vec(); // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 4379663406..956501ed02 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -1,9 +1,9 @@ -use borsh::{BorshSerialize, BorshDeserialize, to_vec, from_slice}; use crate::{ errors::StateError, host::{get_bytes, len_bytes, put_bytes}, program::Program, }; +use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize}; pub struct State { program: Program, @@ -79,8 +79,9 @@ impl State { /// Converts a raw pointer to a deserialized value. /// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, /// with the subsequent [length] bytes comprising the serialized data. -/// Safety -/// This function is unsafe because it dereferences raw pointers. +/// # Panics +/// Panics if the bytes cannot be deserialized. +#[must_use] pub fn from_raw_ptr(ptr: i64) -> V where V: BorshDeserialize, @@ -89,7 +90,6 @@ where from_slice::(&bytes).expect("failed to deserialize") } - // TODO: move this logic to return a Memory struct that conatins ptr + length /// Returns a tuple of the bytes and length of the argument. /// # Panics @@ -102,7 +102,7 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; - assert_eq!(len.len(), std::mem::size_of::()); + assert_eq!(len.len(), std::mem::size_of::()); let len = LenType::from_be_bytes(len.try_into().unwrap()) as usize; let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len + 4) }; diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index e6cd135a8f..097620bd1f 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -1,6 +1,6 @@ -use std::borrow::Cow; -use borsh::{BorshDeserialize, BorshSerialize}; use crate::program::Program; +use borsh::{BorshDeserialize, BorshSerialize}; +use std::borrow::Cow; pub const ADDRESS_LEN: usize = 32; /// A struct that enforces a fixed length of 32 bytes which represents an address. @@ -8,7 +8,6 @@ pub const ADDRESS_LEN: usize = 32; #[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub struct Address([u8; Self::LEN]); - impl Address { pub const LEN: usize = 32; // Constructor function for Address From 7c0ca41c39df102db5b8c417775782430b627a2f Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 22 Nov 2023 17:56:47 -0600 Subject: [PATCH 29/74] go lint --- x/programs/examples/token.go | 6 ++---- x/programs/examples/util.go | 6 +++--- 2 files changed, 5 insertions(+), 7 deletions(-) diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index d376c554d3..5b7f7ff72e 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -194,13 +194,13 @@ func (t *Token) Run(ctx context.Context) error { if err != nil { return err } - + mintValues := []int32{4, 12} mintValuesPtr, err := newPtr(ctx, mintValues, rt, true) if err != nil { return err } - + // perform bulk mint _, err = rt.Call(ctx, "mint_to_many", programIDPtr, addressesPtr, mintValuesPtr) if err != nil { @@ -210,7 +210,6 @@ func (t *Token) Run(ctx context.Context) error { zap.Int64("alice", 4), zap.Int64("to bob", 12), ) - // get balance alice result, err = rt.Call(ctx, "get_balance", programIDPtr, alicePtr) @@ -232,7 +231,6 @@ func (t *Token) Run(ctx context.Context) error { // zap.Uint64("unit", rt.Meter().GetBalance()), // ) - return nil } diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index 1d3963710f..5aa29e7560 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -26,14 +26,14 @@ func newPtr(ctx context.Context, item interface{}, rt runtime.Runtime, prependLe return 0, err } - amountToAllocate := uint64(len(bytes)); + amountToAllocate := uint64(len(bytes)) writeBytes := bytes if prependLength { amountToAllocate += consts.Uint32Len writeBytes = marshalArg(bytes) } - + ptr, err := rt.Memory().Alloc(amountToAllocate) if err != nil { return 0, err @@ -56,7 +56,7 @@ func serializeToBytes(obj interface{}) ([]byte, error) { func marshalArg(arg []byte) []byte { // add length prefix to arg as big endian uint32 argLen := len(arg) - bytes := make([]byte, consts.Uint32Len + argLen) + bytes := make([]byte, consts.Uint32Len+argLen) binary.BigEndian.PutUint32(bytes, uint32(argLen)) copy(bytes[consts.Uint32Len:], arg) return bytes From 1e8fd381ff354fd52c49dd908378a83f38f7ad03 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 23 Nov 2023 00:29:48 -0600 Subject: [PATCH 30/74] mint recipient struct --- x/programs/rust/examples/token/src/lib.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index ade0ad7992..6f91cf4a1d 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,3 +1,4 @@ +use borsh::{BorshDeserialize, BorshSerialize}; use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; /// The program state keys. @@ -100,13 +101,17 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i true } +#[derive(BorshDeserialize, BorshSerialize)] +pub struct MintingRecipient { + recipient: Address, + amount: i32, +} + /// Mints tokens to multiple recipients. #[public] -pub fn mint_to_many(program: Program, recipients: Vec
, amounts: Vec) -> bool { - assert_eq!(recipients.len(), amounts.len(), "invalid input"); - - for (recipient, amount) in recipients.iter().zip(amounts.iter()) { - mint_to(program, *recipient, *amount as i64); +pub fn mint_to_many(program: Program, minting_recipients: Vec) -> bool { + for info in minting_recipients.iter() { + mint_to(program, info.recipient, info.amount as i64); } true From d97a8495648a52c4ef7fa8c99127890a0af6e583 Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 23 Nov 2023 00:29:59 -0600 Subject: [PATCH 31/74] mint recipient struct --- x/programs/examples/testdata/token.wasm | Bin 72853 -> 60443 bytes x/programs/examples/token.go | 27 ++++++++++++++++-------- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index c3d9ddd89c84d22c4e8253f8b2d7b8c97bf05791..b5e06c6ae6daf793fe53fd36fc28772f82eb2270 100755 GIT binary patch delta 16020 zcmcJ0dwf*I+5ef@-DIRT`0Et3a*3#g?|(Vv9;E?Q8Y-ede5#Y!LhV{r-62GduU0 zXP)Q#JoC)V$=ZX?r_MM$TKVF6Ow%;>`YO-UoP}3y`(5}5dxgctIXzyVQ}a7LJYMr8 zICW>D)05OK*^`p$OiSl(C;oB9-I~Mc$>5rYyE5ZF9+Yv;JRZ(t6WO%(< zR6_p}Jz64WR8`LI=&Ng1g)@;mx$Mo0N24HvF_wW=iHS+wQc}~>Gn`HrTgXO@aygim z7!$|BOhh7Wnm2Y0i;J08Id4JrG7L6n{+yaS?pjj0xJGN0%{(Lg3iHpKGr#7Jngv$z zt1P~zx_tiPJ1eWLk|Qk1ZZfZY{xYkyjV0byS#!tC@~ZOrvns8^*O;rks%pV3?R6Gg zQE4XMU~$u!CYblSGBI+<;PDe~n>Kpp-9Nc!>9X*+{CeBCjt3MKnL^RF2pD|ZB4{22BbAvozCFLg9 z4|)rC$Z&~!LqV6mlIjg!z}3GmT)&BR|$6_ za+YwdqXi%3N4-cHs<{#Ed>HdmD{e5fGC=UIk;X$K9kr#%IfNd{&sM8T@Cu)B>g#Dy zT2xxDaL?eI>*ZhEBiJTc6t|qn-xW84nD|-T_59d!In2|yTO(2DB{pc7-wQ4@%6mP7 z**>|~a|1u~u;ktm9;*>U-FWY{$yQb?;7;94d$-Gt-c0$5cW$9sz{{*5H6zAqV>pEo zG9}_2&sbPa@}*}Q%;FEn;+bIfI`j?lDc>MS`lK&|wa7pF1}3z&f+Hdpyzzy^(N@{p zKbyTT*Z3>=*?Rdee>VT(VVM!%L#{~d9%B+AFLb*l`x3!KNm$rPcSzJdh*JGY8A!U; z-ME4VerAQNO8PO6)XRo$z2y0%Ah?#$?UvXFh_NMHE>G&oKU{&zo7|gBUVkP(&b-c> zUj@-Kaqja2-Q|F+ES_H_C#Pq5oQ4aO>LGodygPkloFyJC>$UVdQ@7Fp0f*1&HGm6_ zU!dkWIXvSownJ{o7}&Sgl)i3gBC-|KmGE>V5xEh8{70!?x9B*vI&U!BARo^Qc(tLL z=5u(#M>EeT&+UA{oggXDiGPqlQgQ~ILJPP$CLmZk0XPTY4l)S^7{uui#sokZRA7ik zT7UrnxT&8S0vIC7(nCRq%*iivfB~{Rf3Vk4=+H_vG)8`7euiNKHA>hbD*ZdTD@MSzMajz;9S_loWvEH$M;1lsTdD|-~Mr{tYIhWB|&k;>3fMBLWe z84X$nuCqdiUg{WvRSpS>H4n&ldyKfc1Hi0+r<2w?Yyi6yM)^>UI;4kGFWnv=Ymd0) z#GX0q0a?{^gry`jOXo21)t*BuTknVLM0az}GlWi2`v87zBZdkmrVx!(C^Dkk9k^1v zDtd)Q6wF1>O1>>P&M+$z3bW-7%gl3a8 z(OgUPG|SnA1<8~YY2a>0_hYqkb73iuY?U7s7TL-$MD8g}l|70QSd$!FbSry7t}L34 zVgFV{6D{jK5fi=D`(~tb`qbffYoF=;t)ZRb6U`>==tEJQ5H>ygRB5vuTs(9HDXvI| zG3o5IM=7(l2cQPRy%&+CIZKg*39X@$2j#Bf9JW>-FE)y)Qwd+#wINDoqeP9ZMzwTI ze%vSjO7w2-LT`j}A|O6dU7O{+zE_2h)v0-WP!EeBGVkt?{&FM|fyIu*IlWrTV5~RbcVKafb39C} zUSTenxMlESZH8h|Eei=A3dS2gM8z7JPILm7&?A^Cx>TB*Y>^@oBwO8uciO&K(9 z`1)zuFjmWmRMm8>!3!ZFM$^Ca07;B1;m}-3UL$FwQ5R71EZ{mBERSulw5@?~tdX=e5JMAygN2T< zWQ*Ncn~`7{W;d2(=pBpV{jj28YzXLKrP?q=@rpS^k@EIqSg=7Un`c29bckBAa;Ee# zin)3S5^ez7!&rR*PY!q}N)N<9+(rzb5emj&d~7i2RmhD}KuSqkC#DC$QWCq8Kp+Wi z5=*#&ei$}MbyDV+Qi`4F*rb9nv`NN^a0sw8J(^^I<~B^L2jbw^nC=w;rtW?yhe*=v z2^K_G1!1Xx&j1GFh=FdKfeM2am;{5*5b(FrFU5qG_++`88Ip~!vL8I&oN-jAg<|6igYk?5HT_qO!s<0 z!DZCLlvrD$U$OjGTH8y)-j_P zJ0A#>ESDco9+y)~UCEJgh)2oKBa@W( zj8e1-6i|xvQcZA7f^L12OuZ?uhZ2%0pa8X(uT+FR+twgM^X8bV5Rtl;${&qnvF8;yTjdKkXUad_ z+=Fkclkq?9&mNN3{J1ASP$$p-IKbYJD}FqbJsefkORb*HT7a;RwsVo+MGEj#Ni1^E z)De88J<5|)3ozD^sTpjS{PomD$z4f@11&lhy!e(!*|F8PzQ&K&%QtR4;(os#s}!f} zW&Lf}^X7Va=C-T($$FVOtq@{Ny|4qGII3tgLP%qzoAVuz& zai>MkZ|h}xx!@nw%iGF_5Fu;J@5XG>KXVSh*d&+Etf1(>XXf%tP4e5BnfyYN%$jxc zm`lx|fcEQ95Z=f{KU1eDaoQ!$HK9h|Z%NZdZeJ+qB-3cP0#59h@XP|@J+qZOFzcjE0t`texU^p}V8>fB!OiODeZjWq@le-&J-rkTV z&&^4Zy=M2q*>lqDow>^EGwaDO0VHNrBNAgI}57HC8}MWR{qH#sGAw415ZRyV_k4zJ1qbMNc0w`bI_&GOZ`#q3Ra zes0b+mWzuGSpgen2#%b%M8{RrnNxNJvav8kvyn-o3mB%qDaTbkiM`-#)d+UFC3jv8 zgEHU!Tt!+lDXM_EF~A0>B&@DRw)XSqW_@qn+^yM}UA4p!rSr0FL2v$Oll*K!X>6l{ z#QU=MLUot0YN5JIShX-&9$lE4aE!EEaNV?ITjg)37Ra}z^pV3CrGBp#rdgH-tBf`v zt7TJaifmt`^LR6+nkfqh*NSF3JkmdoX z$eIeJQ>pS`^)SAtN#6K;iu5kdaKC;mUXL#$njyQrt7fZf;h}wfFSlXLiUp z?wN%o%SGx3yvTF=OibWP7ynI5Rt7dFD~^n{;6rWPCiG(au_(vaDA!_ z7k**5E~`vt_etZiRKR7cY`S*jv|8eXDGfUbJ6X4%W_i-o7oR3T?}2s{jq>&V|4K5tExjUIw`N>2^$nL!!d`qeP9V3;{Y_!8dp6 z`>0TS%N7mQ(!jx=b#zDziN~TkSa(`>pj)4P1TkEJsG{qsWIvS%ZLFWRUjTS7 z<%4i6U1VCsvQUtrxi%pyKqO%tM@ZbeNG0duSQj3x4!z7FU)wrEmaund!6ocKJT!zS2GjI?Q`n^`c@CS|-|IR{wg<>ff7#;W^I z$W5_2zu%zKuhh`$B48p8qI;EFS?4_Y`7VokxsJj*DXf}Gp4%NDwB*OJ4Rj@Tr6Z1e@ zl9* zVZ=@(K_(?n(q2}=o5>hk`~Egcn?NyFa7pcVwpU4Ka9##xg~tbD6)8rn{v0hY$ozmA za?uy`VNFx3A~Y)H)2vrAWDRR(+6@{>3(Q#^!j_0Rzk0SaHw9ZN#G7?)njMM8&RZL? z#~sQCEfK)N>(nr}eEac-*+qJaDU2oyH6W+s-2gtwAE}q-{fmRSGu$ut1>7&mr|Y+ei%z-ijEGI^BR{(~-*#B}yoii=H(fD|C!f_Vf( z+j|2pNWhjOzGkP4Ta`V=Jb`K$-$6(s{$1X$v(LqyZG;WFiA6-Om$W4+KWg5pp72`M ztSV-;^7U0i`G>pYH>)yz5#<98HY=xE<84+#U5)MRPt)W5Z^Xj$8AK{ua=%i8@RklG~^z zOGk;~yF(m%S(QXxJsBa?x)VbB-%P-HNzS$MgEgb+VI{bB@WhL|(Z{sc;FOzEP>y0v z*B>M#0=W=3F6LqFu`(b)oc;bDa`W0A@rpM=fCra1o7?5-wL{a6?oosd!U@!(x<8Vu zWx3@{%4Q2MjwM&7B z7=rTbb-_W_GNz&jm_G$ktGPxR67!8k)E|dPg;9G|2b*)`s&zx{BSpu`#c!_n5SYK4CmMa)^7&ao7Yy|zMg|8#v#5)~M1|LiuA$Z_cVGogj z+sdZ(f&BXkpQY>uqOnl>nmAPIAX4dWfX@C2`Z0NKeQ@Y`>J-2X1GGz&q}KpOCjxUR zJ8eIftVid6U~8`|+mN1QT4-DoyNo!4F1lM}Xu|-!us3eV9&9aCxjgiYtZy)}iI;;8 zYc3p^oCmOF1DkLo+T~w2l<>M2WY4E6d+ecgDs2guaFsFFzmLj;4%8Spr0jVrmv3vA z?>?2$ZJVm_89u`^IT({w>OlFwpUUL>+GR%Lz_QQOmaNm-91z(Kj3Tz}!msTG5#~B( zf*RA87(v)f5f@-$%?t98#<5Jw-E+G0124!g8h^;n$x%;VW7{K$Sw8-B4|c!Y_w?{U zS5$Yf)S8^>_sgVbhUZ__ir&A9wMS_gbRr3T%BGNhpbH)_6r#$S23-NmU%%Kf>VLxWn@v~1vfdo6H5Qh?S8I;_zsxlC zyBZVNSXTNSjp?uvhH%?EpZf1gkK@z3p2H=fO;1V{py#RV6x99PT_42^>v4Pz*qPL{;wE>@3v3wLl zN{aI`Z$|-Scm0lWJ+`P1b?6j;>#LoV(IquhhbPl}U*9SZ?dX|Mr&{85lWqVahvnaP zWcB#wFggf2iop}Oa45Pru6LB%{m;Yj@^ks$55xP;<)0jui=HpSb5`T?fotDW28EM1 zz{|+=t~r4bf(~nYUq?CfE?65GF6GUX7uv{3q!tvm0Z8jktlpWPu6miqWt-WA?98Qi zWdEHhStqH49(=-d59yq{NJJt>BU+X?c|y+EnHr8*Jyg3A{`EU*4%8wp;m4Jd1KTD1 zteF%rmLF2m0Y64uq7>ef#Ceqns;_Y1=ZJG=9xsuYR9rBdS-HsDR;P>YZ3EGr9z(G^ znV;}DMV(#!b(b-%&b4pL$p_QYOajGHGoC9Fa5|$U{b*OwfXycDXQ(@^xr86HlGx@I z&&^&2%=8dABVJiPB3ZWWa>`@7;(2SkJhSU+zqJ7RisyX047`v{6=g4s=11FQ-3u%1 z`WUr#nX@~W>aW>7DcqM=9x}i-`i>)-IFx+{Moy zmp|PT2FK+$dmg012VZPJVN1^5?u;t0ZYig^n_3E~O?%6NBsEA7pDy9RY|S=dUy)xG zn;RbHzklD=dDg^)3ROwoA3jZR`aIZospqkF`SHH|X(n%!v=zs2y1_RZIOCf>wACRB zsuoZiiQ)J{jP{rB1F9^4DfRo2`ov2Ejh!?~2T2zRh(RZ2Fy}k}j{NwgK)l_EHZmYw ze>oYDl|5e`kiLbiLJ&LBXmS_GrJhKSZI9*K_0N?d3@|XJuj6P4TaZ3{f z+*F#Aeqgc-R6(~_3W+M$;q6epX#|wcVH(20jYzVFo7#%+J147QB zLu;p6uqTe0uy-mcnrZbiM=Agp6C#BlO==Ae;dTRJz_+m-+Erj`7mO`|0J^&M@QwUj zyZqAje#u4D_PX> z!&h4L^T$a-_+F`us6m&eS92+9d-cnCm+|Zh#t%5gqpeoRYY7bGjl@w-K?q;AU{P_f z4kc#w_aaS!Ng8dp+O#^OXnnLz(Yn3u3ba>Ora?SG=C>w}lLO zqon2a09{?2dOe32_K(+l&`Pu4INHzRQPjLx4jmX_-5ht<1aXs15&}9QK5$My+Cn4z z>}WoX@Ry^fDR=Z|d6fI~XRlpuxDUK(8SWH$;Z4JD8*hLVlFfcAmpv_qzcnGtQdV3& z(_K&~0CPoWTxI(=y%j7rsSL)9&ZG*ub-|~h3Om%uhK0+5#TRcWSiEqo6BbSj79Sjo zxRmvlAHSU}7yrC4tZ-|>5QoR_pcpy~A(<#<2JQruA-8A)tH#iWY#n=onN+JxAfThJ z3(zscWkC19c~nz?A3fRyA$@jxC(`XD$@Xhpib=BHu~hk4yV~ilw7~n{UZ$%l#?S$r ztQrRP9v@@_j7I@%@^J;Q`N#KOWhp}k43s)47~oBaFn}8%5Z?&}i2J5@4tG;d41Ivb z1YRbx$g7co6Jz0;g-+yTn2#_p7~W6a%o_$n$m3-CQ*z^p6vE?y6F;O)!}p8nxy`im z7;s_HO4)}_!Kkfu#V-neU`fY-qlqtHI>o{*u|)N@cmRUQpvXV}Vnqk|unv?&PL3gF z|NLYpv%MC6E}p!Gyo15-MhM*d-|d8v5(k$4`*)8fL=#L)dij_Az2?VKz={5}{QQ>_ z$aNX7HahHSlkzWR(VlI8JlK>mXv)+r)BL48+ zwb1~Ew7&yj+{<9WCVMN}@{&W{Wo5E{2-2v!m>;BPc1?YdB-fLTT0Gg(S$Xd^k#ccWL3}=MA zkAEEmNSz52lBeG=WqYZEr4_AN)B9UClzW1WYOs{BzW-%pY-9dtZmdm^JaibB4CZ$`NA+^`tx%3hrLs_QoVUqPhev(;CoKU zZ69{O-8{|WuTBUEPW>50C?lh59qPrKn!eo}-k{RwD6PJtG#h{g=0RV))zJ`E20~c_ zz5gi1zk@m`?hV&pl-GV#$lB$+k9x9~=R=;+H-5TtuD?`Hwr0u+Ci6*kF$EO7F4K+=Zh_0ix=KcKqf zHZNY&4^i6u#a9d%DqBCy%v27glxT^80m|85{^4>XNO`*W#en%y=^m8EUI1zu7^SUA z*Qtzm+jy8>^|xR3EKSpTAS5HuKZcNkkcyxqI1$ni z(h=NNJ_9ker#cFm2sbRKG4K~&#>{0km5Yt)%JK@yJ`c*lpO5xx+Ek|Fo)Uw|+RuB( z*|{8f;PbqWT)sT_d0vKHhi|1d4}zV)S{h&EcC;NX$9~aY=epK2s>vu>7u95f-17xq zAa$U*bCiilyQ1>9$WOkws@R_6Hq=DVS&n>sRO?w(FBg7!Rd}I8r$5WnrXcQ)*vHLr ziJ3kGVhWW<=d-P{M)b)+Iv2q}pmYG?NAoL}F07nYQ(0kDRnEVwX11~5PGipeg-dD* z`}Rfsm*|ISw2=#{e^|ZXo{39pMpaiYs2+M-q#MbJzNOHW^z3+H`TRMv=3=<=8lxBL z2U+!l(sa#%e2_ZfA4xncgi8@Q?4Jcm>)pBrBx{=yQ^T*Fa>+l7GT%d% zF!DRZMEM^PlQ>X)@Sj72cCYj}6RRT-lNOCe9Ah?1`B#wF#K|B0t0buzrNj&ZA;G6P zu4VbZUUzk2OYgNevffD*3A#pnxDkQkiiDRQVg)@Vw`V+85*5T`J4WnG_R!?!VPJi8?>B$Y- zU95Y<{$$oSV9Q(KbMBn^71kt#2MYd%vN)D3%B#pqEHh>w|X(^^pu8xhZXUwQyM0ESZ1IiMb{EgPV5+jU?XfW z(j^F`4b2{wC$@Ak}2bJBZ_Hmh^^ZA1lqwhN6+MdmtvtY{difKKHSk zZ=Z_t8&G~8{YcyblanSgvXQdunR8!I$2E=14UYFi5Cmu^XnZEz&cs8E%f~ktT}OVPBIA#c}T zi!>zDa6>n?C2XLRj__@!u3bR*7~vNPuOjS4*p9Fs;cs*t!HVLZY$2u_572)z(`Elyj@iy^UF(giDugi&*Qc;SL&nX&yS!>n#Yoy2C)LcZtnS*8*dQt@ ksw)>S?lRzY`;Vuv?3ji>WU;2i_BJ>Zq&!nV3cXkVA4_=Q5&!@I delta 27440 zcmchAd3;sH-S?Su*W861_CSD~dqE9**a9MA4zh!S)&)?MkX$ec$%QN|t#X5+fFPg) zij~J=i;5Nz1Qqvasbbymd2DMH6x2SCZPn7J%j>7=k2u5as8{)kcDP%8|>5HH>y`8Q$Q{?JEPe=JUjygYv-8uJ_RNW^SsqCq4- zV){*C3cuxVZz1Q8bm-VA(z%PjbJs{DA|i&ry=fMhVL$#e&9G@2K7XW}X#~2r!+XG~BIv8t}B@!Ew=sfI@5LwSSQ?c(Di zURzbycx_|atv(^zHP)BcH7rQgyEPw)4qlVm^12mn?Z?7eT+g0$<+Uld?h|>$?3DSf z2$U~cl&&!TQ-ms0I{RND?-n5pM?|l@^86XI&KWa#%Ce1OUip&xt5$3hQrsbK7n{X> z;@Y2xE)ynBpEmv?yQtFvaZRtno{e3f5$(2!Cq##-nMXxMYC*%o>#CYoi<`wQ;vTVG z{F~S<9ua%QT5)x=SS4;eOWY*3iMz!Q#RlQR-Q&{u4R6PT;m zjM>6A-Pr^~<;+PDH=LN`w|=6hVXIOzj7OjpKnmMmY8tj-3+J8ngyx`HhtIL9 z)k0-Sc%FG^qr4+LR_v2+hgT7f%kst&ZCmoDo7-=eALR||_&leIs^w3Jizt@;yzCtr zA>Nd;BNv;^8{|Wgu@SeCz`H+1E-Z1225@EReDtS6_&r?PHA%n5HBi?ab__W`T9eTY z%`$f?!w$NA(a6>y8`1fOS%xNDxk#8X5oN(KCdYNX8OL%pcGO$E6IP2NlZiFNg{pAz zW$kqF2I7{Qa(Jv*JS;C+)lK|LE{hG#Z+Qzyb3!0mtlByJmOL1{PW(Y8;+1CeCb=fw z)BN-a`9S@oBkvL7Cb|CH+4%e0 za~~@x0K7KvV@v?VIe3!4i1!4;ej1;XFu-Q7s}ad=*(^Bdom)xHyJbbY3&Sn95z3ct zlY81-Y3|%8f0KWX9F(5~MK8&pEmq5)<_|ENS^d4>KDAu=d3<)Cqpjn5S&X}Oof=nT zrA4k>HCAi~Lb_O^4e}Ad3_GG4EGCbydcFuXL=EtLJ9_}V9%mU22qoW|(0Mu;9_>hl z``Jhl4cp^r47tU%<_`CJu&%ss(MVZmMa}}y_7sSvZ~~192%}kM`$$96 z5v689fr#L^rrD z32+;e0o!LIO)E_LoG<_nBNuQo4NlS0gwHI?up`&z*K5OaO3hAK6-Iz+u^@eT1#k-R zT)+RD0%OVOC1G7#dtGJb=0J4aIK$c+M(v(t$KvX9LvE$g& zfMHP8Nmvgn%u&oRA^{>!C_+v_b&@PsP~F!sM*7HY;cD63vBU?g%l#ckO!W8l86ypH zuFpwOMA@;#)tdQ$8Bn_@I8%PU5c2v^!4zV{%n?@_An;38T)`5c8^zW1hQy?befEFD#e})xWXeQshq*Ov>M^L34JjB|LlN$Zo}*n02}W-`Vbm*UE-&BhACR zoz$aUJB&BbjSqUJi(aO`*0sO~!D-X48U2k*`{@HVsLB%DuG z*FADfuVI&dwn5DkgP6DgfuA8&))B2BcE?2AvmwWgnxwA}>YFKEqiFKh>O!$OM!RUE z5&_w~zEg&RQI-rkK1#LEIesH%d1Rb@%Q$m28Qcd?Mh#)zrUw{e*yH?{Xo0ffUZQ)S zL?{Ni_t`-@putkOf7GmgN;R~pVI;%w!yJ*wgXW1Kg{V=(PP4GX8T_46i1}fhLdrM= z=_%PE>yUDS^4K)wI!Jj@J8wc98axpKOw{9;D32;0bJOhjoI^%+0-#VVMSUXXD^q#= z0ixFF6$~^+#cB19f;MKRIvKZPj#)j>Fz7UJy=a?kXGihqYbxcXD&y73d{oAjMq^7m zHrO!E6IUY_RSj+1*B9s&W|hLa9}a1>C3SE;c(Q^7yVG5yE2ZPzDPJ&TQXc zarJo^HE4^G1~F+?+i@2ryzT3=N5TdKosQLZJ6CfCsYUXsUllYQ6iPZ7B3i-@78Z`9 z3##2Itwe;SSR#mlV8RtmKlJqX7TyT#@x5H~{2nWr@v3E^{E3}q8li!qw~ z7S){Fh+F^w#^3>hjB>E!10#1^Sk10UHrf$8T(vyM*wmg#sQw z{T~gM-3}lnVs<+s?B zbtbM5NuG$4>l&*G4{)Ta$xonTSzCS@!wJYBu-Q?Mk^Uhcg~>;;96o|@Xy(aua=DF6 z5YIBfKgUGyO4vQWO?PMm@}Lb_3{HxhSVTxMD&~zPqOM|aGLRt(lIx}@#Q}5%fz#Y7 zYzl(Z2ilpzz$!P&2BN55qr*+ZdPHG02tr^AkdBHdL^%vW4oL@K!SJxaGNjAMz9=(kqA*5kn*^t;D!F*4$z!(}1Tk4#Ep* zkfJlOIl#!VWVF({hi-Pyv9L59!_>fTW%2H=20;O?r$utjJJR0PJJo&?pa6EO{S#tzj0$N&He5L`z< zgfSV~a}ye~Bd&djaKH#~oB@vM@6$OycoP(gbwE>`jlpOt{L`H_)MQz8vh!-_w1-f{ zWPl_HjGzSkV@ZIruWxcvj3cjDmqCifID74bXdoU0<+uu(+GhGDPIuRaU?sF6c(_b3 zIW7Q}LU1BZvSaO_vaSALY2b8n`?SK=9SQh1<5Ak5gi3NL4Yr=#h7%LmnUV0W%2YB= z#K6qDcu_KlHdL7=RpuxF4Y?rXS(Qm{%p(UYwP{j3Gm3#HQ*XL_U~MNl6{Vm8H8Vtk z+hDbwN9RHD(ei@vj#u3pg&wAc#;3 zAj=$MpmFdRN{)}RYC79k0PnI}2K!va&`Nhc#R0)@>{M*3cFwzOjgB1V0Q1n6g4)u- zmR?m5P;Mndbcc2OQr#IC;XvEf?6lv&Ici8qRmb^VXi5MWEXUQ3Ns)9AECG$3&$#(e zbS8ln#IR|K4b;w3t(+?;Lt}1#pF(?NX$ZD*G30bO**eI9R+LFR0?xN$iQ}IH#p;|S zrpU#hATXr;je_4$>Z_C~$CT?<)tBFq? zL4)*>NTkfkpQBSQWm+xp(`wOC>lyt7jf9;K6*2BxanowBGD%GVL1fsxP79ja|L82J zh!?l8udev?$x~;#QNJ9cs6R@x1IBdu0J&n+QL}QEFWKGNC+{0QwU^q`b5x(Rm!V(1 zPs4)&yfw0UNWW?B-ZTek>`cT))H?H4Fhx zRKA4ICs(cSoWa_C+|VUMElD`%Sy|oAX9%+$-4t%HY#4ibE|FL~yQ|f&z(X_Qu?XgmRu3?YL{y4}1sU#q!6>RT zd>oin)j7tfVnnyob7R)cm@FU+!vLSLAB;$TwPH8(qBvXtH7UHylfW{?sboq#FGg3y z*_4?Yk6=m2&RgQ_$V|cuh*s3e?8sak4?`_*5{y@*d&UTdo?+z@r*2{#5jTt;VV4&$ z7JIM;#WM7V3gP|{`%)rcMjRdhd=)Gbji<*0YzZ}z7sIx;^~Kb9Am-0#ydicRqT5Z{ zD1mjFSKYXJ`4TuBAuXY;6+RdSklH^Z9*n_vZUsZ_XFMQ0M5@ZxNvC67fP|f39UUX1 z;O3-+n}X2_H}tdH5~zZXtp=3n!%zjfGrr4suWdMau8C(D+m6uK19{+Ts0}dWjJV;h zj0ge435bcJw{KFs*uapg867H)iH;nT#*c!59(Y9mB#VZ02EUtSHq^ehJ9rl$4~{k% z@#s|Tv`UlhN|Flf=$MPo2|)-cR~UDIe)PfPz@19&Y-G`iK@%bvh6=bKoCTiZHewmr zQ;4M&c5L%F3kL+q91sr<*!;g9kfV7~UE2U=1y-2#2Yet^?s=fk$#foVU_K%SCyB%q z@MHT_M9Q}sPD6BS&RGeL4TKJJ5pDYatm#DvSb60p1=#cpT0sZ#*Mqc-HcX_EFkRg9 z)BwlRVe46C8w=Di!S``32>x(9K6^r~iuMyD6sr*ml&M1(R2FAthn@ho_-Y&N#X8`f z17v~WGp2_Q>>PjtvoQ&b9>(BwPBd(WbKuo%1$|KyqDh3G3L-d#AmTv~UBtHmk>btp zL>9z_Kum(CL8#Jb!?Y@A?IQK@4x-=s2CcMKhI`Xq5fV*+b4CC?#)x_cQ8@$2{NCpw zEI+L`j|T4SJt(T8Vo;L?4x!%a-Srw(PU76#q4ESO01yP-_Dw0w-cNv&rU>a{KOCXF zs5~~9aWuAG(#-0X_VbkybxSYG@qLnFmpoQkBwpEnU;hb0d?x>Ezy$I6PX-P&Lx*n% zdaWWBt4AKJ1wI5BcS= zW%#>z_*VQ4j<^ed?;Wv6J~(=Ou1j_D4$S!-m#VYubzbN8u2f~+s$ZSzk8PG`?2P01 zjU#&(l1C^Qpq_H=quIgUJ9V%_|8TJ3=Z(iv&WiKq7qx7{qz-r+egK01&~>&Ci*|Vs z4%~U&<+-y4$g(jVul>hu!OI3laQ1RUZ|{4$DwFeMnYNc&lHu&!u>Y|!<3wl!QD{9b zzdFBrPw(A6O1%?MYe%T5J*WwCb{u<-`T7PqW^9RAFKfr1Z64hqyI+tHTji5uM~e+P zRp%&d@%9NMDyEKGp^~!3n>$B(+-v0g3&xrUyipEaP>iuYzo1)4iDYz_Y(J}5-gDkS znVQw5Z`)IQT}Yw4_wH;-6$tc zcFb=!%5{@R5u~3@UW$3;c~h#)o%hQJrd09~n_6VMMm$+{<+ga5nyk&qKob_Z`f<n$}6B19(*fnhBh0`>j99-qYpqL-c$QO9JnKJLnMvltAL1c0&Zr@93Ie%GsB$%qqmS#48lye_lH9n)lfq45rL1 z_y9bBfUwD>!z^dr8%HQ%QJ6KI?He!vwVP@e2ClWG*UE@GA2tdq`+d3Odv`+9hc6o| zKHop-vPJ=A^X%o7Im!n6C9Q0XR%IjP%+=lH>?@qEt&-HHo!oat&+cvI4$f~@SCTeD1Ud= z+_=8>z~d#jQ1W|M&vb9uDbK_WuSD|<>*w0+uk-nQ8L=|xxvkmDQ-)c_|H)_JB(@oV z3AZAYkE1!zIZ0^TlkNmWFcI{XDN#rCAJI;_&xlo4XOcKva7W{a4)lRav1;okqA!_; z(c${Vu+46Y5kHj zzTo52hW##QrOO)`i<&vr*e_)uNZX}vbnW&-)l)ssBp(TN1{^5??3 z9F*tJt-#gG`{tH=cP>r5i(OL?+C>(y9^c>pnz%4mt&*d!O~smbqYenpwJv=3#kxaA@W4Mq>cbQ=l984S{e%(8obY&}+xU3m{+ibllx+8qbwgm(+ zVF|FeR7XPClp^~c$I^i*mJtWQeV1RdGB-5ej01df)@t0YQp}79vkH`}d$b~v@zZ4& zR0arvQ%eV|7YKL~!2=wssSR|iPfc@$y_*}+&|7QM*%8ieR0&02%r?@uEu3=$cpEpG z+=x2O+^%>*OU98m;1xzC#kL>|reyY@-nFj9&e+rIo0-S!W_3olQdkoEJ7=;uMG(o)MXT74Hi|&RC$b$7pSz=N2LuyzAHBU5&g-f%;#qhz z){(8Pt=}`xNpQ!3hb?&a(Q1>&tN;|d(a{Eg)Jyn}C#csmqYZ9s0ev3~iM90QLmzE$ zYA)zmPHFwY8-AcsoG>&Y3|GHWgBg<$&_|#}00e^pO1&NKlc280`6bpq(CEt-jIaQh z0>{4u7a?>9BDI<3#X;{j6hUjMG*)6Lh5da`$Zywn#{CHe@mYW$;TOQqW!R{+tFt&| z#32`_S^OE!mha+@LJ!z56+;V%y%4M?UnE$#ozn)agb#=0MA$z!{c~zCdOtwy)>a7U z`V2IHEFcz{vy|D&q7?_bt!Nc!0wZb2rrDNjx-(Q(g!S*r+ZU(8s?N$NCeEjdeNM%3 z0?Nc}4c3Y1Z-ftDZLG}3gkW6VOJ!Oc;aJCche}*q(ah?EA0`xQXpP;mA^!(KL4TyI z)#R}Xtvpqi0KNkV$lH+r>VzuQK+}TYIPZb&Y?T$7NVHY8%0z;xVY6T%Rh*e9bnzTb|5U4=I^7j8eaY-{-}YWV3o0T05Hbarw%4g9crA= z5>)YUK3J0o;VK=iGuD6%s&Ptz$PHGkqW?ICGsvSjSHdGyos85ZqG}qR+b09iGfsqO z%?Q}@7@wYk9e_gsK)%yr<>^{v+6;2T>6)}@!5bO>c$y#lKU;i1r$y%Uu&&5y0^~%U z<*4B9DFoZWcYdA<1QV!8;#S~A)EGEENk-5R%!;dlnFefBZr!r$h|%DD`^{I&s+V{t z1wK7o2p9@iXK;ua!95dpim+4Uw4Fc)#^asUPg0^SY+axnwx~i2|7PtQBktREY(O&; zC;=9N2StK3*d{Lcm}QFNNhdplLlCToZS)Nw&=FpkM_9UFU>UV!-Y?KBhPW@`g*3ne zRph|75?qSPYA}M=8MZvn`X7Q}`%#AzFPx)7!gY7x6R>6S&}K6XuY$VY z9TgI$>fO5_t}Doa$hU|Z5<51gDK>AH z4nqJxdT}Va@FkIL~HE8Md;)K9VO82_e;Es z3~0eZ3R(yXkb~EmfL^S|5H4U%ii6LxhyyqZb?OC2R+v}w+GkvDl*b;!Uv3}ocGz!FNufhDQm_$fpm z^n;uAXMD(aCf%q^40ITkBUX!(FC{^6y)ueFO@-#L=1`y+JgNCw!IGEDQn4JC;^`#0 zM-d%tp~g?1o>yH)lx6^1&XPX~!~H)A*j9>?n^P!KYP_jP2zSRE#ZT2YJj zt^nZ6GIsOK6XnIjFN}zPQuG^BSyy>vLZ_ffZ_6+LG-1$iICX$GxYW4-T29oDHh5VI zR;0Cp_Cq)wmcsftC)vU;TgG?dZ6)3AxT-sK7+m9X?^>XhH?|%MleMTmI5t&I0tUjU zj?f+f4^~`kFlYcudkBG#62^B?3L(|F!=d&m%4K$N?g=th+dLrOh69AwSK;~?UdbO=;2lh_NS+l^Z@^VlX2p|NJa+4xk6#x zO?sDIXXqgoBBD{yzC)CSFI7Cuicx2p7U!K9cAjzar z4|*#D1Zp_~m&97A3uu{OeY3-n$NdQUu_8Iwp zUC&8dIh48tT<3$>q=EXyCaHZ18;t=hR8px?pb|{|3cW)7}gphnhuUSt_K>x#@XXi zpLbTrPZfXwo~++V+^A!98;8?_F@?{uWw5>=^A+D673F}0J)h4B=T}=#69U{>AdfsCch^tkS37^HA7O5PLC$R` z=>8xVs|*Qze(Z{s8pC6)dMzH5OB>E=r!WMoNi%c!n0%;Vbl1;b0I)o~L|~gTti#`T z$-g%YH}|&4lE$8K9UxSJZxD4(;}xS_ed>N>Yki|(xDFYI@Sp|CdL_SG8m2;nHuYW}ydYei)5ntPvS7<&P8BC!;fQrHOkn?^QB}Q;x_b$zb6~-4-7aAczae zjLM@c;^y&V@((M9mU){BU<&(0y{kAvedg^d$gWu+A=}sjhm%mkPF_Md&ps#Tet)vq zCXdbRVIF@@9{T>J;w#zp2N!q>4ICop{opLIQ{M7}^Al|aB1<5W36l$Jr~Kpx=l40K z6_^NNmknyUyif{tvEi7UaD8In5guRjb|Ly}p(Hn>M)R&7mVa^2^D8N@KR*|$_pY}K z){!xk3Zl?qFl=BHn|8Qi_-O=WC!-*GzU(BY5s+;+jPB8P4W8(OlJLakqbrB!h@~qm zXB5kmE&q#IXMI;B|Gctnqzgu?NP3VswiEVP)%rV`-H2NEYUKz>sxy6Hwl-yErSxCXHqnkt+RX)b`zz(AV8 zD;}(rM{Y`nf6NtGJ66fR-*nOcp98kWn}?nn;r$!Yn-lPrKfigPxqpNF%gwi#f88jr zzvXQ6#XWN8E$STkgIi|gKTfFO#lZX*I5<=uv!+-)E>mlIn_D)?Th~kuy}}WrqvUVa z6beWF8Lyw0J=RV+Yu8&X&AbGlj>`73V5v|moMe3Xz@3e={VjRx+OzY&e3LEPD>ud2 z@RodGZQ)s8sJe*uFm}9=+Z)?E)%$mEB7|9F{`O4-VT;Un-;~a}e&RW~XkFsM<`2+; zw`8bbX~kMju!3LiE1Skrg7JUH7?&AozRohT&CN7wE#Q|!C*+ZJ1qG^`RyyzKHk9a{ zC+@hlb7AvG=)`L$8D7Hh*I>iZe5lzdbecbsCAW6T>~=e-cBSU7w#6@%gu}ZjH8&7g zOak@0mRV>~zq6A$gbti-Dw9y}tjjo1!lcf2-OMfR_B!qOpk*k!^XoI%JI$Pa z=YaQmmmb3%)9t+X1DUw1Ygd3zaF*+5jgybCG?#SN`hI5};TlTK)$GnSmzsZZmjNkI zIA_bo^+U~1kI7x@$HZM=ag>5}$Um*eVJFP)hKc6MV{+Dpb>4eyHTnLF4MlvPf7^_9 zx+A^EV)N@`a?x!GzS(r!m~LOYGXm<9%*J9MVzK$zG5N`D3(alEj01LgoH1HuVsE8N0olbEj|b%Qio}J>5YKlEm*BsQa*Lw!%C5#Z@)dh~;AbOYa!d z+ntyUpkC4|3|E7TA~56x;V;MJzB~F{t?{5JtFVKuBzBMW>P)n?gYKgE%kxi(TwI|2 zhfFy{b~z(c%4_9N`(2Kb1!)IMJkNq45X5aK2Gq#;e&bf8l)>$sw6Jwg~{fde@k1aDk zDCY#~wmH0T3L3D8I0uHuw<1~TD%R2k#Y!fCtS-BIrn&h8`Rd(0@;_CwztYZIwxpE$ z;4gPSO`+cV!=Cw{xvzqJ1-U=^!}~h8O2p?G0cwzY3fXb@J^QU~$1%SOKN1>rNpCOW zWApYu*Pep2(J;3?MN^j^1zN>MA*wa z&f-cx-*ITLi=&)*0WY_k&~Cn^jY)j)LGWQiKt5pZ_oh0!+UD&~T5za1F*R z(@2wvhZTd3efY6qt}tZTK#7xL1KhMG4qr0yudWmgqxTa{O z^g}CQlxdy)Nb$KYb!<45xF^y|7Skn5PHz_n0GJ9zKK;nLEc0OpW> zUH&<==K^{Mfk&Ik+-n|fWg|rnEPel@hw^g)=8|sNTM|`=5()4Le%tBAz0>GAwA+{L z-^#v>cE8nSRr{T`qKZv}yIK%Ja~)*HS!sKG{m1yLj&H{$Dr;tC4|~+p%1xC>p#@^_|U~j5J`uCV!(IDQ)4^m zo*B;VSdI9lrJu`>o;t7a7wlj}y8%i9utixue6VI%Z^%(k_wW2F->Yyj-p15zr=ut2 z@~3;u)q7YI?jRV!uYV{H@1bpo z{^{w?@z>cwVefqF9og}jzPL$!{xfIe*R?92Da)t`7vqfXZ}ue>DA4#ASD)wMOfdR% z9xjAYO%Y*Ef@frCz?%yK855tj)nHD@d}9r~NJSXi{5pc8MikJb0beO5{O$ngi2*PY zoM8SW0fO&zvXvWxPmZYBygG#F0FRH84b(qpV?wiWB;X%F!yvLbLXp0{-GQsK~ z8bQc_YXKR5l?6EE8gR~OE(JaTm2%#(J}wNa#Utn|gWrMvIKbeEKKHU};W)5V%Tt$A z0uDdLM90PGfsS|t&=DqrNX73Ja)_iKx#El-!v`4$BC;RN^Vc&_R>x_a1KK$|+hQ!h z;h{XfJOpY({>mu7vWM}XTH459IB}(#uCUBIyR+qEXPl+(jpy;63 z2!mm$pwk0*Zqr3|hHtEHN+J@g;=;;3(;rk~Xp2|CRJ%^4W`@5sg~|f`6(w>#c>ERP=G?5XCkel`A#XE466_ zYrSsZ=RNQ{EGOSbtLnkRaNc7?4YI|fl%v$T(QCZxo%kYw6-gW^$fB1Mh-x}7GqySR zx)wR})TeR*T5VNg|iVCjM( zBP)jvoj<>P$cU1XAqxi2PuDkGH*mW%NM4CsHpY=8NPHUn$Cr#~Zdf3u$nDQ$u6L;B!kVMhqV^s-$$m&|&36hK?*L z8CsbdF@Jc;uu=0PD; zBjti=qntoW8b-z_x5rmCEM8Q;!e-x8ZK|%Zys;`>XV<41o9gRQm3DcZovN=-*V|2X zspX4P6^*INMJtTn7=Zr?q&`Uh8t|DFgVirVEBHZ>s=9@Q9s;kRKbD6NO))qpBZ8TT zsk4#JLCOUJKWc;nHN&uw*sdQ^f26Qm#y8<@#(~ruz4^x*co6bC&^?9cBS?L6%8w)8 z*^pfiCp%o6ZnOcjJ%0t*1z0Mtl;<9vm^a5~sp-4QTMzfomU_zP5BJWNdduG*?%mC6 z$@$=I7+(22dG@PC*|uZk#jloFeoL*@YcgJLe6`5&N>kkds_K@OFRH4vtLhdvHKMKs zy-0Jf-E`ywIptaMi&uwT?!BFZH@RTULzy`D-p@bfeKpD)jX&@`+BS^JfMo(XU*X9C<{_P_4Ngzhz#c3g7iwTR zsi!xFB0mgiIFil(eh?WD8Gwgzw-nce(gO zgvKbj@{Myk>qEGk^RQx z>4jg6C$xrvUxHtlvQu^BIp|Ki8TA(GFV2%!zS%Fb1H~>VK9RS7{hL9Nsj90;Q@J#z z?54&A14k*@u^UoLno@NYDSJVEy4D@YFy6t>+xJ6XkEwNsY+F#>mAsr@;i#nmPvS}X zTs3IWpt+P!J*wRCR<{mQ@GgpXm*Gj+?2vrzt$y8CqeyPQ15aZ2PCU61yv{!|I_dQ~ zjA|;KFYu&7`5T^OdNiv!f-mG_a?_F04l`qxQcn~oGXBii{$C$?DG<-4(7Ez~U-j?M zse@%uVa-J1vr~utAOEV_m&t7jFU&X(X$(?sJ+2)ZW05X6rM?Vh2WcD<{-FYxKc&YP zlvgcERgSi6p&`bc53Da*FbE=4+&6d33(=*be39Jp-ptIurpa>^`O;K{XCU8#2vYwX z4rztDpuDkskzLG1So9K{0hptGTsGY_>dYxc9>r!egSoW$~ZOZ)x77j9? z2ZXjHO?4G;2^Oa7GgaTmJPOz}rmlChO^sAS`X5nfwT((FP`?0ZZ>no(TD&-250jZ* zoPvWv!-{_$0Yfz{MkRcaCR$v35xfyBFKsVM*Ddr|pCeGqHfHdG|HcBE)zvgq)TbL7 z23Drv&!kk14clC=TH@bTsKh_9P?K7os%UB~pT7vgg+YL;h86XxhICUsy0D;X)qDUU z#ZtqHhQ?H_y`(AKSZ=45SEN#vsmg{_s>V*&WnlW5%??Ueo&pzOuv^;{IZGq6I+u1hs8OV`(EK(8yWt6Y=|&!TjCv7NyJ zp=he=;d~H-i>hj?8tvlLpoN3%h84BM3J{lG+?UpPV7hM63N@O$By{$G1#DGKwR#}@ z%NKSXYfOM_{0$~nC-TdJ{5c>(6A#5!uL8X7omWvZ?UB-V@IR$4wO9ctJ`HbYG*qN3Q+9E>!F3JkczI$s7Z#41_BuQ{fQKP01m-zaNxj4W z_-;JXX~YyBZB?2=xf5d)8k1p@VBkBUv8xHxzcB)5kt%^sh;alBJL2h?SKSdN+GiNB zeg;MaQ_A?!?q<6lvj5S3nNdBocS4P^AYETu-Uyb|%Q5ERT|VlmnkOK6hI%6MlaK&V zoBAmzPeq!Bbn0>zm)BKQU@f~bW&z&+83{&8zVlJXOkKs`G%O(AzT-l31aG;{+%kRu z!yw0jKcF}5^wL!Qf<@_N5DADqC* zEnbTq6UAnJ%7#>tfuQ%GpqlC%s+Oh}t*Au*QJ5K<8f7@Ht+&a$P4(Db?CdSy`snOT z3z~5G4if$K+$CLxviF|GnU0->)EEAUq%_ieq$`oeBXL2N?Dz4HGKZ6vaS-W2q-{v+kd`4W zK$?Se36g_UiZlSJ2&pqt80qVTW&8o@H%PA`J&yDc(!EG`BHe~`BhoUYc}SNbO-3q3 z8iZsgtO-UZWCBS4ZCl2FA?-$b59uwWUFTTFOL+DMxReE^%aK^-f8^|9B)R7OL2~^k zQ+vkHp+73XV@gkX Date: Thu, 23 Nov 2023 01:31:45 -0500 Subject: [PATCH 32/74] Update x/programs/rust/wasmlanche_sdk/src/types.rs Co-authored-by: Richard Pringle Signed-off-by: Sam Liokumovich <65994425+samliok@users.noreply.github.com> --- x/programs/rust/wasmlanche_sdk/src/types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 097620bd1f..eead174e22 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -79,6 +79,6 @@ impl Argument for Program { impl Argument for String { fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.as_bytes().to_vec()) + Cow::Borrowed(self.as_bytes()) } } From 09448393a7f15acdc158761531b08c6bad6553ca Mon Sep 17 00:00:00 2001 From: samliok Date: Thu, 23 Nov 2023 00:37:00 -0600 Subject: [PATCH 33/74] lint --- x/programs/examples/util.go | 1 - x/programs/rust/sdk_macros/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/state.rs | 6 ++++-- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index 5aa29e7560..fb0197d08c 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -21,7 +21,6 @@ import ( // It returns the pointer to the allocated memory. func newPtr(ctx context.Context, item interface{}, rt runtime.Runtime, prependLength bool) (int64, error) { bytes, err := serializeToBytes(item) - if err != nil { return 0, err } diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index b659fd6354..87a944b1c1 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -47,7 +47,7 @@ impl ParamKind { // only convert from_raw_ptr if not a supported primitive type or Program ParamKind::Pointer => { quote! { - wasmlanche_sdk::state::from_raw_ptr(#param_name) + unsafe { wasmlanche_sdk::state::from_raw_ptr(#param_name) } } } } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 956501ed02..eb2beabf78 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -81,12 +81,14 @@ impl State { /// with the subsequent [length] bytes comprising the serialized data. /// # Panics /// Panics if the bytes cannot be deserialized. +/// # Safety +/// This function is unsafe because it dereferences raw pointers. #[must_use] -pub fn from_raw_ptr(ptr: i64) -> V +pub unsafe fn from_raw_ptr(ptr: i64) -> V where V: BorshDeserialize, { - let (bytes, _) = unsafe { bytes_and_length(ptr) }; + let (bytes, _) = bytes_and_length(ptr); from_slice::(&bytes).expect("failed to deserialize") } From c27266651b37ca37e6a37529716a923ee22990c4 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 24 Nov 2023 00:14:34 -0600 Subject: [PATCH 34/74] remove temp go stuff --- x/programs/examples/counter_test.go | 5 +++-- x/programs/examples/testdata/token.wasm | Bin 60443 -> 37404 bytes x/programs/examples/token.go | 6 ++---- x/programs/examples/token_test.go | 6 +++--- x/programs/examples/util.go | 6 ++++++ 5 files changed, 14 insertions(+), 9 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 29dd12b3f6..33542f611b 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -58,9 +58,10 @@ func TestCounterProgram(t *testing.T) { // generate alice keys _, aliceKey, err := newKey() require.NoError(err) + aliceKeyBytes := fixedByteKey(aliceKey) // write alice's key to stack and get pointer - alicePtr, err := newPtr(ctx, aliceKey[:], rt, true) + alicePtr, err := newPtr(ctx, aliceKeyBytes, rt, true) require.NoError(err) // create counter for alice on program 1 @@ -96,7 +97,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := newPtr(ctx, aliceKey[:], rt2, true) + alicePtr2, err := newPtr(ctx, aliceKeyBytes, rt2, true) require.NoError(err) // initialize counter for alice on runtime 2 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index b5e06c6ae6daf793fe53fd36fc28772f82eb2270..9c95c220705e12bcfc0588efaeb72f3cc42c14a5 100755 GIT binary patch delta 15439 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 R;*)M|?F8Pv#*RY${{Sf=qN@M^ literal 60443 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 diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index b51e87627d..e6223a9016 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -92,8 +92,7 @@ func (t *Token) Run(ctx context.Context) error { if err != nil { return err } - var aliceKeyBytes [32]byte - copy(aliceKeyBytes[:], aliceKey[:]) + aliceKeyBytes := fixedByteKey(aliceKey) // write alice's key to stack and get pointer alicePtr, err := newPtr(ctx, aliceKeyBytes, rt, true) @@ -103,8 +102,7 @@ func (t *Token) Run(ctx context.Context) error { // generate bob keys _, bobKey, err := newKey() - var bobKeyBytes [32]byte - copy(bobKeyBytes[:], bobKey[:]) + bobKeyBytes := fixedByteKey(bobKey) if err != nil { return err diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index 46d7623d88..bd4ac68be0 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -24,7 +24,7 @@ var ( log = logging.NewLogger( "", logging.NewWrappedCore( - logging.Debug, + logging.Info, os.Stderr, logging.Plain.ConsoleEncoder(), )) @@ -33,8 +33,8 @@ var ( // go test -v -timeout 30s -run ^TestTokenProgram$ github.com/ava-labs/hypersdk/x/programs/examples -memprofile benchvset.mem -cpuprofile benchvset.cpu func TestTokenProgram(t *testing.T) { require := require.New(t) - maxUnits := uint64(4000000) - cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() + maxUnits := uint64(40000) + cfg, err := runtime.NewConfigBuilder().Build() require.NoError(err) program, err := newTokenProgram(maxUnits, cfg, tokenProgramBytes) require.NoError(err) diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index fb0197d08c..c598b87b01 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -70,6 +70,12 @@ func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { return priv, priv.PublicKey(), nil } +func fixedByteKey(key ed25519.PublicKey) [32]byte { + var fixedKey [32]byte + copy(fixedKey[:], key[:]) + return fixedKey +} + var ( _ state.Mutable = &testDB{} _ state.Immutable = &testDB{} From 813ffdc8256ca5300e18e6054ef94a89e706a2be Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 28 Nov 2023 12:03:10 -0800 Subject: [PATCH 35/74] tidy --- go.mod | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/go.mod b/go.mod index e0ff6bc519..d5a2407137 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,7 @@ require ( github.com/gorilla/rpc v1.2.0 github.com/gorilla/websocket v1.5.0 github.com/manifoldco/promptui v0.9.0 + github.com/near/borsh-go v0.3.1 github.com/neilotoole/errgroup v0.1.6 github.com/oasisprotocol/curve25519-voi v0.0.0-20230110094441-db37f07504ce github.com/onsi/ginkgo/v2 v2.8.1 @@ -93,7 +94,6 @@ require ( github.com/mitchellh/pointerstructure v1.2.0 // indirect github.com/mr-tron/base58 v1.2.0 // indirect github.com/nbutton23/zxcvbn-go v0.0.0-20180912185939-ae427f1e4c1d // indirect - github.com/near/borsh-go v0.3.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/openzipkin/zipkin-go v0.4.1 // indirect github.com/otiai10/copy v1.11.0 // indirect From 3d61aee6bf7e3e97d5ac632c98df0e12e4115e42 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 28 Nov 2023 12:09:20 -0800 Subject: [PATCH 36/74] remove comment --- x/programs/examples/token.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index e6223a9016..f0789eb2f0 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -234,10 +234,6 @@ func (t *Token) Run(ctx context.Context) error { } t.log.Debug("balance", zap.Int64("bob", result[0])) - // t.log.Debug("remaining balance", - // zap.Uint64("unit", rt.Meter().GetBalance()), - // ) - return nil } From 2f0090e520377d378eb03ffe34362bbe99851512 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 29 Nov 2023 16:30:03 -0800 Subject: [PATCH 37/74] decompose newPtr method + nits --- x/programs/examples/counter_test.go | 4 +-- x/programs/examples/token.go | 16 ++++----- x/programs/examples/util.go | 41 ++++++++++++++--------- x/programs/rust/examples/token/src/lib.rs | 10 +++--- 4 files changed, 41 insertions(+), 30 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 33542f611b..43eb9a7a98 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -61,7 +61,7 @@ func TestCounterProgram(t *testing.T) { aliceKeyBytes := fixedByteKey(aliceKey) // write alice's key to stack and get pointer - alicePtr, err := newPtr(ctx, aliceKeyBytes, rt, true) + alicePtr, err := newParameterPtr(ctx, aliceKeyBytes, rt) require.NoError(err) // create counter for alice on program 1 @@ -97,7 +97,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := newPtr(ctx, aliceKeyBytes, rt2, true) + alicePtr2, err := newParameterPtr(ctx, aliceKeyBytes, rt2) require.NoError(err) // initialize counter for alice on runtime 2 diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index f0789eb2f0..4434f1f89c 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -28,7 +28,7 @@ func NewToken(log logging.Logger, programBytes []byte, db state.Mutable, cfg *ru } } -type mintingRecipient struct { +type minter struct { To [32]byte Amount int32 } @@ -95,7 +95,7 @@ func (t *Token) Run(ctx context.Context) error { aliceKeyBytes := fixedByteKey(aliceKey) // write alice's key to stack and get pointer - alicePtr, err := newPtr(ctx, aliceKeyBytes, rt, true) + alicePtr, err := newParameterPtr(ctx, aliceKeyBytes, rt) if err != nil { return err } @@ -109,7 +109,7 @@ func (t *Token) Run(ctx context.Context) error { } // write bob's key to stack and get pointer - bobPtr, err := newPtr(ctx, bobKey, rt, true) + bobPtr, err := newParameterPtr(ctx, bobKey, rt) if err != nil { return err } @@ -192,7 +192,7 @@ func (t *Token) Run(ctx context.Context) error { ) // combine alice and bobs addresses - payments := []mintingRecipient{ + minters := []minter{ { To: aliceKeyBytes, Amount: 10, @@ -203,19 +203,19 @@ func (t *Token) Run(ctx context.Context) error { }, } - addressesPtr, err := newPtr(ctx, payments, rt, true) + mintersPtr, err := newParameterPtr(ctx, minters, rt) if err != nil { return err } // perform bulk mint - _, err = rt.Call(ctx, "mint_to_many", programIDPtr, addressesPtr) + _, err = rt.Call(ctx, "mint_to_many", programIDPtr, mintersPtr) if err != nil { return err } t.log.Debug("minted many", - zap.Int32("alice", payments[0].Amount), - zap.Int32("to bob", payments[1].Amount), + zap.Int32("alice", minters[0].Amount), + zap.Int32("to bob", minters[1].Amount), ) // get balance alice diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index c598b87b01..8fc2f8cc60 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -19,19 +19,8 @@ import ( // newPtr allocates memory and writes [bytes] to it. // If [prependLength] is true, it prepends the length of [bytes] as a uint32 to [bytes]. // It returns the pointer to the allocated memory. -func newPtr(ctx context.Context, item interface{}, rt runtime.Runtime, prependLength bool) (int64, error) { - bytes, err := serializeToBytes(item) - if err != nil { - return 0, err - } - +func newPtr(ctx context.Context, bytes []byte, rt runtime.Runtime) (int64, error) { amountToAllocate := uint64(len(bytes)) - writeBytes := bytes - - if prependLength { - amountToAllocate += consts.Uint32Len - writeBytes = marshalArg(bytes) - } ptr, err := rt.Memory().Alloc(amountToAllocate) if err != nil { @@ -39,7 +28,7 @@ func newPtr(ctx context.Context, item interface{}, rt runtime.Runtime, prependLe } // write programID to memory which we will later pass to the program - err = rt.Memory().Write(ptr, writeBytes) + err = rt.Memory().Write(ptr, bytes) if err != nil { return 0, err } @@ -47,11 +36,30 @@ func newPtr(ctx context.Context, item interface{}, rt runtime.Runtime, prependLe return int64(ptr), err } -func serializeToBytes(obj interface{}) ([]byte, error) { - return borsh.Serialize(obj) +// serializeParameter serializes [obj] +// using Borsh and prepends its length as a uint32. +// Designed for serializing parameters passed to a WASM program. +func serializeParameter(obj interface{}) ([]byte, error) { + bytes, err := borsh.Serialize(obj) + if err != nil { + return nil, err + } + marshalArg(bytes) + return bytes, nil +} + +// newParameterPtr serializes [obj] and allocates memory for it. +func newParameterPtr(ctx context.Context, obj interface{}, rt runtime.Runtime) (int64, error) { + bytes, err := serializeParameter(obj) + if err != nil { + return 0, err + } + return newPtr(ctx, bytes, rt) } // marshalArg prepends the length of [arg] as a uint32 to [arg]. +// This is required by the program inorder to grab the correct number +// of bytes from memory. func marshalArg(arg []byte) []byte { // add length prefix to arg as big endian uint32 argLen := len(arg) @@ -70,6 +78,9 @@ func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { return priv, priv.PublicKey(), nil } +// fixedByteKey converts [key] into a [32]byte representation. +// Due to Borsh's distinct serialization of fixed/dynamic arrays, +// our program expects a fixed-sized array for deserialization. func fixedByteKey(key ed25519.PublicKey) [32]byte { var fixedKey [32]byte copy(fixedKey[:], key[:]) diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 6f91cf4a1d..edaa60f591 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -102,16 +102,16 @@ pub fn transfer(program: Program, sender: Address, recipient: Address, amount: i } #[derive(BorshDeserialize, BorshSerialize)] -pub struct MintingRecipient { - recipient: Address, +pub struct Minter { + to: Address, amount: i32, } /// Mints tokens to multiple recipients. #[public] -pub fn mint_to_many(program: Program, minting_recipients: Vec) -> bool { - for info in minting_recipients.iter() { - mint_to(program, info.recipient, info.amount as i64); +pub fn mint_to_many(program: Program, minters: Vec) -> bool { + for minter in minters.iter() { + mint_to(program, minter.to, minter.amount as i64); } true From ede907a77b9f1034a760a77dc953fd414b4a3206 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 29 Nov 2023 16:53:31 -0800 Subject: [PATCH 38/74] remove fixedLengthKey method --- x/programs/examples/counter_test.go | 5 ++--- x/programs/examples/token.go | 9 +++------ x/programs/examples/util.go | 13 ++----------- 3 files changed, 7 insertions(+), 20 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 43eb9a7a98..bdb128c108 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -58,10 +58,9 @@ func TestCounterProgram(t *testing.T) { // generate alice keys _, aliceKey, err := newKey() require.NoError(err) - aliceKeyBytes := fixedByteKey(aliceKey) // write alice's key to stack and get pointer - alicePtr, err := newParameterPtr(ctx, aliceKeyBytes, rt) + alicePtr, err := newParameterPtr(ctx, aliceKey, rt) require.NoError(err) // create counter for alice on program 1 @@ -97,7 +96,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := newParameterPtr(ctx, aliceKeyBytes, rt2) + alicePtr2, err := newParameterPtr(ctx, aliceKey, rt2) require.NoError(err) // initialize counter for alice on runtime 2 diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index 4434f1f89c..3809b9abbf 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -92,18 +92,15 @@ func (t *Token) Run(ctx context.Context) error { if err != nil { return err } - aliceKeyBytes := fixedByteKey(aliceKey) // write alice's key to stack and get pointer - alicePtr, err := newParameterPtr(ctx, aliceKeyBytes, rt) + alicePtr, err := newParameterPtr(ctx, aliceKey, rt) if err != nil { return err } // generate bob keys _, bobKey, err := newKey() - bobKeyBytes := fixedByteKey(bobKey) - if err != nil { return err } @@ -194,11 +191,11 @@ func (t *Token) Run(ctx context.Context) error { // combine alice and bobs addresses minters := []minter{ { - To: aliceKeyBytes, + To: aliceKey, Amount: 10, }, { - To: bobKeyBytes, + To: bobKey, Amount: 12, }, } diff --git a/x/programs/examples/util.go b/x/programs/examples/util.go index 8fc2f8cc60..6d3f314d42 100644 --- a/x/programs/examples/util.go +++ b/x/programs/examples/util.go @@ -44,8 +44,8 @@ func serializeParameter(obj interface{}) ([]byte, error) { if err != nil { return nil, err } - marshalArg(bytes) - return bytes, nil + + return marshalArg(bytes), nil } // newParameterPtr serializes [obj] and allocates memory for it. @@ -78,15 +78,6 @@ func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { return priv, priv.PublicKey(), nil } -// fixedByteKey converts [key] into a [32]byte representation. -// Due to Borsh's distinct serialization of fixed/dynamic arrays, -// our program expects a fixed-sized array for deserialization. -func fixedByteKey(key ed25519.PublicKey) [32]byte { - var fixedKey [32]byte - copy(fixedKey[:], key[:]) - return fixedKey -} - var ( _ state.Mutable = &testDB{} _ state.Immutable = &testDB{} From 968661c35eb65edbc6f217809b5f3754d2785221 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 1 Dec 2023 16:19:19 -0800 Subject: [PATCH 39/74] return result in from_raw_ptr --- x/programs/rust/sdk_macros/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/errors.rs | 3 +++ x/programs/rust/wasmlanche_sdk/src/state.rs | 7 ++++--- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index dd7e25f268..d531f1890b 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -47,7 +47,7 @@ impl ParamKind { // only convert from_raw_ptr if not a supported primitive type or Program ParamKind::Pointer => { quote! { - unsafe { wasmlanche_sdk::state::from_raw_ptr(#param_name) } + unsafe { wasmlanche_sdk::state::from_raw_ptr(#param_name).expect("error serializing ptr") } } } } diff --git a/x/programs/rust/wasmlanche_sdk/src/errors.rs b/x/programs/rust/wasmlanche_sdk/src/errors.rs index 30b70fab74..b64e7538f6 100644 --- a/x/programs/rust/wasmlanche_sdk/src/errors.rs +++ b/x/programs/rust/wasmlanche_sdk/src/errors.rs @@ -22,4 +22,7 @@ pub enum StateError { #[error("failed to serialize bytes")] Serialization, + + #[error("failed to deserialize bytes")] + Deserialization, } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index dbf664c832..654bafb760 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -55,7 +55,7 @@ impl State { } // Wrap in OK for now, change from_raw_ptr to return Result - Ok(unsafe { from_raw_ptr(val_ptr) }) + unsafe { from_raw_ptr(val_ptr) } } } @@ -67,12 +67,12 @@ impl State { /// # Safety /// This function is unsafe because it dereferences raw pointers. #[must_use] -pub unsafe fn from_raw_ptr(ptr: i64) -> V +pub unsafe fn from_raw_ptr(ptr: i64) -> Result where V: BorshDeserialize, { let (bytes, _) = bytes_and_length(ptr); - from_slice::(&bytes).expect("failed to deserialize") + from_slice::(&bytes).map_err(|_| StateError::Deserialization) } // TODO: move this logic to return a Memory struct that conatins ptr + length @@ -94,6 +94,7 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { (value[4..].to_vec(), len) } +/// Returns a vector of bytes with the length of the argument prepended. pub fn prepend_length(bytes: &[u8]) -> Vec { let mut len_bytes = bytes.len().to_be_bytes().to_vec(); len_bytes.extend(bytes); From a4f4a15e8f95cf75e2aa121f5d77ce9d63473df5 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 1 Dec 2023 17:02:47 -0800 Subject: [PATCH 40/74] conflicts from merge --- x/programs/rust/examples/token/src/lib.rs | 20 +------------------- x/programs/rust/wasmlanche_sdk/src/state.rs | 6 +++--- x/programs/rust/wasmlanche_sdk/src/types.rs | 19 ------------------- 3 files changed, 4 insertions(+), 41 deletions(-) diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index 234d4fb92f..d6e423af38 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,7 +1,5 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; -use borsh::{BorshDeserialize, BorshSerialize}; -use wasmlanche_sdk::{program::Program, public, state_keys, types::Address, state::Key}; +use wasmlanche_sdk::{program::Program, public, state_keys, state::Key, types::Address}; /// The program state keys. #[state_keys] @@ -113,22 +111,6 @@ pub fn mint_to_many(program: Program, minters: Vec) -> bool { true } -#[derive(BorshDeserialize, BorshSerialize)] -pub struct Minter { - to: Address, - amount: i32, -} - -/// Mints tokens to multiple recipients. -#[public] -pub fn mint_to_many(program: Program, minters: Vec) -> bool { - for minter in minters.iter() { - mint_to(program, minter.to, minter.amount as i64); - } - - true -} - /// Gets the balance of the recipient. #[public] pub fn get_balance(program: Program, recipient: Address) -> i64 { diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index df56780c9a..3e53a5e6c4 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -3,7 +3,7 @@ use crate::{ host::{get_bytes, put_bytes}, program::Program, }; -use borsh::{from_slice, to_vec, BorshDeserialize, BorshSerialize}; +use borsh::{from_slice, BorshDeserialize, BorshSerialize}; pub struct State { program: Program, @@ -46,8 +46,8 @@ impl State { /// Panics if the value cannot be converted from i32 to usize. pub fn get(&self, key: K) -> Result where - K: AsRef<[u8]>, - T: DeserializeOwned, + K: Into, + T: BorshDeserialize, { let val_ptr = unsafe { get_bytes(&self.program, &key.into()) }; if val_ptr < 0 { diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 406dff5dbc..45fe21df44 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -7,9 +7,6 @@ use std::borrow::Cow; #[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] pub struct Address([u8; Self::LEN]); -#[derive(Clone, Copy, PartialEq, Eq, Debug, BorshSerialize, BorshDeserialize)] -pub struct Address([u8; Self::LEN]); - impl Address { // TODO: move to HyperSDK.Address which will be 33 bytes pub const LEN: usize = 32; @@ -50,7 +47,6 @@ pub trait Argument { impl Argument for Address { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Borrowed(self.as_bytes()) - Cow::Borrowed(self.as_bytes()) } } @@ -72,15 +68,6 @@ impl Argument for i32 { } } -impl Argument for i32 { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } -} - impl Argument for Program { fn as_bytes(&self) -> Cow<'_, [u8]> { Cow::Owned(self.id().to_be_bytes().to_vec()) @@ -95,9 +82,3 @@ impl Argument for String { Cow::Borrowed(self.as_bytes()) } } - -impl Argument for String { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Borrowed(self.as_bytes()) - } -} From 236e963b3b0ebb80c41f24b0ba4f2124e5de995c Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 2 Dec 2023 12:52:37 -0800 Subject: [PATCH 41/74] represent pointers as *const u8 --- x/programs/rust/wasmlanche_sdk/src/host/state.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 79049de97b..c9b50c6646 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -10,10 +10,10 @@ use borsh::{to_vec, BorshSerialize}; #[link(wasm_import_module = "state")] extern "C" { #[link_name = "put"] - fn _put(caller_id: i64, key: i64, value: i64) -> i32; + fn _put(caller_id: i64, key_ptr: *const u8, value: *const u8) -> i32; #[link_name = "get"] - fn _get(caller_id: i64, key_ptr: i64) -> i64; + fn _get(caller_id: i64, key_ptr: *const u8) -> i64; } /// Persists the bytes at `value_ptr` to the bytes at key ptr on the host storage. @@ -32,7 +32,7 @@ where let value_bytes = prepend_length(&value_bytes); let key_bytes = prepend_length(key.as_bytes()); - match unsafe { _put(caller.id(), key_bytes.as_ptr() as i64, value_bytes.as_ptr() as i64) } { + match unsafe { _put(caller.id(), key_bytes.as_ptr(), value_bytes.as_ptr()) } { 0 => Ok(()), _ => Err(StateError::Write), } @@ -55,5 +55,5 @@ where pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key let key = prepend_length(key.as_bytes()); - unsafe { _get(caller.id(), key.as_ptr() as i64) } + unsafe { _get(caller.id(), key.as_ptr()) } } From 2d240c8f2fea2a8d59c6e5d1a6933367e736277e Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 2 Dec 2023 12:58:32 -0800 Subject: [PATCH 42/74] comments --- x/programs/examples/imports/util.go | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/x/programs/examples/imports/util.go b/x/programs/examples/imports/util.go index a05d570a87..77ecab1d4c 100644 --- a/x/programs/examples/imports/util.go +++ b/x/programs/examples/imports/util.go @@ -7,20 +7,18 @@ import ( "github.com/ava-labs/hypersdk/x/programs/runtime" ) -// grabBytesFromPtr returns bytes from memory at [ptr]. -func GrabBytesFromPtr(client runtime.WasmtimeExportClient, ptr int64) ([]byte, error) { +// GetBytesFromPtr returns the bytes at [ptr] in [client] memory. +func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptr int64) ([]byte, error) { memory := runtime.NewMemory(client) - // grab the first 4 bytes from ptr which is the length of bytes + // first 4 bytes represent the length lenBytes, err := memory.Range(uint64(ptr), consts.Uint32Len) if err != nil { return nil, err } - - // convert to uint32 length := binary.BigEndian.Uint32(lenBytes) - // grab the remaining bytes from ptr which is the actual bytes + // The following [length] bytes represent the bytes to return bytes, err := memory.Range(uint64(ptr + consts.Uint32Len), uint64(length)) if err != nil { return nil, err @@ -29,6 +27,7 @@ func GrabBytesFromPtr(client runtime.WasmtimeExportClient, ptr int64) ([]byte, e return bytes, nil } +// PrependLength returns the length of [bytes] prepended to [bytes]. func PrependLength(bytes []byte) []byte { length := uint32(len(bytes)) lenBytes := make([]byte, consts.Uint32Len) From cdd09a32462a8df7bc13e80ae9f335112fb96b37 Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 2 Dec 2023 13:03:02 -0800 Subject: [PATCH 43/74] remove import --- x/programs/examples/imports/pstate/pstate.go | 6 +++--- x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/examples/token/src/lib.rs | 2 +- x/programs/rust/sdk_macros/src/lib.rs | 6 +++--- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 61926a40ec..f2ccfaeded 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -71,7 +71,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64, value return -1 } - keyBytes, err := imports.GrabBytesFromPtr(client, keyPtr) + keyBytes, err := imports.GetBytesFromPtr(client, keyPtr) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -79,7 +79,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64, value return -1 } - valueBytes, err := imports.GrabBytesFromPtr(client, valuePtr) + valueBytes, err := imports.GetBytesFromPtr(client, valuePtr) if err != nil { i.log.Error("failed to read value from memory", zap.Error(err), @@ -110,7 +110,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64) int64 return -1 } - keyBytes, err := imports.GrabBytesFromPtr(client, keyPtr) + keyBytes, err := imports.GetBytesFromPtr(client, keyPtr) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 842c0d8742..7e53bad1f5 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state::Key, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/examples/token/src/lib.rs b/x/programs/rust/examples/token/src/lib.rs index d6e423af38..fd03f407e2 100644 --- a/x/programs/rust/examples/token/src/lib.rs +++ b/x/programs/rust/examples/token/src/lib.rs @@ -1,5 +1,5 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use wasmlanche_sdk::{program::Program, public, state_keys, state::Key, types::Address}; +use wasmlanche_sdk::{program::Program, public, state_keys, types::Address}; /// The program state keys. #[state_keys] diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index d531f1890b..0d921cc3ab 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -165,9 +165,9 @@ pub fn state_keys(_attr: TokenStream, item: TokenStream) -> TokenStream { // Generate the Into implementation needed to // convert the enum to a Key type. - impl Into for #name { - fn into(self) -> Key { - Key::new(self.to_vec()) + impl Into for #name { + fn into(self) -> wasmlanche_sdk::state::Key { + wasmlanche_sdk::state::Key::new(self.to_vec()) } } }; From 4449ad77c6dfa256108d1280cd703458ed3f3af1 Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 2 Dec 2023 13:10:07 -0800 Subject: [PATCH 44/74] remove len --- Cargo.toml | 1 - x/programs/rust/examples/verify/Cargo.toml | 8 -------- x/programs/rust/examples/verify/src/main.rs | 3 --- x/programs/rust/sdk_macros/Cargo.toml | 3 --- x/programs/rust/wasmlanche_sdk/src/host/state.rs | 14 ++------------ 5 files changed, 2 insertions(+), 27 deletions(-) delete mode 100644 x/programs/rust/examples/verify/Cargo.toml delete mode 100644 x/programs/rust/examples/verify/src/main.rs diff --git a/Cargo.toml b/Cargo.toml index 7c2416e12e..0971adb859 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,7 +5,6 @@ members = [ "x/programs/rust/wasmlanche_sdk", "x/programs/rust/examples/token", "x/programs/rust/examples/counter", - "x/programs/rust/examples/verify", ] resolver = "2" diff --git a/x/programs/rust/examples/verify/Cargo.toml b/x/programs/rust/examples/verify/Cargo.toml deleted file mode 100644 index 813ce7aa4b..0000000000 --- a/x/programs/rust/examples/verify/Cargo.toml +++ /dev/null @@ -1,8 +0,0 @@ -[package] -name = "verify" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] diff --git a/x/programs/rust/examples/verify/src/main.rs b/x/programs/rust/examples/verify/src/main.rs deleted file mode 100644 index e7a11a969c..0000000000 --- a/x/programs/rust/examples/verify/src/main.rs +++ /dev/null @@ -1,3 +0,0 @@ -fn main() { - println!("Hello, world!"); -} diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index 1248202b94..93fb1a35cb 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -6,9 +6,6 @@ edition = "2021" [lib] proc-macro = true -[dev-dependencies] -wasmlanche_sdk = { version = "0.1.0", path = "../wasmlanche_sdk" } - [dependencies] proc-macro2 = "1.0.67" quote = "1.0.33" diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index c9b50c6646..e4b115a8d0 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -19,8 +19,7 @@ extern "C" { /// Persists the bytes at `value_ptr` to the bytes at key ptr on the host storage. /// /// # Safety -/// The caller must ensure that `key_ptr` + `key_len` and -/// `value_ptr` + `value_len` point to valid memory locations. +/// TODO: #[must_use] pub(crate) unsafe fn put_bytes(caller: &Program, key: &Key, value: &V) -> Result<(), StateError> where @@ -38,19 +37,10 @@ where } } -/// Returns the length of the bytes associated with the key from the host storage. -/// -/// # Safety -/// The caller must ensure that `key_ptr` + `key_len` points to valid memory locations. -// #[must_use] -// pub(crate) unsafe fn len_bytes(caller: &Program, key: &Key) -> i32 { -// unsafe { _len(caller.id(), key.as_bytes().as_ptr(), key.len()) } -// } - /// Gets the bytes associated with the key from the host. /// /// # Safety -/// The caller must ensure that `key_ptr` + `key_len` points to valid memory locations. +/// TODO: #[must_use] pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key From ed5ab6aa121d638cacd9f05a8112b69482433f6d Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 2 Dec 2023 13:17:48 -0800 Subject: [PATCH 45/74] rust lint --- x/programs/rust/wasmlanche_sdk/src/host/state.rs | 2 -- x/programs/rust/wasmlanche_sdk/src/state.rs | 16 ++++++---------- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index e4b115a8d0..ab8c769580 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -20,7 +20,6 @@ extern "C" { /// /// # Safety /// TODO: -#[must_use] pub(crate) unsafe fn put_bytes(caller: &Program, key: &Key, value: &V) -> Result<(), StateError> where V: BorshSerialize, @@ -41,7 +40,6 @@ where /// /// # Safety /// TODO: -#[must_use] pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key let key = prepend_length(key.as_bytes()); diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 3e53a5e6c4..0c529c7904 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -25,13 +25,7 @@ impl State { V: BorshSerialize, K: Into, { - unsafe { - put_bytes( - &self.program, - &key.into(), - value, - ) - } + unsafe { put_bytes(&self.program, &key.into(), value) } } /// Get a value from the host's storage. @@ -55,7 +49,7 @@ impl State { } // Wrap in OK for now, change from_raw_ptr to return Result - unsafe { from_raw_ptr(val_ptr) } + unsafe { from_raw_ptr(val_ptr) } } } @@ -66,7 +60,8 @@ impl State { /// Panics if the bytes cannot be deserialized. /// # Safety /// This function is unsafe because it dereferences raw pointers. -#[must_use] +/// # Errors +/// Returns an `StateError` if the bytes cannot be deserialized. pub unsafe fn from_raw_ptr(ptr: i64) -> Result where V: BorshDeserialize, @@ -95,6 +90,7 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { } /// Returns a vector of bytes with the length of the argument prepended. +#[must_use] pub fn prepend_length(bytes: &[u8]) -> Vec { let mut len_bytes = bytes.len().to_be_bytes().to_vec(); len_bytes.extend(bytes); @@ -125,4 +121,4 @@ impl Key { pub fn is_empty(&self) -> bool { self.len() == 0 } -} \ No newline at end of file +} From f207a5f10b42b6a15b6f80c14f66683f8ea7f72f Mon Sep 17 00:00:00 2001 From: samliok Date: Sun, 3 Dec 2023 00:24:34 -0800 Subject: [PATCH 46/74] lfg some progress on serialize_param macro --- x/programs/examples/counter_test.go | 21 ++-- .../examples/imports/program/program.go | 60 +++++++---- x/programs/examples/imports/pstate/pstate.go | 12 +-- x/programs/examples/imports/util.go | 7 +- x/programs/examples/testdata/counter.wasm | Bin 33951 -> 59438 bytes x/programs/examples/testdata/token.wasm | Bin 37336 -> 34646 bytes x/programs/examples/token.go | 1 - x/programs/examples/token_test.go | 2 +- x/programs/rust/examples/counter/src/lib.rs | 6 +- x/programs/rust/wasmlanche_sdk/src/program.rs | 65 ++++++++---- x/programs/rust/wasmlanche_sdk/src/state.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/types.rs | 94 +++++++++--------- 12 files changed, 158 insertions(+), 112 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index bdb128c108..334e7374f9 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -6,6 +6,7 @@ package examples import ( "context" _ "embed" + "fmt" "testing" "github.com/stretchr/testify/require" @@ -25,8 +26,8 @@ var counterProgramBytes []byte func TestCounterProgram(t *testing.T) { require := require.New(t) db := newTestDB() - maxUnits := uint64(40000) - cfg, err := runtime.NewConfigBuilder().Build() + maxUnits := uint64(4000000) + cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() require.NoError(err) ctx, cancel := context.WithCancel(context.Background()) @@ -109,9 +110,9 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) require.Equal(int64(1), result[0]) - result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) - require.NoError(err) - require.Equal(int64(10), result[0]) + // result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) + // require.NoError(err) + // require.Equal(int64(10), result[0]) // stop the runtime to prevent further execution rt2.Stop() @@ -137,22 +138,24 @@ func TestCounterProgram(t *testing.T) { ) // write program id 2 to stack of program 1 + fmt.Println("allocation program id 2") programID2Ptr, err = runtime.WriteBytes(rt.Memory(), program2ID[:]) require.NoError(err) + fmt.Println("finsihed allocation program id 2") caller := programIDPtr target := programID2Ptr maxUnitsProgramToProgram := int64(10000) // increment alice's counter on program 2 - result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgram, alicePtr, 5) - require.NoError(err) - require.Equal(int64(1), result[0]) + // result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgram, alicePtr, 5) + // require.NoError(err) + // require.Equal(int64(1), result[0]) // expect alice's counter on program 2 to be 15 result, err = rt.Call(ctx, "get_value_external", caller, target, maxUnitsProgramToProgram, alicePtr) require.NoError(err) - require.Equal(int64(15), result[0]) + require.Equal(int64(10), result[0]) require.Greater(rt.Meter().GetBalance(), uint64(0)) } diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index a5f349ea24..d996164c00 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -5,6 +5,7 @@ package program import ( "context" + "encoding/binary" "fmt" "go.uber.org/zap" @@ -13,7 +14,7 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/bytecodealliance/wasmtime-go/v14" - "github.com/ava-labs/hypersdk/codec" + "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/state" "github.com/ava-labs/hypersdk/x/programs/examples/storage" "github.com/ava-labs/hypersdk/x/programs/runtime" @@ -71,7 +72,6 @@ func (i *Import) callProgramFn( ctx, cancel := context.WithCancel(context.Background()) defer cancel() memory := runtime.NewMemory(runtime.NewExportClient(caller)) - // get the entry function for invoke to call. functionBytes, err := memory.Range(uint64(functionPtr), uint64(functionLen)) if err != nil { @@ -96,7 +96,7 @@ func (i *Import) callProgramFn( zap.Error(err), ) return -1 - } + } // create a new runtime for the program to be invoked with a zero balance. rt := runtime.New(i.log, i.cfg, i.imports) @@ -173,28 +173,44 @@ func (i *Import) callProgramFn( func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, invokeProgramID int64) ([]int64, error) { // first arg contains id of program to call args := []int64{invokeProgramID} - p := codec.NewReader(buffer, len(buffer)) + // p := codec.NewReader(buffer, len(buffer)) + // i := 0 + // for !p.Empty() { + // // unpacks uint32 + // size := p.UnpackInt(true) + + // valueBytes := make([]byte, size) + // p.UnpackFixedBytes(int(size), &valueBytes) + // ptr, err := runtime.WriteBytes(memory, valueBytes) + // if err != nil { + // return nil, err + // } + // args = append(args, ptr) + // i++ + // } + // if p.Err() != nil { + // return nil, fmt.Errorf("failed to unpack arguments: %w", p.Err()) + // } i := 0 - for !p.Empty() { - size := p.UnpackInt64(true) - isInt := p.UnpackBool() - if isInt { - valueInt := p.UnpackInt64(true) - args = append(args, valueInt) - } else { - valueBytes := make([]byte, size) - p.UnpackFixedBytes(int(size), &valueBytes) - ptr, err := runtime.WriteBytes(memory, valueBytes) - if err != nil { - return nil, err - } - args = append(args, ptr) + for i < len(buffer) { + fmt.Println("i", i) + // unpacks uint32 + lenBytes := buffer[i:i+consts.Uint32Len] + length := binary.BigEndian.Uint32(lenBytes) + totalLength := int(consts.Uint32Len + length) + + + valueBytes := buffer[i:i + totalLength] + i += consts.Uint32Len + int(length) + + ptr, err := runtime.WriteBytes(memory, valueBytes) + if err != nil { + return nil, err } - i++ - } - if p.Err() != nil { - return nil, fmt.Errorf("failed to unpack arguments: %w", p.Err()) + args = append(args, ptr) } + + return args, nil } diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index f2ccfaeded..84e228e393 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -60,7 +60,7 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, _ runtime.Supp return nil } -func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64, valuePtr int64) int32 { +func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32, valuePtr int32) int32 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) @@ -71,7 +71,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64, value return -1 } - keyBytes, err := imports.GetBytesFromPtr(client, keyPtr) + keyBytes, err := imports.GetBytesFromPtr(client, int64(keyPtr)) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -79,7 +79,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64, value return -1 } - valueBytes, err := imports.GetBytesFromPtr(client, valuePtr) + valueBytes, err := imports.GetBytesFromPtr(client, int64(valuePtr)) if err != nil { i.log.Error("failed to read value from memory", zap.Error(err), @@ -99,7 +99,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64, value return 0 } -func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64) int64 { +func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) @@ -110,7 +110,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64) int64 return -1 } - keyBytes, err := imports.GetBytesFromPtr(client, keyPtr) + keyBytes, err := imports.GetBytesFromPtr(client, int64(keyPtr)) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -135,7 +135,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int64) int64 ) return -1 } - + // prepend the length so that the program can grab the correct number of bytes val = imports.PrependLength(val) ptr, err := runtime.WriteBytes(memory, val) diff --git a/x/programs/examples/imports/util.go b/x/programs/examples/imports/util.go index 77ecab1d4c..ac2cdbda37 100644 --- a/x/programs/examples/imports/util.go +++ b/x/programs/examples/imports/util.go @@ -1,3 +1,6 @@ +// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. +// See the file LICENSE for licensing terms. + package imports import ( @@ -19,7 +22,7 @@ func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptr int64) ([]byte, er length := binary.BigEndian.Uint32(lenBytes) // The following [length] bytes represent the bytes to return - bytes, err := memory.Range(uint64(ptr + consts.Uint32Len), uint64(length)) + bytes, err := memory.Range(uint64(ptr+consts.Uint32Len), uint64(length)) if err != nil { return nil, err } @@ -33,4 +36,4 @@ func PrependLength(bytes []byte) []byte { lenBytes := make([]byte, consts.Uint32Len) binary.BigEndian.PutUint32(lenBytes, length) return append(lenBytes, bytes...) -} \ No newline at end of file +} diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index 7cc8c3e54e4d0837e853c74d39ae3fab898c0828..5f6257982cbb125ed598372b5ef9039d28d4328c 100755 GIT binary patch literal 59438 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 z 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 WKUnz9ulRA0vYD6hu>3os|NIxK`+<=F literal 33951 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 z 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 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index dae32bf5c613bb1ee8972f15c2283ef0011e24f1..ef436f275befdbd61ce0531779454f9d2e5dd3b7 100755 GIT binary patch delta 11545 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 a&1r9FYFoB?m0I!a_@G?8xTU$Z^?v|VyN|j6 delta 14329 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 i64 { - program.call_program(&target, max_units, "inc", &[Box::new(of), Box::new(amount)]) + program.call_program(&target, max_units, "inc", serialize_params!(of, amount)) } /// Gets the count at the address. @@ -62,5 +62,5 @@ fn get_value(program: Program, of: Address) -> i64 { /// Gets the count at the address for an external program. #[public] fn get_value_external(program: Program, target: Program, max_units: i64, of: Address) -> i64 { - program.call_program(&target, max_units, "get_value", &[Box::new(of)]) + program.call_program(&target, max_units, "get_value", serialize_params!(of)) } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 60757cd3de..176c0b798d 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,6 +1,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; +use borsh::{to_vec}; -use crate::{host::call_program, state::State, types::Argument}; +use crate::{host::call_program, state::{State, prepend_length}}; /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. @@ -32,14 +33,16 @@ impl Program { target: &Program, max_units: i64, function_name: &str, - args: &[Box], + args: Vec>, ) -> i64 { + // flatten the args into a single byte vector + let args = args.into_iter().flatten().collect::>(); call_program( self, target, max_units, function_name, - marshal_args(args).as_ref(), + &args ) } } @@ -56,24 +59,46 @@ impl From for Program { } } -/// Marshals arguments into byte slice which can be unpacked by the host. -fn marshal_args(args: &[Box]) -> Vec { - use std::mem::size_of; - // Size of meta data for each argument - const META_SIZE: usize = size_of::() + 1; +// /// Marshals arguments into byte slice which can be unpacked by the host. +// fn marshal_args(args: &[Box]) -> Vec { +// use std::mem::size_of; +// // Size of meta data for each argument +// const META_SIZE: usize = size_of::() + 1; - // Calculate the total size of the combined byte slices - let total_size = args.iter().map(|cow| cow.len() + META_SIZE).sum(); +// // Calculate the total size of the combined byte slices +// let total_size = args.iter().map(|cow| cow.len() + META_SIZE).sum(); - // Create a mutable Vec to hold the combined bytes - let mut bytes = Vec::with_capacity(total_size); +// // Create a mutable Vec to hold the combined bytes +// let mut bytes = Vec::with_capacity(total_size); - for arg in args { - // if we want to be efficient we dont need to add length of bytes if its an int - let len = i64::try_from(arg.len()).expect("Error converting to i64"); - bytes.extend_from_slice(&len.as_bytes()); - bytes.extend_from_slice(&[u8::from(arg.is_primitive())]); - bytes.extend_from_slice(&arg.as_bytes()); - } - bytes +// for arg in args { +// // if we want to be efficient we dont need to add length of bytes if its an int +// let len = i64::try_from(arg.len()).expect("Error converting to i64"); +// bytes.extend_from_slice(&len.as_bytes()); +// bytes.extend_from_slice(&[u8::from(arg.is_primitive())]); +// bytes.extend_from_slice(&arg.as_bytes()); +// } +// bytes +// } + +#[macro_export] +macro_rules! serialize_params { + ($($param:expr),*) => { + { + // the macro expands into this block. This will serialize every parameter + // into a byte vector and return a vector of byte vectors. + let mut params = Vec::new(); + // $(...)* is a repetition operator. It will repeat the code inside the block for each parameter. + $( + params.push(wasmlanche_sdk::program::serialize_params(&$param).unwrap()); + )* + + params + } + }; +} + +pub fn serialize_params(param: &T) -> Result, std::io::Error> where T: BorshSerialize { + let bytes = prepend_length(&borsh::to_vec(param)?); + Ok(bytes) } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 0c529c7904..77f7b7f688 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -92,7 +92,7 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { /// Returns a vector of bytes with the length of the argument prepended. #[must_use] pub fn prepend_length(bytes: &[u8]) -> Vec { - let mut len_bytes = bytes.len().to_be_bytes().to_vec(); + let mut len_bytes = (bytes.len() as u32).to_be_bytes().to_vec(); len_bytes.extend(bytes); len_bytes } diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index 45fe21df44..d472581c54 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -30,55 +30,55 @@ impl IntoIterator for Address { } } -/// A trait that represents an argument that can be passed to & from the host. -pub trait Argument { - fn as_bytes(&self) -> Cow<'_, [u8]>; - fn is_primitive(&self) -> bool { - false - } - fn len(&self) -> usize { - self.as_bytes().len() - } - fn is_empty(&self) -> bool { - self.len() == 0 - } -} +// /// A trait that represents an argument that can be passed to & from the host. +// pub trait Argument { +// fn as_bytes(&self) -> Cow<'_, [u8]>; +// fn is_primitive(&self) -> bool { +// false +// } +// fn len(&self) -> usize { +// self.as_bytes().len() +// } +// fn is_empty(&self) -> bool { +// self.len() == 0 +// } +// } -impl Argument for Address { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Borrowed(self.as_bytes()) - } -} +// impl Argument for Address { +// fn as_bytes(&self) -> Cow<'_, [u8]> { +// Cow::Borrowed(self.as_bytes()) +// } +// } -impl Argument for i64 { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } -} +// impl Argument for i64 { +// fn as_bytes(&self) -> Cow<'_, [u8]> { +// Cow::Owned(self.to_be_bytes().to_vec()) +// } +// fn is_primitive(&self) -> bool { +// true +// } +// } -impl Argument for i32 { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } -} +// impl Argument for i32 { +// fn as_bytes(&self) -> Cow<'_, [u8]> { +// Cow::Owned(self.to_be_bytes().to_vec()) +// } +// fn is_primitive(&self) -> bool { +// true +// } +// } -impl Argument for Program { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Owned(self.id().to_be_bytes().to_vec()) - } - fn is_primitive(&self) -> bool { - true - } -} +// impl Argument for Program { +// fn as_bytes(&self) -> Cow<'_, [u8]> { +// Cow::Owned(self.id().to_be_bytes().to_vec()) +// } +// fn is_primitive(&self) -> bool { +// true +// } +// } -impl Argument for String { - fn as_bytes(&self) -> Cow<'_, [u8]> { - Cow::Borrowed(self.as_bytes()) - } -} +// impl Argument for String { +// fn as_bytes(&self) -> Cow<'_, [u8]> { +// Cow::Borrowed(self.as_bytes()) +// } +// } From 1ee07b13126dd9ef9b14a5bcdd96eb810104d245 Mon Sep 17 00:00:00 2001 From: samliok Date: Sun, 3 Dec 2023 00:31:57 -0800 Subject: [PATCH 47/74] why are we not putting units in second runtime? --- x/programs/examples/counter_test.go | 15 +++++++++------ x/programs/examples/imports/pstate/pstate.go | 4 ++++ 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 334e7374f9..e36ee31519 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -26,7 +26,7 @@ var counterProgramBytes []byte func TestCounterProgram(t *testing.T) { require := require.New(t) db := newTestDB() - maxUnits := uint64(4000000) + maxUnits := uint64(400000000) cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() require.NoError(err) @@ -71,13 +71,15 @@ func TestCounterProgram(t *testing.T) { // validate counter at 0 result, err = rt.Call(ctx, "get_value", programIDPtr, alicePtr) + // print meter + fmt.Println(rt.Meter().GetBalance()) require.NoError(err) require.Equal(int64(0), result[0]) // initialize second runtime to create second counter program with an empty // meter. rt2 := runtime.New(log, cfg, supported.Imports()) - err = rt2.Initialize(ctx, counterProgramBytes, runtime.NoUnits) + err = rt2.Initialize(ctx, counterProgramBytes, maxUnits) require.NoError(err) // define max units to transfer to second runtime @@ -109,10 +111,11 @@ func TestCounterProgram(t *testing.T) { result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, 10) require.NoError(err) require.Equal(int64(1), result[0]) - - // result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) - // require.NoError(err) - // require.Equal(int64(10), result[0]) + fmt.Println("trying to get value next") + result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) + fmt.Println("meter", rt2.Meter().GetBalance()) + require.NoError(err) + require.Equal(int64(10), result[0]) // stop the runtime to prevent further execution rt2.Stop() diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 84e228e393..8f4c48c1de 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -100,8 +100,10 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32, value } func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 { + fmt.Println("getFnPrior") client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) + fmt.Println("getFn") programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) if err != nil { i.log.Error("failed to read program id from memory", @@ -128,6 +130,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 } return -1 } + fmt.Println("getFn1") if err != nil { i.log.Error("failed to convert program id to id", @@ -147,6 +150,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 } return -1 } + fmt.Println("getFn2") return ptr } From e1c319af2609fbb3084982f00d9778529587a3cc Mon Sep 17 00:00:00 2001 From: samliok Date: Sun, 3 Dec 2023 00:33:40 -0800 Subject: [PATCH 48/74] comments --- x/programs/examples/counter_test.go | 4 ++-- x/programs/examples/imports/pstate/pstate.go | 4 ---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index e36ee31519..cc66edecba 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -111,9 +111,7 @@ func TestCounterProgram(t *testing.T) { result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, 10) require.NoError(err) require.Equal(int64(1), result[0]) - fmt.Println("trying to get value next") result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) - fmt.Println("meter", rt2.Meter().GetBalance()) require.NoError(err) require.Equal(int64(10), result[0]) @@ -150,6 +148,8 @@ func TestCounterProgram(t *testing.T) { target := programID2Ptr maxUnitsProgramToProgram := int64(10000) + // TODO: this is commented out because call_program does not support passing raw primitives as parameters. + // to be done soon. // increment alice's counter on program 2 // result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgram, alicePtr, 5) // require.NoError(err) diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 8f4c48c1de..84e228e393 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -100,10 +100,8 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32, value } func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 { - fmt.Println("getFnPrior") client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) - fmt.Println("getFn") programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) if err != nil { i.log.Error("failed to read program id from memory", @@ -130,7 +128,6 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 } return -1 } - fmt.Println("getFn1") if err != nil { i.log.Error("failed to convert program id to id", @@ -150,7 +147,6 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 } return -1 } - fmt.Println("getFn2") return ptr } From 6c2cde53466bb36e7350b29c02294dc41291bdcd Mon Sep 17 00:00:00 2001 From: samliok Date: Sun, 3 Dec 2023 00:48:20 -0800 Subject: [PATCH 49/74] counter test cleanup --- x/programs/examples/counter_test.go | 15 +++++---------- x/programs/examples/testdata/token.wasm | Bin 34646 -> 53942 bytes x/programs/examples/token_test.go | 2 +- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index cc66edecba..4debeb79c1 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -6,7 +6,6 @@ package examples import ( "context" _ "embed" - "fmt" "testing" "github.com/stretchr/testify/require" @@ -72,7 +71,6 @@ func TestCounterProgram(t *testing.T) { // validate counter at 0 result, err = rt.Call(ctx, "get_value", programIDPtr, alicePtr) // print meter - fmt.Println(rt.Meter().GetBalance()) require.NoError(err) require.Equal(int64(0), result[0]) @@ -111,6 +109,7 @@ func TestCounterProgram(t *testing.T) { result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, 10) require.NoError(err) require.Equal(int64(1), result[0]) + result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) require.NoError(err) require.Equal(int64(10), result[0]) @@ -139,26 +138,22 @@ func TestCounterProgram(t *testing.T) { ) // write program id 2 to stack of program 1 - fmt.Println("allocation program id 2") programID2Ptr, err = runtime.WriteBytes(rt.Memory(), program2ID[:]) require.NoError(err) - fmt.Println("finsihed allocation program id 2") caller := programIDPtr target := programID2Ptr maxUnitsProgramToProgram := int64(10000) - // TODO: this is commented out because call_program does not support passing raw primitives as parameters. - // to be done soon. // increment alice's counter on program 2 - // result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgram, alicePtr, 5) - // require.NoError(err) - // require.Equal(int64(1), result[0]) + result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgram, alicePtr, 5) + require.NoError(err) + require.Equal(int64(1), result[0]) // expect alice's counter on program 2 to be 15 result, err = rt.Call(ctx, "get_value_external", caller, target, maxUnitsProgramToProgram, alicePtr) require.NoError(err) - require.Equal(int64(10), result[0]) + require.Equal(int64(15), result[0]) require.Greater(rt.Meter().GetBalance(), uint64(0)) } diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index ef436f275befdbd61ce0531779454f9d2e5dd3b7..a7c628898b2d609543905b4bdcf2b434840c79e5 100755 GIT binary patch literal 53942 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 QfY!_KI}<;1*2|au4_$Jqo&W#< diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index 9c69930018..6ee3be75f3 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -34,7 +34,7 @@ var ( func TestTokenProgram(t *testing.T) { require := require.New(t) maxUnits := uint64(1000000) - cfg, err := runtime.NewConfigBuilder().Build() + cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() require.NoError(err) program, err := newTokenProgram(maxUnits, cfg, tokenProgramBytes) require.NoError(err) From 5d29b275918cf9c45f5effbc806298996e44fdfc Mon Sep 17 00:00:00 2001 From: samliok Date: Sun, 3 Dec 2023 01:02:35 -0800 Subject: [PATCH 50/74] comment cleanup --- .../examples/imports/program/program.go | 34 +++--------- x/programs/rust/wasmlanche_sdk/src/program.rs | 23 -------- x/programs/rust/wasmlanche_sdk/src/types.rs | 53 ------------------- 3 files changed, 7 insertions(+), 103 deletions(-) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index d996164c00..be6a92a3dd 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -173,36 +173,17 @@ func (i *Import) callProgramFn( func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, invokeProgramID int64) ([]int64, error) { // first arg contains id of program to call args := []int64{invokeProgramID} - // p := codec.NewReader(buffer, len(buffer)) - // i := 0 - // for !p.Empty() { - // // unpacks uint32 - // size := p.UnpackInt(true) - - // valueBytes := make([]byte, size) - // p.UnpackFixedBytes(int(size), &valueBytes) - // ptr, err := runtime.WriteBytes(memory, valueBytes) - // if err != nil { - // return nil, err - // } - // args = append(args, ptr) - // i++ - // } - // if p.Err() != nil { - // return nil, fmt.Errorf("failed to unpack arguments: %w", p.Err()) - // } + i := 0 for i < len(buffer) { - fmt.Println("i", i) // unpacks uint32 lenBytes := buffer[i:i+consts.Uint32Len] - length := binary.BigEndian.Uint32(lenBytes) - totalLength := int(consts.Uint32Len + length) - - - valueBytes := buffer[i:i + totalLength] - i += consts.Uint32Len + int(length) - + length := binary.BigEndian.Uint32(lenBytes) + consts.Uint32Len + // we include the length in the value bytes because the program + // will need to know how many bytes to read + valueBytes := buffer[i:i + int(length)] + i += int(length) + ptr, err := runtime.WriteBytes(memory, valueBytes) if err != nil { return nil, err @@ -210,7 +191,6 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, invo args = append(args, ptr) } - return args, nil } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 176c0b798d..2f828e059b 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -59,28 +59,6 @@ impl From for Program { } } -// /// Marshals arguments into byte slice which can be unpacked by the host. -// fn marshal_args(args: &[Box]) -> Vec { -// use std::mem::size_of; -// // Size of meta data for each argument -// const META_SIZE: usize = size_of::() + 1; - -// // Calculate the total size of the combined byte slices -// let total_size = args.iter().map(|cow| cow.len() + META_SIZE).sum(); - -// // Create a mutable Vec to hold the combined bytes -// let mut bytes = Vec::with_capacity(total_size); - -// for arg in args { -// // if we want to be efficient we dont need to add length of bytes if its an int -// let len = i64::try_from(arg.len()).expect("Error converting to i64"); -// bytes.extend_from_slice(&len.as_bytes()); -// bytes.extend_from_slice(&[u8::from(arg.is_primitive())]); -// bytes.extend_from_slice(&arg.as_bytes()); -// } -// bytes -// } - #[macro_export] macro_rules! serialize_params { ($($param:expr),*) => { @@ -88,7 +66,6 @@ macro_rules! serialize_params { // the macro expands into this block. This will serialize every parameter // into a byte vector and return a vector of byte vectors. let mut params = Vec::new(); - // $(...)* is a repetition operator. It will repeat the code inside the block for each parameter. $( params.push(wasmlanche_sdk::program::serialize_params(&$param).unwrap()); )* diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index d472581c54..e5a9e2c1a2 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -29,56 +29,3 @@ impl IntoIterator for Address { IntoIterator::into_iter(self.0) } } - -// /// A trait that represents an argument that can be passed to & from the host. -// pub trait Argument { -// fn as_bytes(&self) -> Cow<'_, [u8]>; -// fn is_primitive(&self) -> bool { -// false -// } -// fn len(&self) -> usize { -// self.as_bytes().len() -// } -// fn is_empty(&self) -> bool { -// self.len() == 0 -// } -// } - -// impl Argument for Address { -// fn as_bytes(&self) -> Cow<'_, [u8]> { -// Cow::Borrowed(self.as_bytes()) -// } -// } - -// impl Argument for i64 { -// fn as_bytes(&self) -> Cow<'_, [u8]> { -// Cow::Owned(self.to_be_bytes().to_vec()) -// } -// fn is_primitive(&self) -> bool { -// true -// } -// } - -// impl Argument for i32 { -// fn as_bytes(&self) -> Cow<'_, [u8]> { -// Cow::Owned(self.to_be_bytes().to_vec()) -// } -// fn is_primitive(&self) -> bool { -// true -// } -// } - -// impl Argument for Program { -// fn as_bytes(&self) -> Cow<'_, [u8]> { -// Cow::Owned(self.id().to_be_bytes().to_vec()) -// } -// fn is_primitive(&self) -> bool { -// true -// } -// } - -// impl Argument for String { -// fn as_bytes(&self) -> Cow<'_, [u8]> { -// Cow::Borrowed(self.as_bytes()) -// } -// } From 7db59e54234b020381a6beda142d25f598cec37c Mon Sep 17 00:00:00 2001 From: samliok Date: Sun, 3 Dec 2023 02:00:52 -0800 Subject: [PATCH 51/74] nits --- x/programs/rust/examples/counter/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/program.rs | 19 +++++++++---------- x/programs/rust/wasmlanche_sdk/src/state.rs | 5 ++++- x/programs/rust/wasmlanche_sdk/src/types.rs | 2 -- 4 files changed, 14 insertions(+), 14 deletions(-) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index cecf97ada1..294b847521 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, state_keys, serialize_params, types::Address}; +use wasmlanche_sdk::{program::Program, public, serialize_params, state_keys, types::Address}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 2f828e059b..856e38e8b0 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,7 +1,9 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use borsh::{to_vec}; -use crate::{host::call_program, state::{State, prepend_length}}; +use crate::{ + host::call_program, + state::{prepend_length, State}, +}; /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. @@ -37,13 +39,7 @@ impl Program { ) -> i64 { // flatten the args into a single byte vector let args = args.into_iter().flatten().collect::>(); - call_program( - self, - target, - max_units, - function_name, - &args - ) + call_program(self, target, max_units, function_name, &args) } } @@ -75,7 +71,10 @@ macro_rules! serialize_params { }; } -pub fn serialize_params(param: &T) -> Result, std::io::Error> where T: BorshSerialize { +pub fn serialize_params(param: &T) -> Result, std::io::Error> +where + T: BorshSerialize, +{ let bytes = prepend_length(&borsh::to_vec(param)?); Ok(bytes) } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 77f7b7f688..d282ce8587 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -92,7 +92,10 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { /// Returns a vector of bytes with the length of the argument prepended. #[must_use] pub fn prepend_length(bytes: &[u8]) -> Vec { - let mut len_bytes = (bytes.len() as u32).to_be_bytes().to_vec(); + let mut len_bytes = u32::try_from(bytes.len()) + .expect("pointer out range") + .to_be_bytes() + .to_vec(); len_bytes.extend(bytes); len_bytes } diff --git a/x/programs/rust/wasmlanche_sdk/src/types.rs b/x/programs/rust/wasmlanche_sdk/src/types.rs index e5a9e2c1a2..0c69f8cd51 100644 --- a/x/programs/rust/wasmlanche_sdk/src/types.rs +++ b/x/programs/rust/wasmlanche_sdk/src/types.rs @@ -1,6 +1,4 @@ -use crate::program::Program; use borsh::{BorshDeserialize, BorshSerialize}; -use std::borrow::Cow; /// A struct that enforces a fixed length of 32 bytes which represents an address. From d19f883c42f3f715ea51308e1ea4a13a6fa32546 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 4 Dec 2023 13:49:45 -0800 Subject: [PATCH 52/74] program struct refactor --- x/programs/examples/imports/pstate/pstate.go | 4 +- x/programs/examples/testdata/token.wasm | Bin 53942 -> 54685 bytes x/programs/examples/token.go | 24 ++++-- x/programs/rust/sdk_macros/src/lib.rs | 73 ++---------------- .../rust/wasmlanche_sdk/src/host/program.rs | 8 +- .../rust/wasmlanche_sdk/src/host/state.rs | 8 +- x/programs/rust/wasmlanche_sdk/src/program.rs | 29 +++---- 7 files changed, 47 insertions(+), 99 deletions(-) diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 84e228e393..a487d3b9ab 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -60,7 +60,7 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, _ runtime.Supp return nil } -func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32, valuePtr int32) int32 { +func (i *Import) putFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32, valuePtr int32) int32 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) @@ -99,7 +99,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32, value return 0 } -func (i *Import) getFn(caller *wasmtime.Caller, idPtr int64, keyPtr int32) int64 { +func (i *Import) getFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32) int64 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index a7c628898b2d609543905b4bdcf2b434840c79e5..830789876135725ff7b8974993a0b22fe36e04de 100755 GIT binary patch literal 54685 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 literal 53942 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 for ParamKind { - fn from(ty: &Box) -> Self { - if is_supported_primitive(ty) { - ParamKind::SupportedPrimitive - } else if is_program(ty) { - ParamKind::Program - } else { - ParamKind::Pointer - } - } -} -impl ParamKind { - fn converted_param_tokenstream(&self, param_name: &Ident) -> proc_macro2::TokenStream { - match self { - // return the original parameter if it is a supported primitive type - ParamKind::SupportedPrimitive => { - quote! { - #param_name - } - } - // use the From trait to convert from i64 to a Program struct - ParamKind::Program => { - quote! { - #param_name.into() - } - } - // only convert from_raw_ptr if not a supported primitive type or Program - ParamKind::Pointer => { - quote! { - unsafe { wasmlanche_sdk::state::from_raw_ptr(#param_name).expect("error serializing ptr") } - } - } - } +fn convert_param(param_name: &Ident) -> proc_macro2::TokenStream { + quote! { + unsafe { wasmlanche_sdk::state::from_raw_ptr(#param_name).expect("error serializing ptr") } } } @@ -76,15 +40,12 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if let Pat::Ident(ref pat_ident) = **pat { let param_name = &pat_ident.ident; - let param_descriptor = ty.into(); - let param_type = if is_supported_primitive(ty) { - ty.to_token_stream() - } else { + // let param_descriptor = ty.into(); + let param_type = parse_str::("i64") .expect("valid i64 type") - .to_token_stream() - }; - return (param_name, param_type, param_descriptor); + .to_token_stream(); + return (param_name, param_type, convert_param(param_name)); } // add unused variable if let Pat::Wild(_) = **pat { @@ -94,7 +55,7 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { parse_str::("i64") .expect("valid i64 type") .to_token_stream(), - ParamKind::Program, + convert_param(&empty_param), ); } else { panic!("Unused variables only supported for Program.") @@ -105,13 +66,6 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { }); let (param_names, param_types, converted_params) = full_params - .map(|(param_name, param_type, param_kind)| { - ( - param_name, - param_type, - param_kind.converted_param_tokenstream(param_name), - ) - }) .unzip_n_vec(); // Extract the original function's return type. This must be a WASM supported type. @@ -202,17 +156,6 @@ fn generate_to_vec( .collect() } -/// Returns whether the type_path represents a supported primitive type. -fn is_supported_primitive(type_path: &std::boxed::Box) -> bool { - if let Type::Path(ref type_path) = **type_path { - let ident = &type_path.path.segments[0].ident; - let ident_str = ident.to_string(); - matches!(ident_str.as_str(), "i32" | "i64" | "bool") - } else { - false - } -} - /// Returns whether the type_path represents a Program type. fn is_program(type_path: &std::boxed::Box) -> bool { if let Type::Path(ref type_path) = **type_path { diff --git a/x/programs/rust/wasmlanche_sdk/src/host/program.rs b/x/programs/rust/wasmlanche_sdk/src/host/program.rs index c74156d592..6956751f85 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/program.rs @@ -5,8 +5,8 @@ use crate::program::Program; extern "C" { #[link_name = "call_program"] fn _call_program( - caller_id: i64, - target_id: i64, + caller_id: *const u8, + target_id: *const u8, max_units: i64, function_ptr: *const u8, function_len: usize, @@ -27,8 +27,8 @@ pub(crate) fn call( let function_bytes = function_name.as_bytes(); unsafe { _call_program( - caller.id(), - target.id(), + caller.id().as_ptr(), + target.id().as_ptr(), max_units, function_bytes.as_ptr(), function_bytes.len(), diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index ab8c769580..2999f687e6 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -10,10 +10,10 @@ use borsh::{to_vec, BorshSerialize}; #[link(wasm_import_module = "state")] extern "C" { #[link_name = "put"] - fn _put(caller_id: i64, key_ptr: *const u8, value: *const u8) -> i32; + fn _put(caller_id: *const u8, key_ptr: *const u8, value: *const u8) -> i32; #[link_name = "get"] - fn _get(caller_id: i64, key_ptr: *const u8) -> i64; + fn _get(caller_id: *const u8, key_ptr: *const u8) -> i64; } /// Persists the bytes at `value_ptr` to the bytes at key ptr on the host storage. @@ -30,7 +30,7 @@ where let value_bytes = prepend_length(&value_bytes); let key_bytes = prepend_length(key.as_bytes()); - match unsafe { _put(caller.id(), key_bytes.as_ptr(), value_bytes.as_ptr()) } { + match unsafe { _put(caller.id().as_ptr(), key_bytes.as_ptr(), value_bytes.as_ptr()) } { 0 => Ok(()), _ => Err(StateError::Write), } @@ -43,5 +43,5 @@ where pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key let key = prepend_length(key.as_bytes()); - unsafe { _get(caller.id(), key.as_ptr()) } + unsafe { _get(caller.id().as_ptr(), key.as_ptr()) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 856e38e8b0..ad86071fdf 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -8,22 +8,25 @@ use crate::{ /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. #[derive(Clone, Copy, BorshDeserialize, BorshSerialize)] -pub struct Program { - id: i64, -} +pub struct Program([u8; Self::LEN]); + impl Program { + /// The length of ids.ID + pub const LEN: usize = 32; + /// Returns the id of the program. #[must_use] - pub fn id(self) -> i64 { - self.id + pub fn id(self) -> [u8; Self::LEN] { + self.0 } + /// Returns a State object that can be used to interact with persistent /// storage exposed by the host. #[must_use] - pub fn state(&self) -> State { - State::new(self.id.into()) + pub fn state(self) -> State { + State::new(self) } /// Attempts to call another program `target` from this program `caller`. @@ -43,18 +46,6 @@ impl Program { } } -impl From for i64 { - fn from(program: Program) -> Self { - program.id() - } -} - -impl From for Program { - fn from(value: i64) -> Self { - Self { id: value } - } -} - #[macro_export] macro_rules! serialize_params { ($($param:expr),*) => { From ef3d0ccd59f70c2bef631c631922c45a4baeb167 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 4 Dec 2023 14:10:35 -0800 Subject: [PATCH 53/74] yesss, external function calls working(needs cleanup) --- x/programs/examples/counter_test.go | 24 ++++++++---- .../examples/imports/program/program.go | 35 +++++++++++------- x/programs/examples/testdata/counter.wasm | Bin 59438 -> 60269 bytes 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 4debeb79c1..c44716fc20 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -52,7 +52,7 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, programID, counterProgramBytes) require.NoError(err) - programIDPtr, err := runtime.WriteBytes(rt.Memory(), programID[:]) + programIDPtr, err := newParameterPtr(ctx, programID, rt) require.NoError(err) // generate alice keys @@ -93,7 +93,7 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, program2ID, counterProgramBytes) require.NoError(err) - programID2Ptr, err := runtime.WriteBytes(rt2.Memory(), program2ID[:]) + programID2Ptr, err := newParameterPtr(ctx, program2ID, rt2) require.NoError(err) // write alice's key to stack and get pointer @@ -106,13 +106,16 @@ func TestCounterProgram(t *testing.T) { require.Equal(int64(1), result[0]) // increment alice's counter on program 2 by 10 - result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, 10) + incAmount := int64(10) + incAmountPtr, err := newParameterPtr(ctx, incAmount, rt2) + require.NoError(err) + result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, incAmountPtr) require.NoError(err) require.Equal(int64(1), result[0]) result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) require.NoError(err) - require.Equal(int64(10), result[0]) + require.Equal(incAmount, result[0]) // stop the runtime to prevent further execution rt2.Stop() @@ -126,7 +129,9 @@ func TestCounterProgram(t *testing.T) { } // increment alice's counter on program 1 - result, err = rt.Call(ctx, "inc", programIDPtr, alicePtr, 1) + onePtr, err := newParameterPtr(ctx, int64(1), rt) + require.NoError(err) + result, err = rt.Call(ctx, "inc", programIDPtr, alicePtr, onePtr) require.NoError(err) require.Equal(int64(1), result[0]) @@ -138,20 +143,23 @@ func TestCounterProgram(t *testing.T) { ) // write program id 2 to stack of program 1 - programID2Ptr, err = runtime.WriteBytes(rt.Memory(), program2ID[:]) + programID2Ptr, err = newParameterPtr(ctx, program2ID, rt) require.NoError(err) caller := programIDPtr target := programID2Ptr maxUnitsProgramToProgram := int64(10000) + maxUnitsProgramToProgramPtr, err := newParameterPtr(ctx, maxUnitsProgramToProgram, rt) // increment alice's counter on program 2 - result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgram, alicePtr, 5) + fivePtr, err := newParameterPtr(ctx, int64(5), rt) + require.NoError(err) + result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgramPtr, alicePtr, fivePtr) require.NoError(err) require.Equal(int64(1), result[0]) // expect alice's counter on program 2 to be 15 - result, err = rt.Call(ctx, "get_value_external", caller, target, maxUnitsProgramToProgram, alicePtr) + result, err = rt.Call(ctx, "get_value_external", caller, target, maxUnitsProgramToProgramPtr, alicePtr) require.NoError(err) require.Equal(int64(15), result[0]) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index be6a92a3dd..5878556988 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -61,8 +61,8 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, imports runtim // callProgramFn makes a call to an entry function of a program in the context of another program's ID. func (i *Import) callProgramFn( caller *wasmtime.Caller, - callerIDPtr int64, - programIDPtr int64, + callerIDPtr int32, + programIDPtr int32, maxUnits int64, functionPtr, functionLen, @@ -132,14 +132,14 @@ func (i *Import) callProgramFn( } }() - // write the program id to the new runtime memory - ptr, err := runtime.WriteBytes(rt.Memory(), programIDBytes) - if err != nil { - i.log.Error("failed to write program id to memory", - zap.Error(err), - ) - return -1 - } + // // write the program id to the new runtime memory + // ptr, err := runtime.WriteBytes(rt.Memory(), programIDBytes) + // if err != nil { + // i.log.Error("failed to write program id to memory", + // zap.Error(err), + // ) + // return -1 + // } argsBytes, err := memory.Range(uint64(argsPtr), uint64(argsLen)) if err != nil { @@ -150,7 +150,7 @@ func (i *Import) callProgramFn( } // sync args to new runtime and return arguments to the invoke call - params, err := getCallArgs(ctx, rt.Memory(), argsBytes, ptr) + params, err := getCallArgs(ctx, rt.Memory(), argsBytes, programIDBytes) if err != nil { i.log.Error("failed to unmarshal call arguments", zap.Error(err), @@ -170,9 +170,18 @@ func (i *Import) callProgramFn( return int64(res[0]) } -func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, invokeProgramID int64) ([]int64, error) { +func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]int64, error) { // first arg contains id of program to call - args := []int64{invokeProgramID} + bytes := make([]byte, consts.Uint32Len+len(programIDBytes)) + binary.BigEndian.PutUint32(bytes, uint32(len(programIDBytes))) + copy(bytes[consts.Uint32Len:], programIDBytes) + + invokeProgramIDPtr, err := runtime.WriteBytes(memory, bytes) + if err != nil { + return nil, err + } + + args := []int64{invokeProgramIDPtr} i := 0 for i < len(buffer) { diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index 5f6257982cbb125ed598372b5ef9039d28d4328c..e2e091ec204dcac65834b4d42681e2942b4ef79e 100755 GIT binary patch literal 60269 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 z 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 literal 59438 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 z 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 WKUnz9ulRA0vYD6hu>3os|NIxK`+<=F From da305142c8199e417fe5c2d9b46f72618469cb64 Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 5 Dec 2023 01:02:47 -0800 Subject: [PATCH 54/74] cleanup --- x/programs/rust/examples/counter/src/lib.rs | 6 +++--- x/programs/rust/examples/token/Cargo.toml | 2 -- x/programs/rust/scripts/build.sh | 2 +- x/programs/rust/sdk_macros/Cargo.toml | 3 +-- x/programs/rust/sdk_macros/src/lib.rs | 19 ++++++++----------- .../rust/wasmlanche_sdk/src/host/state.rs | 10 +++++++--- x/programs/rust/wasmlanche_sdk/src/program.rs | 11 +++++++---- 7 files changed, 27 insertions(+), 26 deletions(-) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 294b847521..f3b3d99608 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, serialize_params, state_keys, types::Address}; +use wasmlanche_sdk::{program::Program, public, params, state_keys, types::Address}; #[state_keys] enum StateKeys { @@ -47,7 +47,7 @@ fn inc_external( of: Address, amount: i64, ) -> i64 { - program.call_program(&target, max_units, "inc", serialize_params!(of, amount)) + program.call_program(&target, max_units, "inc", params!(of, amount)) } /// Gets the count at the address. @@ -62,5 +62,5 @@ fn get_value(program: Program, of: Address) -> i64 { /// Gets the count at the address for an external program. #[public] fn get_value_external(program: Program, target: Program, max_units: i64, of: Address) -> i64 { - program.call_program(&target, max_units, "get_value", serialize_params!(of)) + program.call_program(&target, max_units, "get_value", params!(of)) } diff --git a/x/programs/rust/examples/token/Cargo.toml b/x/programs/rust/examples/token/Cargo.toml index 960ba63bbf..09c2542e3c 100644 --- a/x/programs/rust/examples/token/Cargo.toml +++ b/x/programs/rust/examples/token/Cargo.toml @@ -7,8 +7,6 @@ edition = "2021" [dependencies] wasmlanche_sdk = { version = "0.1.0", path = "../../wasmlanche_sdk" } -serde_bytes = "0.11.5" -serde ={ version = "1.0.130", features = ["derive"] } borsh = { version = "1.2.0", features = ["derive"] } [dev-dependencies] diff --git a/x/programs/rust/scripts/build.sh b/x/programs/rust/scripts/build.sh index 3fba45556f..f08fbf55e7 100755 --- a/x/programs/rust/scripts/build.sh +++ b/x/programs/rust/scripts/build.sh @@ -22,7 +22,7 @@ cargo clean cargo build \ --target "${target}" \ --target-dir "${target_dir}" \ - --release + --release > build.txt # Copy the compiled program into the build directory cp ./"${target_dir}"/"${target}"/release/*.wasm "./${target_dir}/" diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index 93fb1a35cb..43c3ba962a 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -9,5 +9,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.67" quote = "1.0.33" -syn = { version = "2.0.37", features = ["full"] } -unzip-n = "0.1.2" \ No newline at end of file +syn = { version = "2.0.37", features = ["full"] } \ No newline at end of file diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 453a68beb6..f82e2f5f19 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -8,9 +8,6 @@ use quote::{quote, ToTokens}; use syn::{ parse_macro_input, parse_str, Fields, FnArg, Ident, ItemEnum, ItemFn, Pat, PatType, Type, }; -use unzip_n::unzip_n; -unzip_n!(3); - fn convert_param(param_name: &Ident) -> proc_macro2::TokenStream { quote! { @@ -41,11 +38,10 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if let Pat::Ident(ref pat_ident) = **pat { let param_name = &pat_ident.ident; // let param_descriptor = ty.into(); - let param_type = - parse_str::("i64") - .expect("valid i64 type") - .to_token_stream(); - return (param_name, param_type, convert_param(param_name)); + let param_type = parse_str::("i64") + .expect("valid i64 type") + .to_token_stream(); + return (param_name, param_type); } // add unused variable if let Pat::Wild(_) = **pat { @@ -55,7 +51,6 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { parse_str::("i64") .expect("valid i64 type") .to_token_stream(), - convert_param(&empty_param), ); } else { panic!("Unused variables only supported for Program.") @@ -65,8 +60,10 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { panic!("Unsupported function parameter format."); }); - let (param_names, param_types, converted_params) = full_params - .unzip_n_vec(); + let (param_names, param_types): (Vec<_>, Vec<_>) = full_params.unzip(); + let converted_params = param_names + .iter() + .map(|param_name| convert_param(param_name)); // Extract the original function's return type. This must be a WASM supported type. let return_type = &input.sig.output; diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 2999f687e6..6047888df6 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -18,8 +18,6 @@ extern "C" { /// Persists the bytes at `value_ptr` to the bytes at key ptr on the host storage. /// -/// # Safety -/// TODO: pub(crate) unsafe fn put_bytes(caller: &Program, key: &Key, value: &V) -> Result<(), StateError> where V: BorshSerialize, @@ -30,7 +28,13 @@ where let value_bytes = prepend_length(&value_bytes); let key_bytes = prepend_length(key.as_bytes()); - match unsafe { _put(caller.id().as_ptr(), key_bytes.as_ptr(), value_bytes.as_ptr()) } { + match unsafe { + _put( + caller.id().as_ptr(), + key_bytes.as_ptr(), + value_bytes.as_ptr(), + ) + } { 0 => Ok(()), _ => Err(StateError::Write), } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index ad86071fdf..a09d6f659f 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -10,7 +10,6 @@ use crate::{ #[derive(Clone, Copy, BorshDeserialize, BorshSerialize)] pub struct Program([u8; Self::LEN]); - impl Program { /// The length of ids.ID pub const LEN: usize = 32; @@ -21,12 +20,16 @@ impl Program { self.0 } + #[must_use] + pub(crate) fn new(id: [u8; Self::LEN]) -> Self { + Self(id) + } /// Returns a State object that can be used to interact with persistent /// storage exposed by the host. #[must_use] - pub fn state(self) -> State { - State::new(self) + pub fn state(&self) -> State { + State::new(Program::new(self.id())) } /// Attempts to call another program `target` from this program `caller`. @@ -47,7 +50,7 @@ impl Program { } #[macro_export] -macro_rules! serialize_params { +macro_rules! params { ($($param:expr),*) => { { // the macro expands into this block. This will serialize every parameter From 2f9a228fef99bdeed6b48a464fb5d94281df77db Mon Sep 17 00:00:00 2001 From: samliok Date: Tue, 5 Dec 2023 01:10:45 -0800 Subject: [PATCH 55/74] cargo fmt --- x/programs/examples/counter_test.go | 13 +++---- .../examples/imports/program/program.go | 32 ++++++------------ x/programs/examples/testdata/counter.wasm | Bin 60269 -> 37718 bytes x/programs/examples/testdata/token.wasm | Bin 54685 -> 36705 bytes x/programs/examples/token.go | 2 +- x/programs/examples/token_test.go | 6 ++-- x/programs/rust/examples/counter/src/lib.rs | 2 +- .../rust/wasmlanche_sdk/src/host/state.rs | 4 --- x/programs/rust/wasmlanche_sdk/src/program.rs | 3 ++ x/programs/rust/wasmlanche_sdk/src/state.rs | 2 ++ 10 files changed, 28 insertions(+), 36 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index c44716fc20..c215d22ce8 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -25,8 +25,8 @@ var counterProgramBytes []byte func TestCounterProgram(t *testing.T) { require := require.New(t) db := newTestDB() - maxUnits := uint64(400000000) - cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() + maxUnits := uint64(80000) + cfg, err := runtime.NewConfigBuilder().Build() require.NoError(err) ctx, cancel := context.WithCancel(context.Background()) @@ -77,11 +77,12 @@ func TestCounterProgram(t *testing.T) { // initialize second runtime to create second counter program with an empty // meter. rt2 := runtime.New(log, cfg, supported.Imports()) - err = rt2.Initialize(ctx, counterProgramBytes, maxUnits) + err = rt2.Initialize(ctx, counterProgramBytes, runtime.NoUnits) + require.NoError(err) // define max units to transfer to second runtime - unitsTransfer := uint64(10000) + unitsTransfer := uint64(15000) // transfer the units from the original runtime to the new runtime before // any calls are made. @@ -116,7 +117,7 @@ func TestCounterProgram(t *testing.T) { result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) require.NoError(err) require.Equal(incAmount, result[0]) - + // print rt2 meter // stop the runtime to prevent further execution rt2.Stop() @@ -150,6 +151,7 @@ func TestCounterProgram(t *testing.T) { target := programID2Ptr maxUnitsProgramToProgram := int64(10000) maxUnitsProgramToProgramPtr, err := newParameterPtr(ctx, maxUnitsProgramToProgram, rt) + require.NoError(err) // increment alice's counter on program 2 fivePtr, err := newParameterPtr(ctx, int64(5), rt) @@ -162,6 +164,5 @@ func TestCounterProgram(t *testing.T) { result, err = rt.Call(ctx, "get_value_external", caller, target, maxUnitsProgramToProgramPtr, alicePtr) require.NoError(err) require.Equal(int64(15), result[0]) - require.Greater(rt.Meter().GetBalance(), uint64(0)) } diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index 5878556988..69e5c358d1 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -16,6 +16,7 @@ import ( "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/state" + "github.com/ava-labs/hypersdk/x/programs/examples/imports" "github.com/ava-labs/hypersdk/x/programs/examples/storage" "github.com/ava-labs/hypersdk/x/programs/runtime" ) @@ -96,7 +97,7 @@ func (i *Import) callProgramFn( zap.Error(err), ) return -1 - } + } // create a new runtime for the program to be invoked with a zero balance. rt := runtime.New(i.log, i.cfg, i.imports) @@ -132,15 +133,6 @@ func (i *Import) callProgramFn( } }() - // // write the program id to the new runtime memory - // ptr, err := runtime.WriteBytes(rt.Memory(), programIDBytes) - // if err != nil { - // i.log.Error("failed to write program id to memory", - // zap.Error(err), - // ) - // return -1 - // } - argsBytes, err := memory.Range(uint64(argsPtr), uint64(argsLen)) if err != nil { i.log.Error("failed to read program args name from memory", @@ -172,10 +164,7 @@ func (i *Import) callProgramFn( func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]int64, error) { // first arg contains id of program to call - bytes := make([]byte, consts.Uint32Len+len(programIDBytes)) - binary.BigEndian.PutUint32(bytes, uint32(len(programIDBytes))) - copy(bytes[consts.Uint32Len:], programIDBytes) - + bytes := imports.PrependLength(programIDBytes) invokeProgramIDPtr, err := runtime.WriteBytes(memory, bytes) if err != nil { return nil, err @@ -183,16 +172,17 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog args := []int64{invokeProgramIDPtr} - i := 0 - for i < len(buffer) { + for i := 0; i < len(buffer); { // unpacks uint32 - lenBytes := buffer[i:i+consts.Uint32Len] + lenBytes := buffer[i : i+consts.Uint32Len] length := binary.BigEndian.Uint32(lenBytes) + consts.Uint32Len - // we include the length in the value bytes because the program - // will need to know how many bytes to read - valueBytes := buffer[i:i + int(length)] + + // we include the length in the value bytes because the program + // still needs to know how many bytes to read + valueBytes := buffer[i : i+int(length)] i += int(length) - + + // every argument is a pointer ptr, err := runtime.WriteBytes(memory, valueBytes) if err != nil { return nil, err diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index e2e091ec204dcac65834b4d42681e2942b4ef79e..78eaffd501a2c5bc4351a96c907d28c6b52afb18 100755 GIT binary patch delta 16782 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 literal 60269 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 z z7eRKh#+94_7qh9QBg}P{*#oQ)q^Cp!oL%dlcAdbqJM=~ErHv`Di-c~K}D zNdm@EZ_cs`c$#~HvFM8kV24>y>WWyORJ*tw%gU=J)o;dKVaUlnLUzbK@`?)VbkQfU z=Gs2jkFjgtxhvqPa7b*1E#D09$ZM)hmX4Q9_FCCwGNRXnaT_UHh+}5J5XVgGH}P_( zi(^%(YS4ekuCJ%b;8yzrX7A*CPsNq#}553>V@J)3*MY%{2 zd9Mf=2u4Oyjt0`4tOu4{=SmId5_=XdkuD}mmUD^R-P@&hQ`ADiC6I#Cnyy0%w*h~H zi%|-8kmC~C^b$LUOBj^dxx`8@urp1Cqp4g1@{Ku4jyc5r3_pi>7tDeD772o65u{zr z0)Wnr!W<<9%F%U$+(4k7=>|fF7>Te!3o;OLV(cQtx{+dCq!@@4U1qZkI8M-! zB6WLGw5Xj(k!+BnpI~&PD7wr^(Oyf8=A_8zc9SBVnMsQ1F*9;KDauuK5fh|pL5fcm zWpyN3#8`2U%}#g1&{5)yD67$)vli%X^bX zCEgOIuT4L8AfLo@U!ioCn zWH0^1Fh};v*rg{BJWx}{g4~?Uml%8Jb7(1w)j{9Z@#KTym zEU}lgnl%{}oHRR~##4w-hV6d>oibb+FhTIN z>6Gqv(P`XGr_vQUozleYbjpjlo`9#(sc3Bm1x_In>4}_3w3H#I;@JvfZa~E|P3TBC zC}fRHFS2!+&{#-?aS*w^c?gJV3r>eIqyue7D6{$|h}1MPhK~YpVzz72+XfvAI&$6| zQq@h+NOr040v6brHwP~j7Ia~}m{>4(lk*wupa7=x;ZAS>Ar)o<8Xo?qLf#1|fhdkA zA7%n=VncJxrDk*xiU>Y8pN6Z?LvBR_j?4r^imYhzAw;~HzImjBMe&7Okr@ z_oU%HSGVIkfsJa$nXK3Mg(=EhtJd#xe4CESq*UYl9o=EETi03np*EY($lJ>}&fpG(y==OmmJq-~UGUQM(JI2#@Xy_f)5uYRPKQ*T#T_V+Yc9T_ z5o@=r0Tah2{_{|pYrs|@0)=|+dSkk0_TIQ!alizdks9Fw^~@qRrp2rvHgbUo@v|znFktE(0|svALpy%hjrkuJ%-2*x@Tf-zp!<0u6%QJ&2pOL1JV{Uyp zoRT)K7$=-&E`E1rdxPqwoj#h55`;ZH&tHDa_-Af_=|j6&lND z1o#c_u(`g|bk!cCR}Jr``Nc5;-sENoq&VtdZ|H1w5Qq)wgqx@^c6PRc$uis!4J=ww zp3voCCZUZS^2U#|taFE#R2eQ7WS(YOt0K1Q$gYl@w7uP=?R2}EY`J}6C2;OUe^zs> zW^?*O--!NPXv5K;O;{TqWJfDb>?NTDXKqKw9XqdEaBdgnvR);WcgogK{!3n^pMiT>!gZ+1XFhlqt? zb9Qtn?Niv%g^)4(0GuG8b0eC{EtoGq8RbZ&4VXAWTe3ZsE66gf& z?K5c-1kZvgiAw6uNtIjqdXY%gn*2qis-rI4F$wJTO0~qhcIwXrvfQGo`Ufh_fkrK>b*O7z#GdY0TnO#u4mr@|Icp zvJ+!72?0?YAxPm5Go`6oO?p#0%ueCyC=(-AxCpa#PmEwn3%ZUW&BTbQeHR4mN&Gb4x;+0jVgjvdWlc{>^{BB9dVp8Bq4Y0u1P zbb%0JZ~}`nqpd)WrF#7yedyJw5a~;vCWpdk6U_cGvp(G}*VH~C8ly!F9>^c#vd(~J zBU%cgA*FwL99ed5#0%=1V(Yd;Z2|O#wQZPmLZDD)G@3f2*Lh5_EMwy%=|>H-UuYY! z(3Y?hEK85EYnkjlhbdm*Vv&&hW&_Gh9bj-|+!~LQl?fPsP6}GeG`2T~m4*3r7Nl6J zS*A!>b9K6GW+e5rOr$tvZ(Yviy1WL7H?yystlJPISjk0IY7Yr1o1E`^AyN8l};SA)!wSdzEDWYb)A$td75v~Gqk7s+XY@wKM_#W-Jhtt)>iXQ zLq`2j*g3p~CFH>(i)MOi=bTQVwE4TrYcVM5Xy|C_>=wCJh#I+q^urFW%lEb9+ifg* z#>TtmyH%cIAqaDa>t+uI%?~=*QlEu_crZC(L;bOw z9J2wcIgikC@_8NQgt2DkTwiSddP@i`XdbQsa4By&!d7{%RZXHvjPtB-D0fw+o%G~$>#$u8 zebUadpn{}%m;!QHgbkO)ebJ6amk0L6E{t#2sJ?L|z!ms~q_jKQ#?v%~@Zxck0)^d* zQu;WQAY>&V*=h0&(90b)E)Hp5(WMe!C0i1LFeX5=V-!~}=@Mpr#Gp!9pK`KDy^qN` z(B`TU6{%!6wm6^~112ktEeWVb{hi~g;Sy%OR!y&RQcXYAc!A&tQQPoJ&LW{o-z7B@ zghPSVyd)?M2UIJJ^q#@D2P|K|K5b?LD~RPt%NS-En0h32?HRJNYV{8 zX~L0ZVT_f9i_hYQnlwMuk%n4XxL9}GL4Tw;yhvwUAKMmPnuxNN=*=;XWVvY&6RD&b zr=#pq@K^-yG2;LYD^rNfaj#o9oqL&;5= zQSn|=Q{*9kF8iI51DQ@?isR`An!+JjI#VNIYR;n~LW{;u7@HkyefQ+~#RR-l9B zr!IiXb1ig`{nP~z0P3g70mOsklrYIe?Np3|9*EBz6lHd0T%>Wf0v@wE?95OgM0zyj z7KDwR6DMtSM`&nig)}WRrGbr2RPQ%*Ht&&9!z#x5={5>Ey=uflzhBybUO`Np^;xPbI~F@G-FXhLq!)+xr|rEHyT(V;i+5eIb7FM-s^z=KcU?NZU;XfJHF8Hr=*!+r+jlJGT7>oxEh%xPTZR-Mcq< zm~zh|e_nnL_ceY;$H&RFcXZqeZQFTix_d&H$n&X5EmaNm|4SB!S$&A3F}m|oQN$$-)b1-LmgL}F3_Tch zms~!v{PJB}f$sFv@1{PQ4>s&#kgj~;6%%J_u+|6ZF-=l~;E#DPT<6!_TXt@{css3Z znMgGb`lt6N^Sf>5*3qldT~|z~?TaA1t$Wv}6PJw&qIBEd6dr(Rd3G5|34)(eKbK%2 zZW=#4=Q&&ULMap5cI`|z?-;#gB2CA)U3%HX=G2X3PfBfFXCS?%|Ym%dfH2?=$!vylU2=*m=d}#&*HH#L0$jc73)?Gu3WKl<;qnnSFc>Na%ko7%C#%ktr}dl zV%5r3t5&UEwPw}Os^L{@SFKw;xO&Cvm8(~+UcGwF>Y>%ctJkhxw`Oq7iZv_OtXi{r z&6+hsYlhdXU9)azaA?KQ%Ar+5tB2MM4Gj$stsPo7JUF~!c;)b_;nl-yhKGiShu03T zTRXUR#oCo?SFK&WcFo$MwZm)Iu3fhd5ZBTCI;vhrv2`Q~Z#fg#s|LnUDT`j)q^wUrObt$ZTRN(TR(qrkxmu(q$QUO_cM!Jo0+e@as+qRCT z>0+njmT0s#Z>GMm(hTZc8(c*zE4fNHuIF0jI>J?Q=c3U|x9v=y{hU<8xL7w!P`Jn& z4W3lZ<{;QX-ahjF23OJH)m$~sc^v{|iqtYFIxyTvevNUSe+C!tof!85HF%7?qUjjm zBm-vTy#o2UYwIZbc-zj2Ef?(=b-drGHjOVt>qGqJ&(eF+#X%V(D@>wNr4m)EwWx;( zRbSE!=S0Vpj-4|%JT5vRI_>7?qya8WpxY>)1ZKNfv9`dak$=#j=ZYJVPmGx~P; zSm}Gw-z7hYev}?gej5E-{Ijs}tTUc_-uXAZ|NS5M%^TkFTfg)1Pru<~-o8166!-6tC!CkSwa5Tsp1v{G{*H$-B#ol10hl>gxJ=zj9!>c6?8D z;EXfZ#TQp=gU6Rz@%&OavNk!Vv^?pl)G8zCvyw(_C|+NhS4kR`3pNd}>RnYiz1nl& zlwUpPwCbtH&pTzo+!Jc&(ZKV2PptHmH&&ljyQ03~xu=%TDD{+IR1QncxHNggMJI2p z_DtUKn)aFXo^tQ8>&rbuOOq2OKlSXbFK%qC^_+F){EgKY_in26O#bs(JtxIyZyJvK zsy*d(m7W7bCsxjg7rZp=U)g)@doH=6KKa0#&%LtoR`rJ`mHU$Ffg9hHY%lf3wMz5t zo6oLIJbUt=d-hg$A9vPo%x%nVysUQOC*OVTw~{$=Z+vBPVY!in{f%TTom*UOpLgKb8YcnEP_>V&waVm|pV@P; z9E5SHR4zxAaQq_BWrk{6|0Dxoh}2&)ab3&2M}0rB^)krH8-%t-tuY zpC1X*3)|OxH@W8d)%i(z&Vi5gO@6qvuy$a6d}1|BmM5!|N*q?ol{q~Z^dD1sNhMAe z^wi>NTpE*UMqwai#Mr^D8f_MCB727bL$DFGD=dDfc(lCnr7g!u0ZF?3t4f zm9Dujo>#u+$@mqO<7)#o5!_h0r#!FxippuFvwD^$&_=wXzBHM~85)xx;nngLFN`N| zuRc5OkDpyxTRp9G&5=0+)#Y=R#jXBU|KyFyHSapHe%$r%EG;jc0i_MpCO_AnXiWb3 zyhdsANNMuBjsN?7@o??HtLIMMU!DANsb}DfxTn0fdRDbjo~WN3zcP76ZSvZI1wF^t z&P^uYT>kLwjT4d;w-*+qWc>pNr?m{k=z(;a-+sxOL0K z7R30&z0H8IYj6R-y5`TX=3e?^aK*}1tJe$-uU)t0qKmhVUNWQJQMn6J2(P~4H&sVp z(`=uMxR?ES-maaaFWzl6Jo@$9 zUL1V8^=rXn-+ReNzrW>WKYYCPiidx2+bh!GN3S>>?tf*lJE#Q9FouYwh2h5f;Bn1x z6k3U*FnLCJ^88oT*Vk&{KoZtaYo*iTXID=h2-9H-Bvojl(i5E&^7XzjN~&b(iROh- zv=053M9^S(aukPkJ(tK3&W(;oJCd8at6?SXiB1mBplpMZi>aPk;}XfxeVcu5kL0V+B% zO5!G828p6_*dK!X_@wA$en$Ancr}dbwGhq-uZY^=zBq|$VLARwkN~t5)fiRFJyAHg za78l6b17V0YY@gJL%f!k6pYtbqv)2HNy>^EjH3rfg78mTLHw3*a~hPlML`mBTG#~< zG8EWPj7s6VqIt*khNo0dte+ka(zhsjR`@GmK4K|tHC!I9qSh!X(eG2EYWO3eE&PA_ zy4KK2t~!2Z?w#Z|uHCe{S#_6XkcHjFCUJGqZP-nls-5#P`K9Qqgbt=hsHF4sR|z31d5taGGx8GR00 z*K6k;t1*qk)+=|xF<4vpPj42uU|UaHwZ9Qi zC(-LYrbj2RoP24n;-zgDiLmExQ}?%BgGeB5l#%kjM=9Ie=CNb~} z>B_^F2i!;o&tVPk#e6@5EA#({5KuGkS=(IS*qWW0yScG8GdEwXW=+OvJ2}1@WcDy$ z`D)O%$g@{tPJ15-mk<*uXM9g$9?${6$yCK@x2q#;)g;iU{dm$eHA%)c+B3Hx&WJQx0G*Vs@;Ve3lDc5XkgKpy)IkCU*?%-DvK}e>UtGt48Vp~{Yav$H!eGSfu7C=eC3Z@i z)BsV2DJRuu>ikvE{UGMftb?NrgNIgikNu96E8eBHn8&Fpuif+d@scy2{Y&SO@zW5ArxRWO&+CzeZP$KI>v|bUVv(2z;!A2xsq~(hf|$+ z^M}5afecu@q4g3xriA~{Y2?ew#H6{*xkv*uj+^oTcwdaR%bw~l zg=#;}C&dQT%9&^{rOqsYO&mh2y+u0DDD8s%C4@e&cQO6d-DP7aHWjRd+|v;cJgPcz z4Kj1wE(~n3j*ap8%Uef{uFat?bqY|Ck*cl80NQDU1BSD2%W%n}?hNYDr|yE6ZCc6% z3@yBU)Z>y}{(^ARPSTG-v`54Z^h4iA9j1=b4%0u8=wtXyeW&f`d-_%C9>*%Ke9wBU zPunyGVj1hQU$*5vi9V9=NUYEIY{O@c$updyF2~?K&pCMiOX%E7pg)5C2^x9}>@Da5 z=qjiQS_XXp)B;7IkApr7`ZDNQ(Dy+<1N|EGC(s>`0KXfcdq8JF7eLdXhd_^jTA(iI zW1!E0z6yFC^drpShq(R}v~+e<{0i6Wm?!NVX&O|0egMzM57ppk|2xlH#d%4D%GI$S#B(m$vpgEC+%K84pS)nh+cPRib+h0?x> zM|ds=ccVU?{Xe)7PFeuBMccByC9&^#C0?0FAB>7G(YZxn*%H0X6Daj z2wT?Tfh%lS6e1=|l~)+!VjFO{Dffl3L*v(p4%(@l>>ub2dqujnI zodM!Mcn@p=_=K%5Sw|}n5U4&{+4vqoZ$lirk^~644(uvGb{GChWbVT4!e5BR$<=&6 zi!I2f&A2N+&OQ1j-`{eF77@`^Hf%#4CfOnb%cR%1-XZEd-Tb!_7T|&_)_E@ zR0Ie+&+U!++=?KkI>kvu59t^fdqi!J8u$_kqF6|ki8)OBkZ1UGXn28X1_EC@A3Y805H_YQ$eik~S zc3#F=m4&6s7g;Ve7>00<+FUUR)lw6nWn$ejv6(PI6-;IpRf%OJ;$cg7afE3;J%YjK z@Y#f&u#M=!Xitn!sNl>DvQl+U=03Go#7ox8^&bO;|AO;Zd#wI<@s%1dD(5@aC#==l zWc{4D?K~^)t(~jAVEwk%5YIcp3hY-c>0Gftk5j1e+EV>@&e!dK)z3N&=X>@|=ahXY z*6eGwS8Kl)FV;R<|AqKwt?!(-mDQ=ez5cCwQ~cZdw)kXiTl@jg*OT=R*54r>v+lRP iBwld7X3g0P);}D4f%wmVf=_)hYx*v{HvV4dKmP?8i=D3k diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 830789876135725ff7b8974993a0b22fe36e04de..96182f9b7a2ef78e0acd66a7675b35182ebe28bd 100755 GIT binary patch delta 15962 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 diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index 912dbd8c5b..cb5a5c9e93 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -124,7 +124,7 @@ func (t *Token) Run(ctx context.Context) error { ) // mint 100 tokens to alice - mintAlice := int64(100) + mintAlice := int64(1000) mintAlicePtr, err := newParameterPtr(ctx, mintAlice, rt) if err != nil { return err diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index 6ee3be75f3..d0c01d2194 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -24,7 +24,7 @@ var ( log = logging.NewLogger( "", logging.NewWrappedCore( - logging.Debug, + logging.Info, os.Stderr, logging.Plain.ConsoleEncoder(), )) @@ -33,8 +33,8 @@ var ( // go test -v -timeout 30s -run ^TestTokenProgram$ github.com/ava-labs/hypersdk/x/programs/examples -memprofile benchvset.mem -cpuprofile benchvset.cpu func TestTokenProgram(t *testing.T) { require := require.New(t) - maxUnits := uint64(1000000) - cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() + maxUnits := uint64(80000) + cfg, err := runtime.NewConfigBuilder().Build() require.NoError(err) program, err := newTokenProgram(maxUnits, cfg, tokenProgramBytes) require.NoError(err) diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index f3b3d99608..2caa0dc21e 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -1,4 +1,4 @@ -use wasmlanche_sdk::{program::Program, public, params, state_keys, types::Address}; +use wasmlanche_sdk::{params, program::Program, public, state_keys, types::Address}; #[state_keys] enum StateKeys { diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 6047888df6..9f30ac78b5 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -17,7 +17,6 @@ extern "C" { } /// Persists the bytes at `value_ptr` to the bytes at key ptr on the host storage. -/// pub(crate) unsafe fn put_bytes(caller: &Program, key: &Key, value: &V) -> Result<(), StateError> where V: BorshSerialize, @@ -41,9 +40,6 @@ where } /// Gets the bytes associated with the key from the host. -/// -/// # Safety -/// TODO: pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key let key = prepend_length(key.as_bytes()); diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index a09d6f659f..0466900f32 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -65,6 +65,9 @@ macro_rules! params { }; } +/// Serializes the parameter into a byte vector. +/// # Errors +/// Will return an error if the parameter cannot be serialized. pub fn serialize_params(param: &T) -> Result, std::io::Error> where T: BorshSerialize, diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index d282ce8587..9582c7a836 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -90,6 +90,8 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { } /// Returns a vector of bytes with the length of the argument prepended. +/// # Panics +/// Panics if the length of the argument cannot be converted to u32. #[must_use] pub fn prepend_length(bytes: &[u8]) -> Vec { let mut len_bytes = u32::try_from(bytes.len()) From c879e1c8e9608a150d39a469c715db49e82fb106 Mon Sep 17 00:00:00 2001 From: Sam Batschelet Date: Tue, 5 Dec 2023 08:58:23 -0500 Subject: [PATCH 56/74] Fix token benchmark Signed-off-by: Sam Batschelet --- x/programs/examples/token.go | 2 +- x/programs/examples/token_test.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index cb5a5c9e93..f3a82908ec 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -270,7 +270,7 @@ func (t *Token) RunShort(ctx context.Context) error { return err } - programIDPtr, err := runtime.WriteBytes(rt.Memory(), programID[:]) + programIDPtr, err := newParameterPtr(ctx, programID, rt) if err != nil { return err } diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index d0c01d2194..3a4cd8a678 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -45,7 +45,7 @@ func TestTokenProgram(t *testing.T) { // go test -v -benchmem -run=^$ -bench ^BenchmarkTokenProgram$ github.com/ava-labs/hypersdk/x/programs/examples -memprofile benchvset.mem -cpuprofile benchvset.cpu func BenchmarkTokenProgram(b *testing.B) { require := require.New(b) - maxUnits := uint64(40000) + maxUnits := uint64(80000) cfg, err := runtime.NewConfigBuilder(). WithCompileStrategy(runtime.CompileWasm). From bc6741e2146ed090f05db2dd17de221e3776f742 Mon Sep 17 00:00:00 2001 From: samliok Date: Wed, 6 Dec 2023 01:33:17 -0800 Subject: [PATCH 57/74] nits + Deref on Key struct --- x/programs/examples/counter_test.go | 2 -- x/programs/examples/{util.go => utils.go} | 0 x/programs/runtime/{util.go => utils.go} | 0 x/programs/rust/examples/counter/src/lib.rs | 4 ++-- x/programs/rust/scripts/build.sh | 2 +- x/programs/rust/sdk_macros/Cargo.toml | 2 +- x/programs/rust/sdk_macros/src/lib.rs | 21 ++++------------- .../rust/wasmlanche_sdk/src/host/state.rs | 4 ++-- x/programs/rust/wasmlanche_sdk/src/program.rs | 12 ++-------- x/programs/rust/wasmlanche_sdk/src/state.rs | 23 ++++++++----------- 10 files changed, 21 insertions(+), 49 deletions(-) rename x/programs/examples/{util.go => utils.go} (100%) rename x/programs/runtime/{util.go => utils.go} (100%) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index c215d22ce8..51bb918142 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -70,7 +70,6 @@ func TestCounterProgram(t *testing.T) { // validate counter at 0 result, err = rt.Call(ctx, "get_value", programIDPtr, alicePtr) - // print meter require.NoError(err) require.Equal(int64(0), result[0]) @@ -117,7 +116,6 @@ func TestCounterProgram(t *testing.T) { result, err = rt2.Call(ctx, "get_value", programID2Ptr, alicePtr2) require.NoError(err) require.Equal(incAmount, result[0]) - // print rt2 meter // stop the runtime to prevent further execution rt2.Stop() diff --git a/x/programs/examples/util.go b/x/programs/examples/utils.go similarity index 100% rename from x/programs/examples/util.go rename to x/programs/examples/utils.go diff --git a/x/programs/runtime/util.go b/x/programs/runtime/utils.go similarity index 100% rename from x/programs/runtime/util.go rename to x/programs/runtime/utils.go diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 2caa0dc21e..7f2be758a4 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -47,7 +47,7 @@ fn inc_external( of: Address, amount: i64, ) -> i64 { - program.call_program(&target, max_units, "inc", params!(of, amount)) + program.call_program(&target, max_units, "inc", params!(&of, &amount)) } /// Gets the count at the address. @@ -62,5 +62,5 @@ fn get_value(program: Program, of: Address) -> i64 { /// Gets the count at the address for an external program. #[public] fn get_value_external(program: Program, target: Program, max_units: i64, of: Address) -> i64 { - program.call_program(&target, max_units, "get_value", params!(of)) + program.call_program(&target, max_units, "get_value", params!(&of)) } diff --git a/x/programs/rust/scripts/build.sh b/x/programs/rust/scripts/build.sh index f08fbf55e7..3fba45556f 100755 --- a/x/programs/rust/scripts/build.sh +++ b/x/programs/rust/scripts/build.sh @@ -22,7 +22,7 @@ cargo clean cargo build \ --target "${target}" \ --target-dir "${target_dir}" \ - --release > build.txt + --release # Copy the compiled program into the build directory cp ./"${target_dir}"/"${target}"/release/*.wasm "./${target_dir}/" diff --git a/x/programs/rust/sdk_macros/Cargo.toml b/x/programs/rust/sdk_macros/Cargo.toml index 43c3ba962a..a16ddcf5a4 100644 --- a/x/programs/rust/sdk_macros/Cargo.toml +++ b/x/programs/rust/sdk_macros/Cargo.toml @@ -9,4 +9,4 @@ proc-macro = true [dependencies] proc-macro2 = "1.0.67" quote = "1.0.33" -syn = { version = "2.0.37", features = ["full"] } \ No newline at end of file +syn = { version = "2.0.37", features = ["full"] } diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index f82e2f5f19..5324861d8d 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -4,10 +4,8 @@ use core::panic; use proc_macro::TokenStream; use proc_macro2::Span; -use quote::{quote, ToTokens}; -use syn::{ - parse_macro_input, parse_str, Fields, FnArg, Ident, ItemEnum, ItemFn, Pat, PatType, Type, -}; +use quote::quote; +use syn::{parse_macro_input, Fields, FnArg, Ident, ItemEnum, ItemFn, Pat, PatType, Type}; fn convert_param(param_name: &Ident) -> proc_macro2::TokenStream { quote! { @@ -34,24 +32,13 @@ pub fn public(_: TokenStream, item: TokenStream) -> TokenStream { if index == 0 && !is_program(ty) { panic!("First parameter must be Program."); } - if let Pat::Ident(ref pat_ident) = **pat { - let param_name = &pat_ident.ident; - // let param_descriptor = ty.into(); - let param_type = parse_str::("i64") - .expect("valid i64 type") - .to_token_stream(); - return (param_name, param_type); + return (&pat_ident.ident, quote! { i64 }); } // add unused variable if let Pat::Wild(_) = **pat { if is_program(ty) { - return ( - &empty_param, - parse_str::("i64") - .expect("valid i64 type") - .to_token_stream(), - ); + return (&empty_param, quote! { i64 }); } else { panic!("Unused variables only supported for Program.") } diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 9f30ac78b5..45d4572f79 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -25,7 +25,7 @@ where // prepend length to both key & value let value_bytes = prepend_length(&value_bytes); - let key_bytes = prepend_length(key.as_bytes()); + let key_bytes = prepend_length(key); match unsafe { _put( @@ -42,6 +42,6 @@ where /// Gets the bytes associated with the key from the host. pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key - let key = prepend_length(key.as_bytes()); + let key = prepend_length(key); unsafe { _get(caller.id().as_ptr(), key.as_ptr()) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 0466900f32..cfbd808a00 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -49,19 +49,11 @@ impl Program { } } +/// Serialize every parameter into a byte vector and return a vector of byte vectors #[macro_export] macro_rules! params { ($($param:expr),*) => { - { - // the macro expands into this block. This will serialize every parameter - // into a byte vector and return a vector of byte vectors. - let mut params = Vec::new(); - $( - params.push(wasmlanche_sdk::program::serialize_params(&$param).unwrap()); - )* - - params - } + vec![$(wasmlanche_sdk::program::serialize_params($param).unwrap(),)*] }; } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 9582c7a836..b378cbd4b7 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -4,6 +4,7 @@ use crate::{ program::Program, }; use borsh::{from_slice, BorshDeserialize, BorshSerialize}; +use std::ops::Deref; pub struct State { program: Program, @@ -106,24 +107,18 @@ pub fn prepend_length(bytes: &[u8]) -> Vec { #[derive(Debug, Default, Clone)] pub struct Key(Vec); -impl Key { - #[must_use] - pub fn new(bytes: Vec) -> Self { - Self(bytes) - } +impl Deref for Key { + type Target = [u8]; - #[must_use] - pub fn as_bytes(&self) -> &[u8] { + fn deref(&self) -> &Self::Target { &self.0 } +} +impl Key { + /// Returns a new Key from the bytes. #[must_use] - pub fn len(&self) -> usize { - self.0.len() - } - - #[must_use] - pub fn is_empty(&self) -> bool { - self.len() == 0 + pub fn new(bytes: Vec) -> Self { + Self(bytes) } } From b6facbcdee288eb06687992dada0b362b54f261d Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 8 Dec 2023 13:09:07 -0800 Subject: [PATCH 58/74] bitwise operations on ptrs passing to the host --- x/programs/examples/imports/pstate/pstate.go | 28 ++++++++---------- .../examples/imports/{util.go => utils.go} | 17 ++++++----- x/programs/examples/testdata/counter.wasm | Bin 37718 -> 59752 bytes x/programs/examples/testdata/token.wasm | Bin 36705 -> 54363 bytes x/programs/examples/token_test.go | 6 ++-- x/programs/rust/wasmlanche_sdk/src/errors.rs | 3 ++ .../rust/wasmlanche_sdk/src/host/state.rs | 26 +++++++++------- x/programs/rust/wasmlanche_sdk/src/memory.rs | 20 +++++++++++++ x/programs/rust/wasmlanche_sdk/src/program.rs | 16 ++++++++-- x/programs/rust/wasmlanche_sdk/src/state.rs | 13 -------- 10 files changed, 77 insertions(+), 52 deletions(-) rename x/programs/examples/imports/{util.go => utils.go} (68%) diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index a487d3b9ab..6d540d1bb4 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -13,7 +13,6 @@ import ( "go.uber.org/zap" "github.com/ava-labs/avalanchego/database" - "github.com/ava-labs/avalanchego/ids" "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/hypersdk/state" @@ -60,10 +59,10 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, _ runtime.Supp return nil } -func (i *Import) putFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32, valuePtr int32) int32 { +func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64) int32 { client := runtime.NewExportClient(caller) - memory := runtime.NewMemory(client) - programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) + // memory := runtime.NewMemory(client) + programIDBytes, err := imports.GetBytesFromPtr(client, id) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -71,15 +70,16 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32, value return -1 } - keyBytes, err := imports.GetBytesFromPtr(client, int64(keyPtr)) + keyBytes, err := imports.GetBytesFromPtr(client, key) if err != nil { i.log.Error("failed to read key from memory", - zap.Error(err), - ) - return -1 - } + zap.Error(err), + ) + return -1 +} + +valueBytes, err := imports.GetBytesFromPtr(client, value) - valueBytes, err := imports.GetBytesFromPtr(client, int64(valuePtr)) if err != nil { i.log.Error("failed to read value from memory", zap.Error(err), @@ -99,10 +99,10 @@ func (i *Import) putFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32, value return 0 } -func (i *Import) getFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32) int64 { +func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) - programIDBytes, err := memory.Range(uint64(idPtr), uint64(ids.IDLen)) + programIDBytes, err := imports.GetBytesFromPtr(client, id) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -110,14 +110,13 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32) int64 return -1 } - keyBytes, err := imports.GetBytesFromPtr(client, int64(keyPtr)) + keyBytes, err := imports.GetBytesFromPtr(client, key) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), ) return -1 } - k := storage.ProgramPrefixKey(programIDBytes, keyBytes) val, err := i.mu.GetValue(context.Background(), k) if err != nil { @@ -128,7 +127,6 @@ func (i *Import) getFn(caller *wasmtime.Caller, idPtr int32, keyPtr int32) int64 } return -1 } - if err != nil { i.log.Error("failed to convert program id to id", zap.Error(err), diff --git a/x/programs/examples/imports/util.go b/x/programs/examples/imports/utils.go similarity index 68% rename from x/programs/examples/imports/util.go rename to x/programs/examples/imports/utils.go index ac2cdbda37..7e02bf368a 100644 --- a/x/programs/examples/imports/util.go +++ b/x/programs/examples/imports/utils.go @@ -11,18 +11,19 @@ import ( ) // GetBytesFromPtr returns the bytes at [ptr] in [client] memory. -func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptr int64) ([]byte, error) { +func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, error) { memory := runtime.NewMemory(client) - // first 4 bytes represent the length - lenBytes, err := memory.Range(uint64(ptr), consts.Uint32Len) - if err != nil { - return nil, err - } - length := binary.BigEndian.Uint32(lenBytes) + // first 4 bytes represent the length of the bytes to return + length := ptrArg >> 32 + + // grab the ptr which is the right most 4 bytes + mask := ^uint32(0) + ptr := ptrArg & int64(mask) + // The following [length] bytes represent the bytes to return - bytes, err := memory.Range(uint64(ptr+consts.Uint32Len), uint64(length)) + bytes, err := memory.Range(uint64(ptr), uint64(length)) if err != nil { return nil, err } diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index 78eaffd501a2c5bc4351a96c907d28c6b52afb18..c72085f6fda5b4543761cc8b821e03ab0c7d8efa 100755 GIT binary patch literal 59752 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 KG8g@H{{I08n~T!` diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 96182f9b7a2ef78e0acd66a7675b35182ebe28bd..28a2591f4d541c27061aa40fed1d151b96a31974 100755 GIT binary patch literal 54363 zcmeIb3z%JHdH20e`!svc%npPwBmvgmMwn<0lhaHR4rWDxL=aFspOPUN$V`$+GBXLG zDw#k))Tn5+Qbh|&0Z|0|`BvLnOdIdMeAqL($>B&McS&REt>cDzn`_%-ZPni zrR{Zn*VT`(XRYjU zTQ&{tAD-~M@Z@H;!Z>V*?djAn;X!Qbr<3=~4&n^mkpj%0H3h*vGW zҴ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 delta 16452 zcmc(G513Web?@2x+9Tih+)sjdP`(A43D}D9*%4^K4w)Fda;r)JV z?{nu4kTmUk-&go%&faUUz4uycuf5jVYw!8*2mHT&M91EW4R$+DKos%PC<`iq!0-Uy3^;ym=2*b46O2RUp3(QuDtH<0Z;kMm!(qaOxly*nQShjb(801GU?`g zI#Xyaj>xnG>DH0jOQ*HcqwvXS&r5r{Ei<~QDXq0u-sf~i;j49~ZA_ci`E(lXTIbLM z|59nSPK9CGS6*vooFA*GRvYy4u@`;ofc*~go87PSnLAhAdDr@1*Ix6QwQB~J-G29~ z4Fldp)2rL#$;CU@tQ}Z3aF>IYM+~fAv3A3MTD9H*ri@Gw?p(3<*B!946&x?Sb;TVk z*504Xb?J)Tz8k zu;4GV`ZRQ`G(D ze>FX=wwkXuztR3ctyc3w-R<|3n(|@O{;+95xP5=H&1}tA$3Do$e5j+Es!l~2m2WGR zHY;jvW@KtX$8OuXOBYI+Pk+Axr*tYGsz_B!enF$urBhLk71dD5hdw$)or{WqdZFsp-aPFQ#fy$@ z|4e_d9E7jV7J+s9^HPNt)+D2&Gw!> zfbqub-l!0Ksb*eCmquBL)PYsj3yYrl$MjtD(ac4ohtHPJ|9w`aWAg{QJHRpIsQQZ# zcI5XjEGqJb-l115d1zFj?klUv>(XE0jF$t^C-Z)PJyL+DlX4mO3pZQ0yk(JA!9 z>aS0nS^epNmEMeHkgC-~T1_$BuypdDW?eIEKWYYLIjbWD%;0CEAK*r>uZi zEko9}jA7gY3=IR8puM)U@EF0EU=F)}wzn-e^iG7vS)*jJZBfRcc4Lfvq@bL-hC1Qo zS@xk%kylc>moTBLoQ}Go0@2C;0`!s>`@N7L8mV&rRagLM9@eqS3N{+bxw2RE@>npA z@jkniJ*+Ut^{G7Alc2VaNA9B2ljYY{9Tk00Bm-p<%A&YpDHVP6qSz^9=ml@d*2Ab) zqS7ylMWS{Lujm;0cM{P;Np0$nJ|qvY9aO>V$du?XG?zm6Hx86NtHEHY#61FzAQbE+ z!3+HoY@g5d&xN7}g;0giF@CT-xqRNF(0sq?^lyMQy~m$*ZQYvYO0-w|LuIY0aGWir zF$sps%=2?mu9RjueX-|ZVX%N+n6fsC1~;r)vt+hrN|@pC%pCQw`C;bw)dOZr_FlEk zoX(c?gEdpm{UxUUF!#pof2%Y+^=4<-2EDT^+YSXTocr@ra=JS7Qjuy)1p9-z9v$?9|M+$ZreadQKk%r7euSk_r1t05| zm}>xrA!3;#l^}9s{vt#TM4cdFv2;`l;N{G=;>Xn<^S$C<#Gvspda$!R$k3p=H%d7o zQ$>$Vr7%$Y0Djee4tt&(SdU_Eqtw{4asB#=2Z=A(3eE=M%iu_9)L_%;PZj>_YOs@R z$5353D#EP|gvo~>{cfFt3j{n!g!eUn$j=>xI;5PVOR>KWL>-3FT+2D4>Cv!8wcI>C zm!wy84?g}pKMYfG)Ki6Z4(%@tWyuOt-FmLwX<@2M_lQ>n9+VAwCY!)2n(YexBU++; zDGYjs_6caX_6f)=YZ()R93i7ihh-QXs$nMBLh;Z95-^o4r0Y6IkZ5LR2;}c?)XNBB z2~|f)Q5S&?#=G?VU>gUee7Pnbt#T^L#N6D_a_EVjO*9<%xnu*UqN9ltx8$J!|5(yF zY)&eF@*kspplF~$GsOg43x4&@j-c*W<;_n?l0#;i7)W!Ls>0>v|;kXG~&RV?-29 zH1vR;hjuiFcq1E4+!&?$Xxx9l79UveJx=YzGy|AbYbzfx7b~Xw`Je;3}#T~HZ z{>HM}2!S!8@+exg#2Y99Rb}%4+~C&76OOrc${9`xQk{FSF%arB>}j#~))izK{0v1t zpisucuUNt@)Uj0JM4kW7!0~7Z^(JYQOtPqOt<9mgdiaunHpsUhQZ1#0 z8vp{jYDXz1hQ+B< zNl5{8&p;8! zkKx+P@QLc$psldhdI_Z>R%3Dhkk+Ofv{nKmr>rn8)LNPrsFu~*%Ve)xUE~Ub4>{~m zE&7)5Oz0F_wh-bMww|Hf=KJ3qWzR%5Foj5MU@E81hDFh$;&lbVmY~`}L6j&6Prc$a zAPHEH`a)>#Jw%g`xm^$H2juJ2gy*cV3w!aGDo7%Hv-Fa-co@GhxY&50%EtN_8g2k) z8skMz)>2jM#9(7DL=(k}%9$b-A_}0>3yV+ycH2Y8LXx9e?VkQH(@}>}6|z~pQJeaG}&`hbiK)xd!- zg#StvV2c1RV3{C8Iy5Z$;v#)l9X~Dum-vfu){qfUMP?wKoNz2*j)V{=TacYhtlb3E z#vyzkj1Y$e%dD1e2#-~FD1rxrsf-YKVc!VL5L+&~QN(3WfFR46AC#(57lQ;3f~~?5yWCmk)XQmZzJ34jU(RXDIr1ZIHTt?eldm}f}4JOf-OgiHNMEuzr{0VEHhYvQBoT+>y7=LT;@7g~bj3^ULt%nl^(rTM0ed8QUFO=MjsEZjhIZMnTqHU?LudJD9dvHl2u~gr(tt z;_!WFPh#d#R2&cD7DNa(asKE+=O1GofMR_af;#j7vTVdc1_}XflI5{mR)~T!wNU9H zc&L3sDmr4Mz9H^mc@z&boZQNT5u#N?V7d*31WLn>!jv4R?yoqS_$x9|_iA-nl4~0m zzy{fE;v8K)(E{e6wa`vUsmU&7ge7FarA9HmporP-mvfA*dm*31ooKgN=mr`#i=yt4 zTDw{3P9Rgb6PryFzpkxchnuW#7FCLw4YmG6+)6{d0e*7~a7ZDTJ3ZMYV<4e(+6)_b zRrL19#hTdo46=7s3CoZKan&9CR&=~;IJST>+gEJ!qrs`9PqcZXL`xT<_%;fGgGy6VZt8FYiEdR?mT zyQ+LEy0#xsQ0b~4x>osOxn1j4ezDxH>RJVgzB_E|uHnc#_H%wTf5kRG>Y5$4K+(F# zwjOY;4q2dR-Dg{$a;*+oplCg4TMxTdhb&OEJ`>yKLD%fCpK;aaZ0oD8D&UG1C^{dp ztw)C=3ly!d+t#;Tt3wtjT94V*<1+scwt!Lnv2A|Wb#~YSMe7OM`krfb$O1*{N!xnL zwK`;hqV;{-T6102B;e~3nh1r$Bn0JGZs)MGp^=9>)xv%wN z{qjTR`PK{6qvn6NE*k@-5|=wz20er!p)oHr&qf%!WiWz`=fE;<^xLNZ|NG2~N~)dJ~N} zcSFPJ>LrshJNSIB{X*uF>wI$k9G^eU;nL9Mmv!8^I*p~ZiU;GNv#UsdqDXWE%Ofru16TXafPe{Nz|xsmiNXifBthrQC zQ}>w24=$KDZu-|>=~B zDdY4{YNjytJhp#)>PL!JVoCevsUP!y=2gwH&d~g1>c~+;f)Na)19B$S+06^(Ih_}z zfm+U*-l;vKXm;;)=06$izjpQ)t;7<@%xRSgTV+8k?a^_o#L+H+?lt#Mi?WYOwDO4g z{+oRaxZk> zgnReZ-B;jx{ps#c=w}ZYHDjy~CvPUsxDJ=`>u0=zruj2_D7EU$O=_3qn`xarmJ`pIeLsTUCuUD%<&D|bj~F)hZc{mL5}3LEyyZ}zZ=H8b!}e3`CWa^u`)tZ>cFs|bP#0m4Wk8Z+poFq=DK>f&OO|Cu2snF4 zD~z11bfoMZD+Dnl2eN1LgO)u>(I;WIJfIQ%i#CbGdHdVnfo->`UxZDeF7Cj~L~K0h zif1D$>@-B{T7*1|E~NXpO3Lbows}Cyme7DA*s{4-FaNSe#LlaPcJ5~WXQhBemWO<} zj+M*nHc-O7;dj`qvOL<-JiP!L4k}SF^lJ4h6g2(x?J+5->Ee}IYr9Vfl@ zcZEC-it(~n(x9&Q7e0*i&)o2&3KrESa_Rep4s-OIZ84Tu7C=*eqBNX9YRrCvXD>HJe_;=8*MECk=7!eC#4GT4UZ=>0Dc`iA-B#Sh0PY}sP8W3zD&h?e8) zOieythFlkH`{6(Q;ekV^-+B{g(;VvGdgKoeZ+Y_ZeP4}{vdK3A#qC=!4;5ke@qWxJ z$R5PUcHjcvcpz@U{L##4&tr0s+v~_v(CuTkjNM=2l&8M)Pv1HA!IvK#Z)g1O;Mbo0 z>36^P)s`*RbR~{>-XI60=ySD^7(d6fPDQR5T8y-2NfzIMW^8 zLE5nIn3PK5eQ7!I5T)kg=oV0SA*TtxYl2Jf4nN$6MxHs+mOI)GUcp7jM85mXjh9a{ zFJF2|{QiS>e7|vgADBq;xUv6E`x;NK>QBAFoSq7~fUfE8p_;c~=bPSVDP=q##Kkb+ zelIpw6D%(7s}RaSctEL@Qw!dE+K0uvXFqNXPoIu)k9fjcTjpz}=zVfjo#T0zc(_lC zHsjJe+7sUarw&YBIG%yxV_Zf`3r@fIqd7Owq+^lN_T_Du+K+kv#zO|y(Sh;GKJ28O z*v%WKf7uMy)TEA&uVi@G%$LW_i0(ilP;r&N2v2b^K_1#)s~y4BBc3(M*xW7{9;1+& zHoT0&r=77P)Kdq4OzIhFB3em>O=d;!n3(V9e$@_e>8)EhhIJ-TO?d-?IRdPs7xhqK z@wPN973`4AlZC&OluK}N*C!0>UU1$_CY$k00ikD4*o1*w?~@7PP4mn=$hZmp=SO2= zT&o5UZ!?#YW7&se5H0B_H;+hZPkD$i(xqmg$qQtx(MCuJpDIg8l{yi7IFUnwkh!pg z+jZVGbj$3Bqj@wih;uu+brrovc5W88oKDX8Lp7&o73ZPZqjy zd^^0z#UbUd6hmlrDKZNee7W?tGdH@?9B3Mj6JHvnxiSB|;Jk4MDaia-k8uuy9m^}M zqeGE-f;M=lT zICli!hOzogdB+#+5Pl@T{P5k=#Q2>tn{hfX5qD~`FZl%sUvp{b5p74!`8SNusMDmf5)HdZ2KQXq)8)E$|3b!-=Lo5_Rn*XCP*c*rb?$dWE^@jQMXO>mo{Y~=b zLwR0BE+VWDIHZyICtXO~WTO1ks>#qPH<%;whz771DvQoaY`Q$82XOiR&QFzpyKGG0a)$jvy|=>O<16G`rL4II-W9a9v%O~ypmhm6GpqDT0YQ(`JaVgAtVUVc_VV3(mwtIHH)Z-=kXLo44$JMA|*W1;h$nW#O{F+VpV}p zgRz;SFYhydRvUjCo<}7e5#dC?CmmbS5f19%VI6sEi7B{>cm@|eA(+j;#AUf8ZR=C; zuOvCeVM~QMS{vO$BTLvH3oK=JZkd>UQOZTOH$$DI{mp&m$t~l|$t^AMiyD!ebET3W z;@v6mpeLc%$KVW+9B;eqVFvp`@lOG;(K3(?B1IT5L}yH|;VcJhhnN#P1yTu9eTa|m z!Ji7azrYHyXA!`;{2v}#UxAnGi0b5tcsu^!0cD^!L!5k%5N7%!KvQ8eBNEPur*xs- zNESRsm;;haWV$DUk@$WIXtm=|eu3lc*G` z4i@o%FD<-c0}8L)Uzlt-uU`I2v;XO-*K*lP^ag^1J9i{|+@CSP)};GNOh@KNK(3I4 z4&D)kt5^R@s`-DIsyxKBgI@l`RMY!h*TjP7c>#V>_$lINge$Y&a_E8Q-qIJbnP>#H z;-|4b(!tvOz#D~f8-7OPhvhNm%P&kCxn}Lg6?d#z8Ln7=`v&hWpcTwtzuaa9Unoof z&es8eA@Xj*&shBMpTbYO89g{J7({D`+Hrh2llk1>M=)|G6$lYy@MWjjX7AvXn-b_! z*SZ|vCbqio#i8e2*Gl3&ZwFwUb{u{Z*6=F8>%b4m3h{4NIIFpo=xV-7e+U& zz5CAd)^G5d3s- zg8+5{NP;W)Ie2LCkwfX$b;ZEzLUk#A_+4j;uYFv-dgz+h`g{|-In(U?^U i32; + fn _put(caller: i64, key: i64, value: i64) -> i32; #[link_name = "get"] - fn _get(caller_id: *const u8, key_ptr: *const u8) -> i64; + fn _get(caller: i64, key: i64) -> i64; } /// Persists the bytes at `value_ptr` to the bytes at key ptr on the host storage. @@ -22,16 +23,17 @@ where V: BorshSerialize, { let value_bytes = to_vec(value).map_err(|_| StateError::Serialization)?; - // prepend length to both key & value - let value_bytes = prepend_length(&value_bytes); - let key_bytes = prepend_length(key); + let caller_id = caller.id(); + let caller = to_ptr_arg(&caller_id)?; + let value = to_ptr_arg(&value_bytes)?; + let key = to_ptr_arg(key)?; match unsafe { _put( - caller.id().as_ptr(), - key_bytes.as_ptr(), - value_bytes.as_ptr(), + caller, + key, + value, ) } { 0 => Ok(()), @@ -42,6 +44,8 @@ where /// Gets the bytes associated with the key from the host. pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key - let key = prepend_length(key); - unsafe { _get(caller.id().as_ptr(), key.as_ptr()) } + let caller_id = caller.id(); + let caller = to_ptr_arg(&caller_id).unwrap(); + let key = to_ptr_arg(key).unwrap(); + unsafe { _get(caller, key) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index 69d94b4b92..419b7a45fc 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -4,6 +4,8 @@ //! the program. These methods are unsafe as should be used //! with caution. +use crate::errors::StateError; + /// Represents a pointer to a block of memory allocated by the global allocator. #[derive(Clone, Copy)] pub struct Pointer(*mut u8); @@ -68,6 +70,24 @@ impl Memory { } } +// Converts a pointer to a i64 with the first 4 bytes of the pointer +// representing the length of the memory block. +pub fn to_ptr_arg(arg: &[u8]) -> Result { + let mut ptr = u32::try_from(arg.as_ptr() as i64).map_err(|_| StateError::IntegerConversion)? as i64; + let len = u32::try_from(arg.len()).map_err(|_| StateError::IntegerConversion)? as i64; + ptr |= len << 32; + Ok(ptr) +} + +// Converts a i64 to a pointer with the first 4 bytes of the pointer +// representing the length of the memory block. +pub fn from_ptr_arg(arg: i64) -> (i64, usize) { + let len = (arg >> 32) as usize; + let ptr = arg & 0x00000000ffffffff; + (ptr, len) +} + + /// Attempts to allocate a block of memory of size `len` and returns a pointer /// to the start of the block. #[must_use] diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index cfbd808a00..dcf0fdb546 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -2,7 +2,7 @@ use borsh::{BorshDeserialize, BorshSerialize}; use crate::{ host::call_program, - state::{prepend_length, State}, + state::State, }; /// Represents the current Program in the context of the caller. Or an external @@ -16,7 +16,7 @@ impl Program { /// Returns the id of the program. #[must_use] - pub fn id(self) -> [u8; Self::LEN] { + pub fn id(&self) -> [u8; Self::LEN] { self.0 } @@ -67,3 +67,15 @@ where let bytes = prepend_length(&borsh::to_vec(param)?); Ok(bytes) } + +/// Returns a vector of bytes with the length of the argument prepended. +/// # Panics +/// Panics if the length of the argument cannot be converted to u32. +fn prepend_length(bytes: &[u8]) -> Vec { + let mut len_bytes = u32::try_from(bytes.len()) + .expect("pointer out range") + .to_be_bytes() + .to_vec(); + len_bytes.extend(bytes); + len_bytes +} \ No newline at end of file diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index b378cbd4b7..e1b79c178e 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -90,19 +90,6 @@ pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { (value[4..].to_vec(), len) } -/// Returns a vector of bytes with the length of the argument prepended. -/// # Panics -/// Panics if the length of the argument cannot be converted to u32. -#[must_use] -pub fn prepend_length(bytes: &[u8]) -> Vec { - let mut len_bytes = u32::try_from(bytes.len()) - .expect("pointer out range") - .to_be_bytes() - .to_vec(); - len_bytes.extend(bytes); - len_bytes -} - /// Key is a wrapper around a Vec that represents a key in the host storage. #[derive(Debug, Default, Clone)] pub struct Key(Vec); From 5ea23bb0ae2d054e3bfbf5e33fe4f855b6b94bf8 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 8 Dec 2023 13:56:04 -0800 Subject: [PATCH 59/74] bitwise operations working pasing parameters into wasm --- x/programs/rust/sdk_macros/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/memory.rs | 40 +++++++++++++++++++- x/programs/rust/wasmlanche_sdk/src/state.rs | 38 +------------------ 3 files changed, 42 insertions(+), 38 deletions(-) diff --git a/x/programs/rust/sdk_macros/src/lib.rs b/x/programs/rust/sdk_macros/src/lib.rs index 5324861d8d..2eaac653ac 100644 --- a/x/programs/rust/sdk_macros/src/lib.rs +++ b/x/programs/rust/sdk_macros/src/lib.rs @@ -9,7 +9,7 @@ use syn::{parse_macro_input, Fields, FnArg, Ident, ItemEnum, ItemFn, Pat, PatTyp fn convert_param(param_name: &Ident) -> proc_macro2::TokenStream { quote! { - unsafe { wasmlanche_sdk::state::from_raw_ptr(#param_name).expect("error serializing ptr") } + unsafe { wasmlanche_sdk::memory::from_raw_ptr(#param_name).expect("error serializing ptr") } } } diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index 419b7a45fc..519b4c8f11 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -5,6 +5,7 @@ //! with caution. use crate::errors::StateError; +use borsh::{from_slice, BorshDeserialize}; /// Represents a pointer to a block of memory allocated by the global allocator. #[derive(Clone, Copy)] @@ -83,11 +84,48 @@ pub fn to_ptr_arg(arg: &[u8]) -> Result { // representing the length of the memory block. pub fn from_ptr_arg(arg: i64) -> (i64, usize) { let len = (arg >> 32) as usize; - let ptr = arg & 0x00000000ffffffff; + let mask : u32 = !0; + let ptr = arg & (mask as i64); (ptr, len) } + +/// Converts a raw pointer to a deserialized value. +/// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, +/// with the subsequent [length] bytes comprising the serialized data. +/// # Panics +/// Panics if the bytes cannot be deserialized. +/// # Safety +/// This function is unsafe because it dereferences raw pointers. +/// # Errors +/// Returns an `StateError` if the bytes cannot be deserialized. +pub unsafe fn from_raw_ptr(ptr: i64) -> Result +where + V: BorshDeserialize, +{ + let (bytes, _) = bytes_and_length(ptr); + from_slice::(&bytes).map_err(|_| StateError::Deserialization) +} + +/// Returns a tuple of the bytes and length of the argument. +/// PtrArg is encoded using Big Endian as an i64. +/// The first 32 bits representing the length of the bytes and +/// the last 32 representing the ptr. +/// # Panics +/// Panics if the value cannot be converted from i32 to usize. +/// # Safety +/// This function is unsafe because it dereferences raw pointers. +#[must_use] +pub unsafe fn bytes_and_length(ptr_arg: i64) -> (Vec, usize) { + // grab length from ptrArg + let (ptr, len) = from_ptr_arg(ptr_arg); + println!("ptr: {}, len: {}", ptr, len); + let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len) }; + (value.to_vec(), len) +} + + /// Attempts to allocate a block of memory of size `len` and returns a pointer /// to the start of the block. #[must_use] diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index e1b79c178e..50139c64ee 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -2,8 +2,9 @@ use crate::{ errors::StateError, host::{get_bytes, put_bytes}, program::Program, + memory::from_raw_ptr, }; -use borsh::{from_slice, BorshDeserialize, BorshSerialize}; +use borsh::{BorshDeserialize, BorshSerialize}; use std::ops::Deref; pub struct State { @@ -54,41 +55,6 @@ impl State { } } -/// Converts a raw pointer to a deserialized value. -/// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, -/// with the subsequent [length] bytes comprising the serialized data. -/// # Panics -/// Panics if the bytes cannot be deserialized. -/// # Safety -/// This function is unsafe because it dereferences raw pointers. -/// # Errors -/// Returns an `StateError` if the bytes cannot be deserialized. -pub unsafe fn from_raw_ptr(ptr: i64) -> Result -where - V: BorshDeserialize, -{ - let (bytes, _) = bytes_and_length(ptr); - from_slice::(&bytes).map_err(|_| StateError::Deserialization) -} - -// TODO: move this logic to return a Memory struct that conatins ptr + length -/// Returns a tuple of the bytes and length of the argument. -/// # Panics -/// Panics if the value cannot be converted from i32 to usize. -/// # Safety -/// This function is unsafe because it dereferences raw pointers. -#[must_use] -pub unsafe fn bytes_and_length(ptr: i64) -> (Vec, usize) { - type LenType = u32; - - let len = unsafe { std::slice::from_raw_parts(ptr as *const u8, 4) }; - - assert_eq!(len.len(), std::mem::size_of::()); - let len = LenType::from_be_bytes(len.try_into().unwrap()) as usize; - - let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len + 4) }; - (value[4..].to_vec(), len) -} /// Key is a wrapper around a Vec that represents a key in the host storage. #[derive(Debug, Default, Clone)] From c4efc96d43e84556d871326a92a8ca841863bacc Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 8 Dec 2023 14:09:01 -0800 Subject: [PATCH 60/74] full circle -> external function calls(needs cleanup) --- x/programs/examples/counter_test.go | 8 +-- .../examples/imports/program/program.go | 22 ++++---- x/programs/examples/imports/pstate/pstate.go | 4 +- x/programs/examples/imports/utils.go | 31 ++++++++--- x/programs/examples/testdata/counter.wasm | Bin 59752 -> 67266 bytes x/programs/examples/testdata/token.wasm | Bin 54363 -> 67032 bytes x/programs/examples/utils.go | 51 +++++++++++------- 7 files changed, 73 insertions(+), 43 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index 51bb918142..d52c5bf548 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -25,8 +25,8 @@ var counterProgramBytes []byte func TestCounterProgram(t *testing.T) { require := require.New(t) db := newTestDB() - maxUnits := uint64(80000) - cfg, err := runtime.NewConfigBuilder().Build() + maxUnits := uint64(80000000) + cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() require.NoError(err) ctx, cancel := context.WithCancel(context.Background()) @@ -81,7 +81,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // define max units to transfer to second runtime - unitsTransfer := uint64(15000) + unitsTransfer := uint64(150000) // transfer the units from the original runtime to the new runtime before // any calls are made. @@ -147,7 +147,7 @@ func TestCounterProgram(t *testing.T) { caller := programIDPtr target := programID2Ptr - maxUnitsProgramToProgram := int64(10000) + maxUnitsProgramToProgram := int64(100000) maxUnitsProgramToProgramPtr, err := newParameterPtr(ctx, maxUnitsProgramToProgram, rt) require.NoError(err) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index 69e5c358d1..6ea578159e 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -140,7 +140,7 @@ func (i *Import) callProgramFn( ) return -1 } - + fmt.Println("function name ", string(functionBytes)) // sync args to new runtime and return arguments to the invoke call params, err := getCallArgs(ctx, rt.Memory(), argsBytes, programIDBytes) if err != nil { @@ -163,31 +163,31 @@ func (i *Import) callProgramFn( } func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]int64, error) { + fmt.Println("in getCallArgs") // first arg contains id of program to call - bytes := imports.PrependLength(programIDBytes) - invokeProgramIDPtr, err := runtime.WriteBytes(memory, bytes) + invokeProgramIDPtr, err := runtime.WriteBytes(memory, programIDBytes) if err != nil { return nil, err } - - args := []int64{invokeProgramIDPtr} + argPtr := imports.ToPtrArgument(invokeProgramIDPtr, uint32(len(programIDBytes))) + + args := []int64{argPtr} for i := 0; i < len(buffer); { // unpacks uint32 lenBytes := buffer[i : i+consts.Uint32Len] - length := binary.BigEndian.Uint32(lenBytes) + consts.Uint32Len + length := binary.BigEndian.Uint32(lenBytes) - // we include the length in the value bytes because the program - // still needs to know how many bytes to read - valueBytes := buffer[i : i+int(length)] - i += int(length) + valueBytes := buffer[i + consts.Uint32Len : i+ consts.Uint32Len + int(length)] + i += int(length) + consts.Uint32Len // every argument is a pointer ptr, err := runtime.WriteBytes(memory, valueBytes) if err != nil { return nil, err } - args = append(args, ptr) + argPtr := imports.ToPtrArgument(ptr, length) + args = append(args, argPtr) } return args, nil diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 6d540d1bb4..ff5a99c372 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -135,8 +135,8 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { } // prepend the length so that the program can grab the correct number of bytes - val = imports.PrependLength(val) ptr, err := runtime.WriteBytes(memory, val) + argPtr := imports.ToPtrArgument(ptr, uint32(len(val))) if err != nil { { i.log.Error("failed to write to memory", @@ -146,5 +146,5 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { return -1 } - return ptr + return argPtr } diff --git a/x/programs/examples/imports/utils.go b/x/programs/examples/imports/utils.go index 7e02bf368a..97703f9e6d 100644 --- a/x/programs/examples/imports/utils.go +++ b/x/programs/examples/imports/utils.go @@ -4,9 +4,8 @@ package imports import ( - "encoding/binary" + "fmt" - "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/x/programs/runtime" ) @@ -31,10 +30,26 @@ func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, return bytes, nil } -// PrependLength returns the length of [bytes] prepended to [bytes]. -func PrependLength(bytes []byte) []byte { - length := uint32(len(bytes)) - lenBytes := make([]byte, consts.Uint32Len) - binary.BigEndian.PutUint32(lenBytes, length) - return append(lenBytes, bytes...) +// // PrependLength returns the length of [bytes] prepended to [bytes]. +// func PrependLength(bytes []byte) []byte { +// length := uint32(len(bytes)) +// lenBytes := make([]byte, consts.Uint32Len) +// binary.BigEndian.PutUint32(lenBytes, length) +// return append(lenBytes, bytes...) +// } + + +// toPtrArgument converts [ptr] to an int64 with the length of [bytes] in the upper 32 bits +// and [ptr] in the lower 32 bits. +func ToPtrArgument(ptr int64, len uint32) int64 { + + // // ensure length of bytes is not greater than int32 + // if !runtime.EnsureInt64ToInt32(int64(len(bytes))) { + // return 0, fmt.Errorf("length of bytes is greater than int32") + // } + // convert to int64 with length of bytes in the upper 32 bits and ptr in the lower 32 bits + argPtr := int64(len) << 32 + argPtr |= int64((uint32(ptr))) + fmt.Println("ptr and len", ptr, len) + return argPtr } diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index c72085f6fda5b4543761cc8b821e03ab0c7d8efa..cfa4a06ab1b96d3445f433a4439ac77b61715bff 100755 GIT binary patch delta 19017 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≪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 Dce~!r diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index 28a2591f4d541c27061aa40fed1d151b96a31974..67e1cf4342fb8f6b4f6bec2040f67082ad6094c8 100755 GIT binary patch delta 24227 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 RmKZr%#$44=+u)ZV{x?o_6+8d{ delta 12566 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 B1l|Au diff --git a/x/programs/examples/utils.go b/x/programs/examples/utils.go index 6d3f314d42..1a7f64d243 100644 --- a/x/programs/examples/utils.go +++ b/x/programs/examples/utils.go @@ -5,11 +5,10 @@ package examples import ( "context" - "encoding/binary" + "fmt" "os" "github.com/ava-labs/avalanchego/database/memdb" - "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/crypto/ed25519" "github.com/ava-labs/hypersdk/state" "github.com/ava-labs/hypersdk/x/programs/runtime" @@ -41,11 +40,7 @@ func newPtr(ctx context.Context, bytes []byte, rt runtime.Runtime) (int64, error // Designed for serializing parameters passed to a WASM program. func serializeParameter(obj interface{}) ([]byte, error) { bytes, err := borsh.Serialize(obj) - if err != nil { - return nil, err - } - - return marshalArg(bytes), nil + return bytes, err } // newParameterPtr serializes [obj] and allocates memory for it. @@ -54,21 +49,41 @@ func newParameterPtr(ctx context.Context, obj interface{}, rt runtime.Runtime) ( if err != nil { return 0, err } - return newPtr(ctx, bytes, rt) + ptr, err := newPtr(ctx, bytes, rt) + if err != nil { + return 0, err + } + + return toPtrArgument(ptr, uint32(len(bytes))), nil } -// marshalArg prepends the length of [arg] as a uint32 to [arg]. -// This is required by the program inorder to grab the correct number -// of bytes from memory. -func marshalArg(arg []byte) []byte { - // add length prefix to arg as big endian uint32 - argLen := len(arg) - bytes := make([]byte, consts.Uint32Len+argLen) - binary.BigEndian.PutUint32(bytes, uint32(argLen)) - copy(bytes[consts.Uint32Len:], arg) - return bytes +// toPtrArgument converts [ptr] to an int64 with the length of [bytes] in the upper 32 bits +// and [ptr] in the lower 32 bits. +func toPtrArgument(ptr int64, len uint32) int64 { + + // // ensure length of bytes is not greater than int32 + // if !runtime.EnsureInt64ToInt32(int64(len(bytes))) { + // return 0, fmt.Errorf("length of bytes is greater than int32") + // } + // convert to int64 with length of bytes in the upper 32 bits and ptr in the lower 32 bits + argPtr := int64(len) << 32 + argPtr |= int64((uint32(ptr))) + fmt.Println("ptr and len", ptr, len) + return argPtr } +// // marshalArg prepends the length of [arg] as a uint32 to [arg]. +// // This is required by the program inorder to grab the correct number +// // of bytes from memory. +// func marshalArg(arg []byte) []byte { +// // add length prefix to arg as big endian uint32 +// argLen := len(arg) +// bytes := make([]byte, consts.Uint32Len+argLen) +// binary.BigEndian.PutUint32(bytes, uint32(argLen)) +// copy(bytes[consts.Uint32Len:], arg) +// return bytes +// } + func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { priv, err := ed25519.GeneratePrivateKey() if err != nil { From caab4f3d022ebc6682258ebd8ded72b4690bad5d Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 8 Dec 2023 14:36:44 -0800 Subject: [PATCH 61/74] ptr cleanup --- .../examples/imports/program/program.go | 12 ++++--- x/programs/examples/imports/pstate/pstate.go | 18 ++++++---- x/programs/examples/imports/utils.go | 26 +++++---------- x/programs/examples/testdata/counter.wasm | Bin 67266 -> 59488 bytes x/programs/examples/testdata/token.wasm | Bin 67032 -> 54126 bytes x/programs/examples/utils.go | 31 ++---------------- x/programs/runtime/utils.go | 4 +++ x/programs/rust/wasmlanche_sdk/src/memory.rs | 1 - 8 files changed, 34 insertions(+), 58 deletions(-) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index 6ea578159e..01c578859f 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -140,7 +140,6 @@ func (i *Import) callProgramFn( ) return -1 } - fmt.Println("function name ", string(functionBytes)) // sync args to new runtime and return arguments to the invoke call params, err := getCallArgs(ctx, rt.Memory(), argsBytes, programIDBytes) if err != nil { @@ -163,13 +162,15 @@ func (i *Import) callProgramFn( } func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]int64, error) { - fmt.Println("in getCallArgs") // first arg contains id of program to call invokeProgramIDPtr, err := runtime.WriteBytes(memory, programIDBytes) if err != nil { return nil, err } - argPtr := imports.ToPtrArgument(invokeProgramIDPtr, uint32(len(programIDBytes))) + argPtr, err := imports.ToPtrArgument(invokeProgramIDPtr, uint32(len(programIDBytes))) + if err != nil { + return nil, err + } args := []int64{argPtr} @@ -186,7 +187,10 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog if err != nil { return nil, err } - argPtr := imports.ToPtrArgument(ptr, length) + argPtr, err := imports.ToPtrArgument(ptr, length) + if err != nil { + return nil, err + } args = append(args, argPtr) } diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index ff5a99c372..7daab6dfa5 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -62,7 +62,7 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, _ runtime.Supp func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64) int32 { client := runtime.NewExportClient(caller) // memory := runtime.NewMemory(client) - programIDBytes, err := imports.GetBytesFromPtr(client, id) + programIDBytes, err := imports.GetBytesFromArgPtr(client, id) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -70,7 +70,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 return -1 } - keyBytes, err := imports.GetBytesFromPtr(client, key) + keyBytes, err := imports.GetBytesFromArgPtr(client, key) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -78,7 +78,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 return -1 } -valueBytes, err := imports.GetBytesFromPtr(client, value) +valueBytes, err := imports.GetBytesFromArgPtr(client, value) if err != nil { i.log.Error("failed to read value from memory", @@ -102,7 +102,7 @@ valueBytes, err := imports.GetBytesFromPtr(client, value) func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) - programIDBytes, err := imports.GetBytesFromPtr(client, id) + programIDBytes, err := imports.GetBytesFromArgPtr(client, id) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -110,7 +110,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { return -1 } - keyBytes, err := imports.GetBytesFromPtr(client, key) + keyBytes, err := imports.GetBytesFromArgPtr(client, key) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -136,7 +136,6 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { // prepend the length so that the program can grab the correct number of bytes ptr, err := runtime.WriteBytes(memory, val) - argPtr := imports.ToPtrArgument(ptr, uint32(len(val))) if err != nil { { i.log.Error("failed to write to memory", @@ -145,6 +144,13 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { } return -1 } + argPtr, err := imports.ToPtrArgument(ptr, uint32(len(val))) + if err != nil { + i.log.Error("failed to convert ptr to argument", + zap.Error(err), + ) + return -1 + } return argPtr } diff --git a/x/programs/examples/imports/utils.go b/x/programs/examples/imports/utils.go index 97703f9e6d..c86d3309c0 100644 --- a/x/programs/examples/imports/utils.go +++ b/x/programs/examples/imports/utils.go @@ -10,7 +10,7 @@ import ( ) // GetBytesFromPtr returns the bytes at [ptr] in [client] memory. -func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, error) { +func GetBytesFromArgPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, error) { memory := runtime.NewMemory(client) // first 4 bytes represent the length of the bytes to return @@ -30,26 +30,16 @@ func GetBytesFromPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, return bytes, nil } -// // PrependLength returns the length of [bytes] prepended to [bytes]. -// func PrependLength(bytes []byte) []byte { -// length := uint32(len(bytes)) -// lenBytes := make([]byte, consts.Uint32Len) -// binary.BigEndian.PutUint32(lenBytes, length) -// return append(lenBytes, bytes...) -// } - - -// toPtrArgument converts [ptr] to an int64 with the length of [bytes] in the upper 32 bits +// ToPtrArgument converts [ptr] to an int64 with the length of [bytes] in the upper 32 bits // and [ptr] in the lower 32 bits. -func ToPtrArgument(ptr int64, len uint32) int64 { +func ToPtrArgument(ptr int64, len uint32) (int64, error) { + // ensure length of bytes is not greater than int32 to prevent overflow + if !runtime.EnsureUint32ToInt32(len) { + return 0, fmt.Errorf("length of bytes is greater than int32") + } - // // ensure length of bytes is not greater than int32 - // if !runtime.EnsureInt64ToInt32(int64(len(bytes))) { - // return 0, fmt.Errorf("length of bytes is greater than int32") - // } // convert to int64 with length of bytes in the upper 32 bits and ptr in the lower 32 bits argPtr := int64(len) << 32 argPtr |= int64((uint32(ptr))) - fmt.Println("ptr and len", ptr, len) - return argPtr + return argPtr, nil } diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index cfa4a06ab1b96d3445f433a4439ac77b61715bff..a8022dbbce230402a66d1d6ef48cf59578eb44fd 100755 GIT binary patch delta 14321 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 delta 21401 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 math.MinInt32 && v <= math.MaxInt32 } + +func EnsureUint32ToInt32(v uint32) bool { + return v <= math.MaxInt32 +} \ No newline at end of file diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index 519b4c8f11..9c415cbd28 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -120,7 +120,6 @@ where pub unsafe fn bytes_and_length(ptr_arg: i64) -> (Vec, usize) { // grab length from ptrArg let (ptr, len) = from_ptr_arg(ptr_arg); - println!("ptr: {}, len: {}", ptr, len); let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len) }; (value.to_vec(), len) } From 5595b01ec3d4ea31401cafc2c36bf664a9651605 Mon Sep 17 00:00:00 2001 From: samliok Date: Fri, 8 Dec 2023 14:48:16 -0800 Subject: [PATCH 62/74] comments and nit go cleanup --- x/programs/examples/imports/pstate/pstate.go | 1 - x/programs/examples/imports/utils.go | 4 +++- x/programs/rust/wasmlanche_sdk/src/errors.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/host/state.rs | 13 ++----------- x/programs/rust/wasmlanche_sdk/src/memory.rs | 10 ++++------ x/programs/rust/wasmlanche_sdk/src/program.rs | 11 ++++------- x/programs/rust/wasmlanche_sdk/src/state.rs | 3 +-- 7 files changed, 15 insertions(+), 29 deletions(-) diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 7daab6dfa5..3b9c40930a 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -134,7 +134,6 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { return -1 } - // prepend the length so that the program can grab the correct number of bytes ptr, err := runtime.WriteBytes(memory, val) if err != nil { { diff --git a/x/programs/examples/imports/utils.go b/x/programs/examples/imports/utils.go index c86d3309c0..287e403fd4 100644 --- a/x/programs/examples/imports/utils.go +++ b/x/programs/examples/imports/utils.go @@ -9,7 +9,9 @@ import ( "github.com/ava-labs/hypersdk/x/programs/runtime" ) -// GetBytesFromPtr returns the bytes at [ptr] in [client] memory. +// GetBytesFromArgPtr returns the bytes at [ptr] in [client] memory. +// The first 4 bytes of [ptr] must represent the length and the +// following 4 bytes represent the pointer to the bytes. func GetBytesFromArgPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, error) { memory := runtime.NewMemory(client) diff --git a/x/programs/rust/wasmlanche_sdk/src/errors.rs b/x/programs/rust/wasmlanche_sdk/src/errors.rs index 3f5da1a0fe..cfdfae2e76 100644 --- a/x/programs/rust/wasmlanche_sdk/src/errors.rs +++ b/x/programs/rust/wasmlanche_sdk/src/errors.rs @@ -27,5 +27,5 @@ pub enum StateError { Deserialization, #[error("failed to convert integer")] - IntegerConversion + IntegerConversion, } diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 53e663db73..15fae168ad 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -2,10 +2,7 @@ //! storage exposed by the host. use crate::errors::StateError; use crate::memory::to_ptr_arg; -use crate::{ - program::Program, - state::Key, -}; +use crate::{program::Program, state::Key}; use borsh::{to_vec, BorshSerialize}; #[link(wasm_import_module = "state")] @@ -29,13 +26,7 @@ where let value = to_ptr_arg(&value_bytes)?; let key = to_ptr_arg(key)?; - match unsafe { - _put( - caller, - key, - value, - ) - } { + match unsafe { _put(caller, key, value) } { 0 => Ok(()), _ => Err(StateError::Write), } diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index 9c415cbd28..ecde3cc82d 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -74,7 +74,8 @@ impl Memory { // Converts a pointer to a i64 with the first 4 bytes of the pointer // representing the length of the memory block. pub fn to_ptr_arg(arg: &[u8]) -> Result { - let mut ptr = u32::try_from(arg.as_ptr() as i64).map_err(|_| StateError::IntegerConversion)? as i64; + let mut ptr = + u32::try_from(arg.as_ptr() as i64).map_err(|_| StateError::IntegerConversion)? as i64; let len = u32::try_from(arg.len()).map_err(|_| StateError::IntegerConversion)? as i64; ptr |= len << 32; Ok(ptr) @@ -84,13 +85,11 @@ pub fn to_ptr_arg(arg: &[u8]) -> Result { // representing the length of the memory block. pub fn from_ptr_arg(arg: i64) -> (i64, usize) { let len = (arg >> 32) as usize; - let mask : u32 = !0; + let mask: u32 = !0; let ptr = arg & (mask as i64); (ptr, len) } - - /// Converts a raw pointer to a deserialized value. /// Expects the first 4 bytes of the pointer to represent the [length] of the serialized value, /// with the subsequent [length] bytes comprising the serialized data. @@ -110,7 +109,7 @@ where /// Returns a tuple of the bytes and length of the argument. /// PtrArg is encoded using Big Endian as an i64. -/// The first 32 bits representing the length of the bytes and +/// The first 32 bits representing the length of the bytes and /// the last 32 representing the ptr. /// # Panics /// Panics if the value cannot be converted from i32 to usize. @@ -124,7 +123,6 @@ pub unsafe fn bytes_and_length(ptr_arg: i64) -> (Vec, usize) { (value.to_vec(), len) } - /// Attempts to allocate a block of memory of size `len` and returns a pointer /// to the start of the block. #[must_use] diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index dcf0fdb546..4f793c9ddf 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,9 +1,6 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use crate::{ - host::call_program, - state::State, -}; +use crate::{host::call_program, state::State}; /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. @@ -76,6 +73,6 @@ fn prepend_length(bytes: &[u8]) -> Vec { .expect("pointer out range") .to_be_bytes() .to_vec(); - len_bytes.extend(bytes); - len_bytes -} \ No newline at end of file + len_bytes.extend(bytes); + len_bytes +} diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 50139c64ee..5c48d3f8c3 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -1,8 +1,8 @@ use crate::{ errors::StateError, host::{get_bytes, put_bytes}, - program::Program, memory::from_raw_ptr, + program::Program, }; use borsh::{BorshDeserialize, BorshSerialize}; use std::ops::Deref; @@ -55,7 +55,6 @@ impl State { } } - /// Key is a wrapper around a Vec that represents a key in the host storage. #[derive(Debug, Default, Clone)] pub struct Key(Vec); From 245b06cc228b2996a218911b1443bb294d6dcff8 Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 15:46:36 -0800 Subject: [PATCH 63/74] updated call_program host function --- x/programs/examples/counter_test.go | 8 ++--- .../examples/imports/program/program.go | 22 ++++++------- x/programs/examples/testdata/counter.wasm | Bin 59488 -> 37093 bytes x/programs/examples/testdata/token.wasm | Bin 54126 -> 36150 bytes .../rust/wasmlanche_sdk/src/host/program.rs | 30 ++++++++++-------- 5 files changed, 31 insertions(+), 29 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index d52c5bf548..a1ddbde61f 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -25,8 +25,8 @@ var counterProgramBytes []byte func TestCounterProgram(t *testing.T) { require := require.New(t) db := newTestDB() - maxUnits := uint64(80000000) - cfg, err := runtime.NewConfigBuilder().WithDebugMode(true).Build() + maxUnits := uint64(80000) + cfg, err := runtime.NewConfigBuilder().Build() require.NoError(err) ctx, cancel := context.WithCancel(context.Background()) @@ -81,7 +81,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // define max units to transfer to second runtime - unitsTransfer := uint64(150000) + unitsTransfer := uint64(10000) // transfer the units from the original runtime to the new runtime before // any calls are made. @@ -147,7 +147,7 @@ func TestCounterProgram(t *testing.T) { caller := programIDPtr target := programID2Ptr - maxUnitsProgramToProgram := int64(100000) + maxUnitsProgramToProgram := int64(10000) maxUnitsProgramToProgramPtr, err := newParameterPtr(ctx, maxUnitsProgramToProgram, rt) require.NoError(err) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index 01c578859f..afdf8431af 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -62,19 +62,17 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, imports runtim // callProgramFn makes a call to an entry function of a program in the context of another program's ID. func (i *Import) callProgramFn( caller *wasmtime.Caller, - callerIDPtr int32, - programIDPtr int32, + callerID int64, + programID int64, maxUnits int64, - functionPtr, - functionLen, - argsPtr, - argsLen int32, + function int64, + args int64, ) int64 { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - memory := runtime.NewMemory(runtime.NewExportClient(caller)) + client := runtime.NewExportClient(caller) // get the entry function for invoke to call. - functionBytes, err := memory.Range(uint64(functionPtr), uint64(functionLen)) + functionBytes, err := imports.GetBytesFromArgPtr(client, function) if err != nil { i.log.Error("failed to read function name from memory", zap.Error(err), @@ -82,7 +80,7 @@ func (i *Import) callProgramFn( return -1 } - programIDBytes, err := memory.Range(uint64(programIDPtr), uint64(ids.IDLen)) + programIDBytes, err := imports.GetBytesFromArgPtr(client, programID) if err != nil { i.log.Error("failed to read id from memory", zap.Error(err), @@ -133,7 +131,7 @@ func (i *Import) callProgramFn( } }() - argsBytes, err := memory.Range(uint64(argsPtr), uint64(argsLen)) + argsBytes, err := imports.GetBytesFromArgPtr(client, args) if err != nil { i.log.Error("failed to read program args name from memory", zap.Error(err), @@ -149,8 +147,8 @@ func (i *Import) callProgramFn( return -1 } - function := string(functionBytes) - res, err := rt.Call(ctx, function, params...) + function_name := string(functionBytes) + res, err := rt.Call(ctx, function_name, params...) if err != nil { i.log.Error("failed to call entry function", zap.Error(err), diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index a8022dbbce230402a66d1d6ef48cf59578eb44fd..e0bcfd688c1c62727fcf7f9c3d44b22280d028b1 100755 GIT binary patch delta 16576 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 KX8W1HTl8;fxdUzh literal 59488 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

n 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 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index b9e55375a5a136d0dd28b0a15d0011313a6c7af3..42b2c90abf37f069ef15e66206f991a34eb55f19 100755 GIT binary patch delta 15363 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 Kqs-ecE&gx9t*PVy literal 54126 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 i64; } @@ -24,16 +23,21 @@ pub(crate) fn call( function_name: &str, args: &[u8], ) -> i64 { - let function_bytes = function_name.as_bytes(); + + let caller_id = caller.id(); + let caller = to_ptr_arg(&caller_id).unwrap(); + let target_id = target.id(); + let target = to_ptr_arg(&target_id).unwrap(); + let function = to_ptr_arg(function_name.as_bytes()).unwrap(); + let args = to_ptr_arg(args).unwrap(); + unsafe { _call_program( - caller.id().as_ptr(), - target.id().as_ptr(), + caller, + target, max_units, - function_bytes.as_ptr(), - function_bytes.len(), - args.as_ptr(), - args.len(), + function, + args, ) } } From 764077d01b332c19a1493d1a8321a2144232eabb Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 16:45:15 -0800 Subject: [PATCH 64/74] SmartPtr type & cleanup utils --- x/programs/examples/counter_test.go | 18 ++-- .../examples/imports/program/program.go | 16 +-- x/programs/examples/imports/pstate/pstate.go | 15 ++- x/programs/examples/imports/utils.go | 47 --------- x/programs/examples/testdata/counter.wasm | Bin 37093 -> 59507 bytes x/programs/examples/testdata/token.wasm | Bin 36150 -> 54126 bytes x/programs/examples/token.go | 16 +-- x/programs/examples/utils.go | 45 --------- x/programs/runtime/dependencies.go | 2 +- x/programs/runtime/runtime.go | 8 +- x/programs/runtime/utils.go | 93 +++++++++++++++++- 11 files changed, 129 insertions(+), 131 deletions(-) delete mode 100644 x/programs/examples/imports/utils.go diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index a1ddbde61f..e2ebf91e15 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -52,7 +52,7 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, programID, counterProgramBytes) require.NoError(err) - programIDPtr, err := newParameterPtr(ctx, programID, rt) + programIDPtr, err := runtime.NewSmartPtr(ctx, programID, rt) require.NoError(err) // generate alice keys @@ -60,7 +60,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr, err := newParameterPtr(ctx, aliceKey, rt) + alicePtr, err := runtime.NewSmartPtr(ctx, aliceKey, rt) require.NoError(err) // create counter for alice on program 1 @@ -93,11 +93,11 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, program2ID, counterProgramBytes) require.NoError(err) - programID2Ptr, err := newParameterPtr(ctx, program2ID, rt2) + programID2Ptr, err := runtime.NewSmartPtr(ctx, program2ID, rt2) require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := newParameterPtr(ctx, aliceKey, rt2) + alicePtr2, err := runtime.NewSmartPtr(ctx, aliceKey, rt2) require.NoError(err) // initialize counter for alice on runtime 2 @@ -107,7 +107,7 @@ func TestCounterProgram(t *testing.T) { // increment alice's counter on program 2 by 10 incAmount := int64(10) - incAmountPtr, err := newParameterPtr(ctx, incAmount, rt2) + incAmountPtr, err := runtime.NewSmartPtr(ctx, incAmount, rt2) require.NoError(err) result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, incAmountPtr) require.NoError(err) @@ -128,7 +128,7 @@ func TestCounterProgram(t *testing.T) { } // increment alice's counter on program 1 - onePtr, err := newParameterPtr(ctx, int64(1), rt) + onePtr, err := runtime.NewSmartPtr(ctx, int64(1), rt) require.NoError(err) result, err = rt.Call(ctx, "inc", programIDPtr, alicePtr, onePtr) require.NoError(err) @@ -142,17 +142,17 @@ func TestCounterProgram(t *testing.T) { ) // write program id 2 to stack of program 1 - programID2Ptr, err = newParameterPtr(ctx, program2ID, rt) + programID2Ptr, err = runtime.NewSmartPtr(ctx, program2ID, rt) require.NoError(err) caller := programIDPtr target := programID2Ptr maxUnitsProgramToProgram := int64(10000) - maxUnitsProgramToProgramPtr, err := newParameterPtr(ctx, maxUnitsProgramToProgram, rt) + maxUnitsProgramToProgramPtr, err := runtime.NewSmartPtr(ctx, maxUnitsProgramToProgram, rt) require.NoError(err) // increment alice's counter on program 2 - fivePtr, err := newParameterPtr(ctx, int64(5), rt) + fivePtr, err := runtime.NewSmartPtr(ctx, int64(5), rt) require.NoError(err) result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgramPtr, alicePtr, fivePtr) require.NoError(err) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index afdf8431af..86a9e5305b 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -16,7 +16,7 @@ import ( "github.com/ava-labs/hypersdk/consts" "github.com/ava-labs/hypersdk/state" - "github.com/ava-labs/hypersdk/x/programs/examples/imports" + "github.com/ava-labs/hypersdk/x/programs/examples/storage" "github.com/ava-labs/hypersdk/x/programs/runtime" ) @@ -72,7 +72,7 @@ func (i *Import) callProgramFn( defer cancel() client := runtime.NewExportClient(caller) // get the entry function for invoke to call. - functionBytes, err := imports.GetBytesFromArgPtr(client, function) + functionBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(function)) if err != nil { i.log.Error("failed to read function name from memory", zap.Error(err), @@ -80,7 +80,7 @@ func (i *Import) callProgramFn( return -1 } - programIDBytes, err := imports.GetBytesFromArgPtr(client, programID) + programIDBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(programID)) if err != nil { i.log.Error("failed to read id from memory", zap.Error(err), @@ -131,7 +131,7 @@ func (i *Import) callProgramFn( } }() - argsBytes, err := imports.GetBytesFromArgPtr(client, args) + argsBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(args)) if err != nil { i.log.Error("failed to read program args name from memory", zap.Error(err), @@ -159,18 +159,18 @@ func (i *Import) callProgramFn( return int64(res[0]) } -func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]int64, error) { +func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]runtime.SmartPtr, error) { // first arg contains id of program to call invokeProgramIDPtr, err := runtime.WriteBytes(memory, programIDBytes) if err != nil { return nil, err } - argPtr, err := imports.ToPtrArgument(invokeProgramIDPtr, uint32(len(programIDBytes))) + argPtr, err := runtime.ToSmartPtr(uint32(invokeProgramIDPtr), uint32(len(programIDBytes))) if err != nil { return nil, err } - args := []int64{argPtr} + args := []runtime.SmartPtr{argPtr} for i := 0; i < len(buffer); { // unpacks uint32 @@ -185,7 +185,7 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog if err != nil { return nil, err } - argPtr, err := imports.ToPtrArgument(ptr, length) + argPtr, err := runtime.ToSmartPtr(uint32(ptr), length) if err != nil { return nil, err } diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 3b9c40930a..c169d42483 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -16,7 +16,6 @@ import ( "github.com/ava-labs/avalanchego/utils/logging" "github.com/ava-labs/hypersdk/state" - "github.com/ava-labs/hypersdk/x/programs/examples/imports" "github.com/ava-labs/hypersdk/x/programs/examples/storage" "github.com/ava-labs/hypersdk/x/programs/runtime" ) @@ -62,7 +61,7 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, _ runtime.Supp func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64) int32 { client := runtime.NewExportClient(caller) // memory := runtime.NewMemory(client) - programIDBytes, err := imports.GetBytesFromArgPtr(client, id) + programIDBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(id)) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -70,7 +69,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 return -1 } - keyBytes, err := imports.GetBytesFromArgPtr(client, key) + keyBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(key)) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -78,7 +77,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 return -1 } -valueBytes, err := imports.GetBytesFromArgPtr(client, value) +valueBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(value)) if err != nil { i.log.Error("failed to read value from memory", @@ -102,7 +101,7 @@ valueBytes, err := imports.GetBytesFromArgPtr(client, value) func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) - programIDBytes, err := imports.GetBytesFromArgPtr(client, id) + programIDBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(id)) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -110,7 +109,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { return -1 } - keyBytes, err := imports.GetBytesFromArgPtr(client, key) + keyBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(key)) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -143,7 +142,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { } return -1 } - argPtr, err := imports.ToPtrArgument(ptr, uint32(len(val))) + argPtr, err := runtime.ToSmartPtr(uint32(ptr), uint32(len(val))) if err != nil { i.log.Error("failed to convert ptr to argument", zap.Error(err), @@ -151,5 +150,5 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { return -1 } - return argPtr + return int64(argPtr) } diff --git a/x/programs/examples/imports/utils.go b/x/programs/examples/imports/utils.go deleted file mode 100644 index 287e403fd4..0000000000 --- a/x/programs/examples/imports/utils.go +++ /dev/null @@ -1,47 +0,0 @@ -// Copyright (C) 2023, Ava Labs, Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -package imports - -import ( - "fmt" - - "github.com/ava-labs/hypersdk/x/programs/runtime" -) - -// GetBytesFromArgPtr returns the bytes at [ptr] in [client] memory. -// The first 4 bytes of [ptr] must represent the length and the -// following 4 bytes represent the pointer to the bytes. -func GetBytesFromArgPtr(client runtime.WasmtimeExportClient, ptrArg int64) ([]byte, error) { - memory := runtime.NewMemory(client) - - // first 4 bytes represent the length of the bytes to return - length := ptrArg >> 32 - - // grab the ptr which is the right most 4 bytes - mask := ^uint32(0) - ptr := ptrArg & int64(mask) - - - // The following [length] bytes represent the bytes to return - bytes, err := memory.Range(uint64(ptr), uint64(length)) - if err != nil { - return nil, err - } - - return bytes, nil -} - -// ToPtrArgument converts [ptr] to an int64 with the length of [bytes] in the upper 32 bits -// and [ptr] in the lower 32 bits. -func ToPtrArgument(ptr int64, len uint32) (int64, error) { - // ensure length of bytes is not greater than int32 to prevent overflow - if !runtime.EnsureUint32ToInt32(len) { - return 0, fmt.Errorf("length of bytes is greater than int32") - } - - // convert to int64 with length of bytes in the upper 32 bits and ptr in the lower 32 bits - argPtr := int64(len) << 32 - argPtr |= int64((uint32(ptr))) - return argPtr, nil -} diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index e0bcfd688c1c62727fcf7f9c3d44b22280d028b1..e0cde6d6e10ee3c371b429f8c10a9e08889261bf 100755 GIT binary patch literal 59507 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

v?~|bKyEW?%K3t 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 delta 16240 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 Kqs-ecE&gx9t*PVy diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index f3a82908ec..2e3999abcf 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -63,7 +63,7 @@ func (t *Token) Run(ctx context.Context) error { return err } - programIDPtr, err := newParameterPtr(ctx, programID, rt) + programIDPtr, err := runtime.NewSmartPtr(ctx, programID, rt) if err != nil { return err } @@ -97,7 +97,7 @@ func (t *Token) Run(ctx context.Context) error { } // write alice's key to stack and get pointer - alicePtr, err := newParameterPtr(ctx, aliceKey, rt) + alicePtr, err := runtime.NewSmartPtr(ctx, aliceKey, rt) if err != nil { return err } @@ -109,7 +109,7 @@ func (t *Token) Run(ctx context.Context) error { } // write bob's key to stack and get pointer - bobPtr, err := newParameterPtr(ctx, bobKey, rt) + bobPtr, err := runtime.NewSmartPtr(ctx, bobKey, rt) if err != nil { return err } @@ -125,7 +125,7 @@ func (t *Token) Run(ctx context.Context) error { // mint 100 tokens to alice mintAlice := int64(1000) - mintAlicePtr, err := newParameterPtr(ctx, mintAlice, rt) + mintAlicePtr, err := runtime.NewSmartPtr(ctx, mintAlice, rt) if err != nil { return err } @@ -158,7 +158,7 @@ func (t *Token) Run(ctx context.Context) error { // transfer 50 from alice to bob transferToBob := int64(50) - transferToBobPtr, err := newParameterPtr(ctx, transferToBob, rt) + transferToBobPtr, err := runtime.NewSmartPtr(ctx, transferToBob, rt) if err != nil { return err } @@ -171,7 +171,7 @@ func (t *Token) Run(ctx context.Context) error { zap.Int64("to bob", transferToBob), ) - onePtr, err := newParameterPtr(ctx, int64(1), rt) + onePtr, err := runtime.NewSmartPtr(ctx, int64(1), rt) if err != nil { return err } @@ -217,7 +217,7 @@ func (t *Token) Run(ctx context.Context) error { }, } - mintersPtr, err := newParameterPtr(ctx, minters, rt) + mintersPtr, err := runtime.NewSmartPtr(ctx, minters, rt) if err != nil { return err } @@ -270,7 +270,7 @@ func (t *Token) RunShort(ctx context.Context) error { return err } - programIDPtr, err := newParameterPtr(ctx, programID, rt) + programIDPtr, err := runtime.NewSmartPtr(ctx, programID, rt) if err != nil { return err } diff --git a/x/programs/examples/utils.go b/x/programs/examples/utils.go index cc6d556e24..abae16e43d 100644 --- a/x/programs/examples/utils.go +++ b/x/programs/examples/utils.go @@ -10,53 +10,8 @@ import ( "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/hypersdk/crypto/ed25519" "github.com/ava-labs/hypersdk/state" - "github.com/ava-labs/hypersdk/x/programs/examples/imports" - "github.com/ava-labs/hypersdk/x/programs/runtime" - "github.com/near/borsh-go" ) -// newPtr allocates memory and writes [bytes] to it. -// If [prependLength] is true, it prepends the length of [bytes] as a uint32 to [bytes]. -// It returns the pointer to the allocated memory. -func newPtr(ctx context.Context, bytes []byte, rt runtime.Runtime) (int64, error) { - amountToAllocate := uint64(len(bytes)) - - ptr, err := rt.Memory().Alloc(amountToAllocate) - if err != nil { - return 0, err - } - - // write programID to memory which we will later pass to the program - err = rt.Memory().Write(ptr, bytes) - if err != nil { - return 0, err - } - - return int64(ptr), err -} - -// serializeParameter serializes [obj] -// using Borsh and prepends its length as a uint32. -// Designed for serializing parameters passed to a WASM program. -func serializeParameter(obj interface{}) ([]byte, error) { - bytes, err := borsh.Serialize(obj) - return bytes, err -} - -// newParameterPtr serializes [obj] and allocates memory for it. -func newParameterPtr(ctx context.Context, obj interface{}, rt runtime.Runtime) (int64, error) { - bytes, err := serializeParameter(obj) - if err != nil { - return 0, err - } - ptr, err := newPtr(ctx, bytes, rt) - if err != nil { - return 0, err - } - - return imports.ToPtrArgument(ptr, uint32(len(bytes))) -} - func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { priv, err := ed25519.GeneratePrivateKey() if err != nil { diff --git a/x/programs/runtime/dependencies.go b/x/programs/runtime/dependencies.go index 1145b5f6ec..eb8f376031 100644 --- a/x/programs/runtime/dependencies.go +++ b/x/programs/runtime/dependencies.go @@ -32,7 +32,7 @@ type Runtime interface { // Call invokes an exported guest function with the given parameters. // Returns the results of the call or an error if the call failed. // If the function called does not return a result this value is set to nil. - Call(context.Context, string, ...int64) ([]int64, error) + Call(context.Context, string, ...SmartPtr) ([]int64, error) // Memory returns the runtime memory. Memory() Memory // Meter returns the runtime meter. diff --git a/x/programs/runtime/runtime.go b/x/programs/runtime/runtime.go index 9525b55719..c84cbcaa69 100644 --- a/x/programs/runtime/runtime.go +++ b/x/programs/runtime/runtime.go @@ -152,7 +152,7 @@ func getRegisteredImportModules(importTypes []*wasmtime.ImportType) []string { return imports } -func (r *WasmRuntime) Call(_ context.Context, name string, params ...int64) ([]int64, error) { +func (r *WasmRuntime) Call(_ context.Context, name string, params ...SmartPtr) ([]int64, error) { var fnName string switch name { case AllocFnName, DeallocFnName, MemoryFnName: @@ -242,18 +242,18 @@ func PreCompileWasmBytes(programBytes []byte, cfg *Config) ([]byte, error) { } // mapFunctionParams maps call input to the expected wasm function params. -func mapFunctionParams(input []int64, values []*wasmtime.ValType) ([]interface{}, error) { +func mapFunctionParams(input []SmartPtr, values []*wasmtime.ValType) ([]interface{}, error) { params := make([]interface{}, len(values)) for i, v := range values { switch v.Kind() { case wasmtime.KindI32: // ensure this value is within the range of an int32 - if !EnsureInt64ToInt32(input[i]) { + if !EnsureInt64ToInt32(int64(input[i])) { return nil, fmt.Errorf("%w: %d", ErrIntegerConversionOverflow, input[i]) } params[i] = int32(input[i]) case wasmtime.KindI64: - params[i] = input[i] + params[i] = int64(input[i]) default: return nil, fmt.Errorf("%w: %v", ErrInvalidParamType, v.Kind()) } diff --git a/x/programs/runtime/utils.go b/x/programs/runtime/utils.go index a2216fb024..6e53dcd207 100644 --- a/x/programs/runtime/utils.go +++ b/x/programs/runtime/utils.go @@ -3,7 +3,13 @@ package runtime -import "math" +import ( + "context" + "fmt" + "math" + + "github.com/near/borsh-go" +) func EnsureInt64ToInt32(v int64) bool { return v >= math.MinInt32 && v <= math.MaxInt32 @@ -11,4 +17,89 @@ func EnsureInt64ToInt32(v int64) bool { func EnsureUint32ToInt32(v uint32) bool { return v <= math.MaxInt32 +} + +// SmartPtr is an int64 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. +type SmartPtr int64; + +// ptrMask is used to get the lower 32 bits of a SmartPtr +var ptrMask = ^uint32(0) + +// GetBytesFromArgPtr returns the bytes at [ptr] in [client] memory. +func FromSmartPtr(client WasmtimeExportClient, smartPtr SmartPtr) ([]byte, error) { + memory := NewMemory(client) + + ptr, length := splitSmartPtr(smartPtr) + + // The following [length] bytes represent the bytes to return + bytes, err := memory.Range(uint64(ptr), uint64(length)) + if err != nil { + return nil, err + } + + return bytes, nil +} + +// ToSmartPtr converts [ptr] and [len] to a SmartPtr. +func ToSmartPtr(ptr uint32, len uint32) (SmartPtr, error) { + // ensure length of bytes is not greater than int32 to prevent overflow + if !EnsureUint32ToInt32(len) { + return 0, fmt.Errorf("length of bytes is greater than int32") + } + + // convert to int64 with length of bytes in the upper 32 bits and ptr in the lower 32 bits + smartPtr := int64(len) << 32 + smartPtr |= int64(ptr) + return SmartPtr(smartPtr), nil +} + +// splitSmartPtr splits the upper 32 and lower 32 bits of [smartPtr] +// into a length and ptr respectively. +func splitSmartPtr(smartPtr SmartPtr) (uint32, uint32) { + length := smartPtr >> 32 + ptr := int64(smartPtr) & int64(ptrMask) + + return uint32(ptr), uint32(length) +} + +// NewRuntimePtr allocates memory in the runtime and writes [bytes] to it. +// It returns the pointer of the allocated memory. +func NewRuntimePtr(ctx context.Context, bytes []byte, rt Runtime) (int64, error) { + amountToAllocate := len(bytes) + + ptr, err := rt.Memory().Alloc(uint64(amountToAllocate)) + if err != nil { + return 0, err + } + + // write programID to memory which we will later pass to the program + err = rt.Memory().Write(ptr, bytes) + if err != nil { + return 0, err + } + + return int64(ptr), err +} + +// SerializeParameter serializes [obj] using Borsh +func SerializeParameter(obj interface{}) ([]byte, error) { + bytes, err := borsh.Serialize(obj) + return bytes, err +} + +// NewSmartPtr creates a SmartPtr by serializing the provided object using Borsh, +// allocating memory for it in [rt], and constructing a SmartPtr +// from the resulting pointer and length of the serialized bytes. +func NewSmartPtr(ctx context.Context, obj interface{}, rt Runtime) (SmartPtr, error) { + bytes, err := SerializeParameter(obj) + if err != nil { + return 0, err + } + ptr, err := NewRuntimePtr(ctx, bytes, rt) + if err != nil { + return 0, err + } + + return ToSmartPtr(uint32(ptr), uint32(len(bytes))) } \ No newline at end of file From cc96b79436f7293c46db7347342782425671af9d Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 17:06:31 -0800 Subject: [PATCH 65/74] go lint --- x/programs/examples/counter_test.go | 18 +++++++------- .../examples/imports/program/program.go | 6 +++-- x/programs/examples/imports/pstate/pstate.go | 10 ++++---- x/programs/examples/testdata/counter.wasm | Bin 59507 -> 37093 bytes x/programs/examples/testdata/token.wasm | Bin 54126 -> 36150 bytes x/programs/examples/token.go | 16 ++++++------ x/programs/examples/token_test.go | 8 +++--- x/programs/runtime/utils.go | 23 +++++++++--------- 8 files changed, 41 insertions(+), 40 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index e2ebf91e15..e8e929d30d 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -52,7 +52,7 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, programID, counterProgramBytes) require.NoError(err) - programIDPtr, err := runtime.NewSmartPtr(ctx, programID, rt) + programIDPtr, err := runtime.NewSmartPtr(programID, rt) require.NoError(err) // generate alice keys @@ -60,7 +60,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr, err := runtime.NewSmartPtr(ctx, aliceKey, rt) + alicePtr, err := runtime.NewSmartPtr(aliceKey, rt) require.NoError(err) // create counter for alice on program 1 @@ -93,11 +93,11 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, program2ID, counterProgramBytes) require.NoError(err) - programID2Ptr, err := runtime.NewSmartPtr(ctx, program2ID, rt2) + programID2Ptr, err := runtime.NewSmartPtr(program2ID, rt2) require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := runtime.NewSmartPtr(ctx, aliceKey, rt2) + alicePtr2, err := runtime.NewSmartPtr(aliceKey, rt2) require.NoError(err) // initialize counter for alice on runtime 2 @@ -107,7 +107,7 @@ func TestCounterProgram(t *testing.T) { // increment alice's counter on program 2 by 10 incAmount := int64(10) - incAmountPtr, err := runtime.NewSmartPtr(ctx, incAmount, rt2) + incAmountPtr, err := runtime.NewSmartPtr(incAmount, rt2) require.NoError(err) result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, incAmountPtr) require.NoError(err) @@ -128,7 +128,7 @@ func TestCounterProgram(t *testing.T) { } // increment alice's counter on program 1 - onePtr, err := runtime.NewSmartPtr(ctx, int64(1), rt) + onePtr, err := runtime.NewSmartPtr(int64(1), rt) require.NoError(err) result, err = rt.Call(ctx, "inc", programIDPtr, alicePtr, onePtr) require.NoError(err) @@ -142,17 +142,17 @@ func TestCounterProgram(t *testing.T) { ) // write program id 2 to stack of program 1 - programID2Ptr, err = runtime.NewSmartPtr(ctx, program2ID, rt) + programID2Ptr, err = runtime.NewSmartPtr(program2ID, rt) require.NoError(err) caller := programIDPtr target := programID2Ptr maxUnitsProgramToProgram := int64(10000) - maxUnitsProgramToProgramPtr, err := runtime.NewSmartPtr(ctx, maxUnitsProgramToProgram, rt) + maxUnitsProgramToProgramPtr, err := runtime.NewSmartPtr(maxUnitsProgramToProgram, rt) require.NoError(err) // increment alice's counter on program 2 - fivePtr, err := runtime.NewSmartPtr(ctx, int64(5), rt) + fivePtr, err := runtime.NewSmartPtr(int64(5), rt) require.NoError(err) result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgramPtr, alicePtr, fivePtr) require.NoError(err) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index 86a9e5305b..bffd838d8c 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -159,6 +159,8 @@ func (i *Import) callProgramFn( return int64(res[0]) } + +// getCallArgs returns the arguments to be passed to the program being invoked from [buffer]. func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]runtime.SmartPtr, error) { // first arg contains id of program to call invokeProgramIDPtr, err := runtime.WriteBytes(memory, programIDBytes) @@ -169,7 +171,7 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog if err != nil { return nil, err } - + args := []runtime.SmartPtr{argPtr} for i := 0; i < len(buffer); { @@ -177,7 +179,7 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog lenBytes := buffer[i : i+consts.Uint32Len] length := binary.BigEndian.Uint32(lenBytes) - valueBytes := buffer[i + consts.Uint32Len : i+ consts.Uint32Len + int(length)] + valueBytes := buffer[i+consts.Uint32Len : i+consts.Uint32Len+int(length)] i += int(length) + consts.Uint32Len // every argument is a pointer diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index c169d42483..8ea4becfc1 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -72,12 +72,12 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 keyBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(key)) if err != nil { i.log.Error("failed to read key from memory", - zap.Error(err), - ) - return -1 -} + zap.Error(err), + ) + return -1 + } -valueBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(value)) + valueBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(value)) if err != nil { i.log.Error("failed to read value from memory", diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index e0cde6d6e10ee3c371b429f8c10a9e08889261bf..e0bcfd688c1c62727fcf7f9c3d44b22280d028b1 100755 GIT binary patch delta 16240 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

v?~|bKyEW?%K3t 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 diff --git a/x/programs/examples/testdata/token.wasm b/x/programs/examples/testdata/token.wasm index b9e55375a5a136d0dd28b0a15d0011313a6c7af3..42b2c90abf37f069ef15e66206f991a34eb55f19 100755 GIT binary patch delta 15363 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 Kqs-ecE&gx9t*PVy literal 54126 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 32 ptr := int64(smartPtr) & int64(ptrMask) return uint32(ptr), uint32(length) -} +} // NewRuntimePtr allocates memory in the runtime and writes [bytes] to it. // It returns the pointer of the allocated memory. -func NewRuntimePtr(ctx context.Context, bytes []byte, rt Runtime) (int64, error) { +func NewRuntimePtr(bytes []byte, rt Runtime) (int64, error) { amountToAllocate := len(bytes) ptr, err := rt.Memory().Alloc(uint64(amountToAllocate)) @@ -82,7 +81,7 @@ func NewRuntimePtr(ctx context.Context, bytes []byte, rt Runtime) (int64, error) return int64(ptr), err } -// SerializeParameter serializes [obj] using Borsh +// SerializeParameter serializes [obj] using Borsh func SerializeParameter(obj interface{}) ([]byte, error) { bytes, err := borsh.Serialize(obj) return bytes, err @@ -90,16 +89,16 @@ func SerializeParameter(obj interface{}) ([]byte, error) { // NewSmartPtr creates a SmartPtr by serializing the provided object using Borsh, // allocating memory for it in [rt], and constructing a SmartPtr -// from the resulting pointer and length of the serialized bytes. -func NewSmartPtr(ctx context.Context, obj interface{}, rt Runtime) (SmartPtr, error) { +// from the resulting pointer and length of the serialized bytes. +func NewSmartPtr(obj interface{}, rt Runtime) (SmartPtr, error) { bytes, err := SerializeParameter(obj) if err != nil { return 0, err } - ptr, err := NewRuntimePtr(ctx, bytes, rt) + ptr, err := NewRuntimePtr(bytes, rt) if err != nil { return 0, err } return ToSmartPtr(uint32(ptr), uint32(len(bytes))) -} \ No newline at end of file +} From a17803d7fa78197b6df98f744d4c0489a9bbc178 Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 17:26:46 -0800 Subject: [PATCH 66/74] rust lint --- .../rust/wasmlanche_sdk/src/host/program.rs | 21 ++----- .../rust/wasmlanche_sdk/src/host/state.rs | 12 ++-- x/programs/rust/wasmlanche_sdk/src/memory.rs | 57 ++++++++++++------- 3 files changed, 48 insertions(+), 42 deletions(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/program.rs b/x/programs/rust/wasmlanche_sdk/src/host/program.rs index df58cc26f4..40061ce6af 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/program.rs @@ -1,6 +1,6 @@ //! The `program` module provides functions for calling other programs. +use crate::memory::to_smart_ptr; use crate::program::Program; -use crate::memory::to_ptr_arg; #[link(wasm_import_module = "program")] extern "C" { @@ -23,21 +23,12 @@ pub(crate) fn call( function_name: &str, args: &[u8], ) -> i64 { - let caller_id = caller.id(); - let caller = to_ptr_arg(&caller_id).unwrap(); + let caller = to_smart_ptr(&caller_id).unwrap(); let target_id = target.id(); - let target = to_ptr_arg(&target_id).unwrap(); - let function = to_ptr_arg(function_name.as_bytes()).unwrap(); - let args = to_ptr_arg(args).unwrap(); + let target = to_smart_ptr(&target_id).unwrap(); + let function = to_smart_ptr(function_name.as_bytes()).unwrap(); + let args = to_smart_ptr(args).unwrap(); - unsafe { - _call_program( - caller, - target, - max_units, - function, - args, - ) - } + unsafe { _call_program(caller, target, max_units, function, args) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 15fae168ad..3f147aba85 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -1,7 +1,7 @@ //! The `state` module provides functions for interacting with persistent //! storage exposed by the host. use crate::errors::StateError; -use crate::memory::to_ptr_arg; +use crate::memory::to_smart_ptr; use crate::{program::Program, state::Key}; use borsh::{to_vec, BorshSerialize}; @@ -22,9 +22,9 @@ where let value_bytes = to_vec(value).map_err(|_| StateError::Serialization)?; // prepend length to both key & value let caller_id = caller.id(); - let caller = to_ptr_arg(&caller_id)?; - let value = to_ptr_arg(&value_bytes)?; - let key = to_ptr_arg(key)?; + let caller = to_smart_ptr(&caller_id)?; + let value = to_smart_ptr(&value_bytes)?; + let key = to_smart_ptr(key)?; match unsafe { _put(caller, key, value) } { 0 => Ok(()), @@ -36,7 +36,7 @@ where pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key let caller_id = caller.id(); - let caller = to_ptr_arg(&caller_id).unwrap(); - let key = to_ptr_arg(key).unwrap(); + let caller = to_smart_ptr(&caller_id).unwrap(); + let key = to_smart_ptr(key).unwrap(); unsafe { _get(caller, key) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index ecde3cc82d..4b632ce39d 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -71,23 +71,42 @@ impl Memory { } } -// Converts a pointer to a i64 with the first 4 bytes of the pointer -// representing the length of the memory block. -pub fn to_ptr_arg(arg: &[u8]) -> Result { - let mut ptr = - u32::try_from(arg.as_ptr() as i64).map_err(|_| StateError::IntegerConversion)? as i64; - let len = u32::try_from(arg.len()).map_err(|_| StateError::IntegerConversion)? as i64; - ptr |= len << 32; - Ok(ptr) +/// `SmartPtr` 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. +pub type SmartPtr = i64; + +/// Converts a pointer to a i64 with the first 4 bytes of the pointer +/// representing the length of the memory block. +/// # Errors +/// Returns an `StateError` if the pointer or length of [args] exceeds +/// the maximum size of a u32. +#[allow(clippy::cast_possible_truncation)] +pub fn to_smart_ptr(arg: &[u8]) -> Result { + let ptr = arg.as_ptr() as usize; + let len = arg.len(); + + // Make sure the pointer and length fit into u32 + if ptr > u32::MAX as usize || len > u32::MAX as usize { + return Err(StateError::IntegerConversion); + } + + let smart_ptr = i64::from(ptr as u32) | (i64::from(len as u32) << 32); + Ok(smart_ptr) } -// Converts a i64 to a pointer with the first 4 bytes of the pointer -// representing the length of the memory block. -pub fn from_ptr_arg(arg: i64) -> (i64, usize) { - let len = (arg >> 32) as usize; +/// Converts a i64 to a pointer with the first 4 bytes of the pointer +/// representing the length of the memory block. +/// # Panics +/// Panics if arg is negative. +#[must_use] +#[allow(clippy::cast_sign_loss)] +pub fn from_smart_ptr(arg: SmartPtr) -> (i64, usize) { + assert!(arg >= 0); + + let len = arg >> 32; let mask: u32 = !0; - let ptr = arg & (mask as i64); - (ptr, len) + let ptr = arg & i64::from(mask); + (ptr, len as usize) } /// Converts a raw pointer to a deserialized value. @@ -108,17 +127,13 @@ where } /// Returns a tuple of the bytes and length of the argument. -/// PtrArg is encoded using Big Endian as an i64. -/// The first 32 bits representing the length of the bytes and -/// the last 32 representing the ptr. -/// # Panics -/// Panics if the value cannot be converted from i32 to usize. +/// `smart_ptr` is encoded using Big Endian as an i64. /// # Safety /// This function is unsafe because it dereferences raw pointers. #[must_use] -pub unsafe fn bytes_and_length(ptr_arg: i64) -> (Vec, usize) { +pub unsafe fn bytes_and_length(smart_ptr: i64) -> (Vec, usize) { // grab length from ptrArg - let (ptr, len) = from_ptr_arg(ptr_arg); + let (ptr, len) = from_smart_ptr(smart_ptr); let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len) }; (value.to_vec(), len) } From 158bfd2b60bb0bcd845238bd14177849a30f03b0 Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 17:35:32 -0800 Subject: [PATCH 67/74] update program impl --- x/programs/examples/testdata/counter.wasm | Bin 37093 -> 37320 bytes x/programs/examples/testdata/token.wasm | Bin 36150 -> 36782 bytes x/programs/examples/token_test.go | 2 +- .../rust/wasmlanche_sdk/src/host/program.rs | 6 ++---- .../rust/wasmlanche_sdk/src/host/state.rs | 6 ++---- x/programs/rust/wasmlanche_sdk/src/program.rs | 6 +++--- 6 files changed, 8 insertions(+), 12 deletions(-) diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index e0bcfd688c1c62727fcf7f9c3d44b22280d028b1..dab04782cef6376a00fc622cf7713c0430397d43 100755 GIT binary patch delta 7160 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 delta 8023 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 diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index bd4ac68be0..d0c01d2194 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -33,7 +33,7 @@ var ( // go test -v -timeout 30s -run ^TestTokenProgram$ github.com/ava-labs/hypersdk/x/programs/examples -memprofile benchvset.mem -cpuprofile benchvset.cpu func TestTokenProgram(t *testing.T) { require := require.New(t) - maxUnits := uint64(40000) + maxUnits := uint64(80000) cfg, err := runtime.NewConfigBuilder().Build() require.NoError(err) program, err := newTokenProgram(maxUnits, cfg, tokenProgramBytes) diff --git a/x/programs/rust/wasmlanche_sdk/src/host/program.rs b/x/programs/rust/wasmlanche_sdk/src/host/program.rs index 40061ce6af..a3c22c3cf7 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/program.rs @@ -23,10 +23,8 @@ pub(crate) fn call( function_name: &str, args: &[u8], ) -> i64 { - let caller_id = caller.id(); - let caller = to_smart_ptr(&caller_id).unwrap(); - let target_id = target.id(); - let target = to_smart_ptr(&target_id).unwrap(); + let caller = to_smart_ptr(caller.id()).unwrap(); + let target = to_smart_ptr(target.id()).unwrap(); let function = to_smart_ptr(function_name.as_bytes()).unwrap(); let args = to_smart_ptr(args).unwrap(); diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index 3f147aba85..fc3f8f3737 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -21,8 +21,7 @@ where { let value_bytes = to_vec(value).map_err(|_| StateError::Serialization)?; // prepend length to both key & value - let caller_id = caller.id(); - let caller = to_smart_ptr(&caller_id)?; + let caller = to_smart_ptr(caller.id())?; let value = to_smart_ptr(&value_bytes)?; let key = to_smart_ptr(key)?; @@ -35,8 +34,7 @@ where /// Gets the bytes associated with the key from the host. pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { // prepend length to key - let caller_id = caller.id(); - let caller = to_smart_ptr(&caller_id).unwrap(); + let caller = to_smart_ptr(caller.id()).unwrap(); let key = to_smart_ptr(key).unwrap(); unsafe { _get(caller, key) } } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 4f793c9ddf..6e6292806d 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -13,8 +13,8 @@ impl Program { /// Returns the id of the program. #[must_use] - pub fn id(&self) -> [u8; Self::LEN] { - self.0 + pub fn id(&self) -> &[u8; Self::LEN] { + &self.0 } #[must_use] @@ -26,7 +26,7 @@ impl Program { /// storage exposed by the host. #[must_use] pub fn state(&self) -> State { - State::new(Program::new(self.id())) + State::new(Program::new(*self.id())) } /// Attempts to call another program `target` from this program `caller`. From 2bd46d416d46312e09290a2fd1d063c793078aba Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 17:39:59 -0800 Subject: [PATCH 68/74] return result from rust side host function wrappers --- x/programs/examples/testdata/counter.wasm | Bin 37320 -> 37537 bytes x/programs/rust/examples/counter/src/lib.rs | 8 ++++++-- .../rust/wasmlanche_sdk/src/host/program.rs | 13 +++++++------ .../rust/wasmlanche_sdk/src/host/state.rs | 8 ++++---- x/programs/rust/wasmlanche_sdk/src/program.rs | 4 ++-- x/programs/rust/wasmlanche_sdk/src/state.rs | 2 +- 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index dab04782cef6376a00fc622cf7713c0430397d43..2655a22b0eefb1dc0e34c26d5806b51ddb46be41 100755 GIT binary patch delta 6130 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 delta 5827 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 LizQ^_$-e&w@h?S@ diff --git a/x/programs/rust/examples/counter/src/lib.rs b/x/programs/rust/examples/counter/src/lib.rs index 7f2be758a4..e94fff17b0 100644 --- a/x/programs/rust/examples/counter/src/lib.rs +++ b/x/programs/rust/examples/counter/src/lib.rs @@ -47,7 +47,9 @@ fn inc_external( of: Address, amount: i64, ) -> i64 { - program.call_program(&target, max_units, "inc", params!(&of, &amount)) + program + .call_program(&target, max_units, "inc", params!(&of, &amount)) + .unwrap() } /// Gets the count at the address. @@ -62,5 +64,7 @@ fn get_value(program: Program, of: Address) -> i64 { /// Gets the count at the address for an external program. #[public] fn get_value_external(program: Program, target: Program, max_units: i64, of: Address) -> i64 { - program.call_program(&target, max_units, "get_value", params!(&of)) + program + .call_program(&target, max_units, "get_value", params!(&of)) + .unwrap() } diff --git a/x/programs/rust/wasmlanche_sdk/src/host/program.rs b/x/programs/rust/wasmlanche_sdk/src/host/program.rs index a3c22c3cf7..ef739440a2 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/program.rs @@ -1,4 +1,5 @@ //! The `program` module provides functions for calling other programs. +use crate::errors::StateError; use crate::memory::to_smart_ptr; use crate::program::Program; @@ -22,11 +23,11 @@ pub(crate) fn call( max_units: i64, function_name: &str, args: &[u8], -) -> i64 { - let caller = to_smart_ptr(caller.id()).unwrap(); - let target = to_smart_ptr(target.id()).unwrap(); - let function = to_smart_ptr(function_name.as_bytes()).unwrap(); - let args = to_smart_ptr(args).unwrap(); +) -> Result { + let caller = to_smart_ptr(caller.id())?; + let target = to_smart_ptr(target.id())?; + let function = to_smart_ptr(function_name.as_bytes())?; + let args = to_smart_ptr(args)?; - unsafe { _call_program(caller, target, max_units, function, args) } + Ok(unsafe { _call_program(caller, target, max_units, function, args) }) } diff --git a/x/programs/rust/wasmlanche_sdk/src/host/state.rs b/x/programs/rust/wasmlanche_sdk/src/host/state.rs index fc3f8f3737..20ca3ba47a 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/state.rs @@ -32,9 +32,9 @@ where } /// Gets the bytes associated with the key from the host. -pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> i64 { +pub(crate) unsafe fn get_bytes(caller: &Program, key: &Key) -> Result { // prepend length to key - let caller = to_smart_ptr(caller.id()).unwrap(); - let key = to_smart_ptr(key).unwrap(); - unsafe { _get(caller, key) } + let caller = to_smart_ptr(caller.id())?; + let key = to_smart_ptr(key)?; + Ok(unsafe { _get(caller, key) }) } diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 6e6292806d..9f01e7314a 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -1,6 +1,6 @@ use borsh::{BorshDeserialize, BorshSerialize}; -use crate::{host::call_program, state::State}; +use crate::{errors::StateError, host::call_program, state::State}; /// Represents the current Program in the context of the caller. Or an external /// program that is being invoked. @@ -39,7 +39,7 @@ impl Program { max_units: i64, function_name: &str, args: Vec>, - ) -> i64 { + ) -> Result { // flatten the args into a single byte vector let args = args.into_iter().flatten().collect::>(); call_program(self, target, max_units, function_name, &args) diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index 5c48d3f8c3..ba958853aa 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -45,7 +45,7 @@ impl State { K: Into, T: BorshDeserialize, { - let val_ptr = unsafe { get_bytes(&self.program, &key.into()) }; + let val_ptr = unsafe { get_bytes(&self.program, &key.into())? }; if val_ptr < 0 { return Err(StateError::Read); } From ee4507d514a70cff097b8a0360133a43a8f4f835 Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 17:45:36 -0800 Subject: [PATCH 69/74] small rename --- x/programs/examples/testdata/counter.wasm | Bin 37537 -> 37537 bytes x/programs/rust/sdk_macros/src/lib.rs | 2 +- x/programs/rust/wasmlanche_sdk/src/memory.rs | 6 +++--- x/programs/rust/wasmlanche_sdk/src/state.rs | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x/programs/examples/testdata/counter.wasm b/x/programs/examples/testdata/counter.wasm index 2655a22b0eefb1dc0e34c26d5806b51ddb46be41..8ad9f2c730de7e19ef038b71bc71f7063667eedf 100755 GIT binary patch delta 149 zcmZ3ulxg8orU{RjIoR1YKILL(?4JCAJ&dtuvO9+kWAEk?jt`8JgLssI!eu-gfx;TR zXBm4Zf8(7#Ifd&3kQK`PcXKb_Z(+u+$(>5Mj9r_*E1hKqa*nDc06A*vd@MkYsdg!l mT&)d~m((%l0CIdyQh=OICQOV#&Q{YxAgOK!lAmhE69WJwGd1=A delta 162 zcmZ3ulxg8orU{Rj+1WTYKILL(?3(<6J&dt?vO9+kW6$Oijt`8J=kt7E?3p})_b proc_macro2::TokenStream { quote! { - unsafe { wasmlanche_sdk::memory::from_raw_ptr(#param_name).expect("error serializing ptr") } + unsafe { wasmlanche_sdk::memory::from_smart_ptr(#param_name).expect("error serializing ptr") } } } diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index 4b632ce39d..c6c18768da 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -100,7 +100,7 @@ pub fn to_smart_ptr(arg: &[u8]) -> Result { /// Panics if arg is negative. #[must_use] #[allow(clippy::cast_sign_loss)] -pub fn from_smart_ptr(arg: SmartPtr) -> (i64, usize) { +pub fn split_smart_ptr(arg: SmartPtr) -> (i64, usize) { assert!(arg >= 0); let len = arg >> 32; @@ -118,7 +118,7 @@ pub fn from_smart_ptr(arg: SmartPtr) -> (i64, usize) { /// This function is unsafe because it dereferences raw pointers. /// # Errors /// Returns an `StateError` if the bytes cannot be deserialized. -pub unsafe fn from_raw_ptr(ptr: i64) -> Result +pub unsafe fn from_smart_ptr(ptr: SmartPtr) -> Result where V: BorshDeserialize, { @@ -133,7 +133,7 @@ where #[must_use] pub unsafe fn bytes_and_length(smart_ptr: i64) -> (Vec, usize) { // grab length from ptrArg - let (ptr, len) = from_smart_ptr(smart_ptr); + let (ptr, len) = split_smart_ptr(smart_ptr); let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len) }; (value.to_vec(), len) } diff --git a/x/programs/rust/wasmlanche_sdk/src/state.rs b/x/programs/rust/wasmlanche_sdk/src/state.rs index ba958853aa..0920897ee1 100644 --- a/x/programs/rust/wasmlanche_sdk/src/state.rs +++ b/x/programs/rust/wasmlanche_sdk/src/state.rs @@ -1,7 +1,7 @@ use crate::{ errors::StateError, host::{get_bytes, put_bytes}, - memory::from_raw_ptr, + memory::from_smart_ptr, program::Program, }; use borsh::{BorshDeserialize, BorshSerialize}; @@ -51,7 +51,7 @@ impl State { } // Wrap in OK for now, change from_raw_ptr to return Result - unsafe { from_raw_ptr(val_ptr) } + unsafe { from_smart_ptr(val_ptr) } } } From 2ab2bb15829afb5e8d154ac2c88dd0d072ddbe3a Mon Sep 17 00:00:00 2001 From: samliok Date: Sat, 9 Dec 2023 17:52:01 -0800 Subject: [PATCH 70/74] rust lint --- x/programs/examples/token_test.go | 2 +- x/programs/rust/wasmlanche_sdk/src/host/program.rs | 1 - x/programs/rust/wasmlanche_sdk/src/program.rs | 3 ++- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/x/programs/examples/token_test.go b/x/programs/examples/token_test.go index d0c01d2194..3a4cd8a678 100644 --- a/x/programs/examples/token_test.go +++ b/x/programs/examples/token_test.go @@ -45,7 +45,7 @@ func TestTokenProgram(t *testing.T) { // go test -v -benchmem -run=^$ -bench ^BenchmarkTokenProgram$ github.com/ava-labs/hypersdk/x/programs/examples -memprofile benchvset.mem -cpuprofile benchvset.cpu func BenchmarkTokenProgram(b *testing.B) { require := require.New(b) - maxUnits := uint64(40000) + maxUnits := uint64(80000) cfg, err := runtime.NewConfigBuilder(). WithCompileStrategy(runtime.CompileWasm). diff --git a/x/programs/rust/wasmlanche_sdk/src/host/program.rs b/x/programs/rust/wasmlanche_sdk/src/host/program.rs index ef739440a2..df61db4ccf 100644 --- a/x/programs/rust/wasmlanche_sdk/src/host/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/host/program.rs @@ -16,7 +16,6 @@ extern "C" { } /// Calls another program `target` and returns the result. -#[must_use] pub(crate) fn call( caller: &Program, target: &Program, diff --git a/x/programs/rust/wasmlanche_sdk/src/program.rs b/x/programs/rust/wasmlanche_sdk/src/program.rs index 9f01e7314a..a25606cb9a 100644 --- a/x/programs/rust/wasmlanche_sdk/src/program.rs +++ b/x/programs/rust/wasmlanche_sdk/src/program.rs @@ -30,9 +30,10 @@ impl Program { } /// Attempts to call another program `target` from this program `caller`. + /// # Errors + /// Returns a `StateError` if the call fails. /// # Safety /// The caller must ensure that `function_name` + `args` point to valid memory locations. - #[must_use] pub fn call_program( &self, target: &Program, From f991a9582c447d05404da5f405852656ea6e06f4 Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 11 Dec 2023 09:47:13 -0800 Subject: [PATCH 71/74] into_bytes function --- x/programs/rust/wasmlanche_sdk/src/memory.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/x/programs/rust/wasmlanche_sdk/src/memory.rs b/x/programs/rust/wasmlanche_sdk/src/memory.rs index c6c18768da..e980118bfc 100644 --- a/x/programs/rust/wasmlanche_sdk/src/memory.rs +++ b/x/programs/rust/wasmlanche_sdk/src/memory.rs @@ -122,20 +122,18 @@ pub unsafe fn from_smart_ptr(ptr: SmartPtr) -> Result where V: BorshDeserialize, { - let (bytes, _) = bytes_and_length(ptr); + let bytes = into_bytes(ptr); from_slice::(&bytes).map_err(|_| StateError::Deserialization) } /// Returns a tuple of the bytes and length of the argument. /// `smart_ptr` is encoded using Big Endian as an i64. -/// # Safety -/// This function is unsafe because it dereferences raw pointers. #[must_use] -pub unsafe fn bytes_and_length(smart_ptr: i64) -> (Vec, usize) { +pub fn into_bytes(smart_ptr: SmartPtr) -> Vec { // grab length from ptrArg let (ptr, len) = split_smart_ptr(smart_ptr); let value = unsafe { std::slice::from_raw_parts(ptr as *const u8, len) }; - (value.to_vec(), len) + value.to_vec() } /// Attempts to allocate a block of memory of size `len` and returns a pointer From 866febf1a0f9eb9f4a06b09f0c3be9a79e92922e Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 11 Dec 2023 11:42:46 -0800 Subject: [PATCH 72/74] smart ptr method refactor --- x/programs/examples/counter_test.go | 18 ++-- .../examples/imports/program/program.go | 12 +-- x/programs/examples/imports/pstate/pstate.go | 14 +-- x/programs/examples/token.go | 16 ++-- x/programs/examples/utils.go | 18 ++++ x/programs/runtime/memory.go | 47 ++++++++++ x/programs/runtime/utils.go | 88 +------------------ 7 files changed, 97 insertions(+), 116 deletions(-) diff --git a/x/programs/examples/counter_test.go b/x/programs/examples/counter_test.go index e8e929d30d..948b6ee6e8 100644 --- a/x/programs/examples/counter_test.go +++ b/x/programs/examples/counter_test.go @@ -52,7 +52,7 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, programID, counterProgramBytes) require.NoError(err) - programIDPtr, err := runtime.NewSmartPtr(programID, rt) + programIDPtr, err := argumentToSmartPtr(programID, rt.Memory()) require.NoError(err) // generate alice keys @@ -60,7 +60,7 @@ func TestCounterProgram(t *testing.T) { require.NoError(err) // write alice's key to stack and get pointer - alicePtr, err := runtime.NewSmartPtr(aliceKey, rt) + alicePtr, err := argumentToSmartPtr(aliceKey, rt.Memory()) require.NoError(err) // create counter for alice on program 1 @@ -93,11 +93,11 @@ func TestCounterProgram(t *testing.T) { err = storage.SetProgram(ctx, db, program2ID, counterProgramBytes) require.NoError(err) - programID2Ptr, err := runtime.NewSmartPtr(program2ID, rt2) + programID2Ptr, err := argumentToSmartPtr(program2ID, rt2.Memory()) require.NoError(err) // write alice's key to stack and get pointer - alicePtr2, err := runtime.NewSmartPtr(aliceKey, rt2) + alicePtr2, err := argumentToSmartPtr(aliceKey, rt2.Memory()) require.NoError(err) // initialize counter for alice on runtime 2 @@ -107,7 +107,7 @@ func TestCounterProgram(t *testing.T) { // increment alice's counter on program 2 by 10 incAmount := int64(10) - incAmountPtr, err := runtime.NewSmartPtr(incAmount, rt2) + incAmountPtr, err := argumentToSmartPtr(incAmount, rt2.Memory()) require.NoError(err) result, err = rt2.Call(ctx, "inc", programID2Ptr, alicePtr2, incAmountPtr) require.NoError(err) @@ -128,7 +128,7 @@ func TestCounterProgram(t *testing.T) { } // increment alice's counter on program 1 - onePtr, err := runtime.NewSmartPtr(int64(1), rt) + onePtr, err := argumentToSmartPtr(int64(1), rt.Memory()) require.NoError(err) result, err = rt.Call(ctx, "inc", programIDPtr, alicePtr, onePtr) require.NoError(err) @@ -142,17 +142,17 @@ func TestCounterProgram(t *testing.T) { ) // write program id 2 to stack of program 1 - programID2Ptr, err = runtime.NewSmartPtr(program2ID, rt) + programID2Ptr, err = argumentToSmartPtr(program2ID, rt.Memory()) require.NoError(err) caller := programIDPtr target := programID2Ptr maxUnitsProgramToProgram := int64(10000) - maxUnitsProgramToProgramPtr, err := runtime.NewSmartPtr(maxUnitsProgramToProgram, rt) + maxUnitsProgramToProgramPtr, err := argumentToSmartPtr(maxUnitsProgramToProgram, rt.Memory()) require.NoError(err) // increment alice's counter on program 2 - fivePtr, err := runtime.NewSmartPtr(int64(5), rt) + fivePtr, err := argumentToSmartPtr(int64(5), rt.Memory()) require.NoError(err) result, err = rt.Call(ctx, "inc_external", caller, target, maxUnitsProgramToProgramPtr, alicePtr, fivePtr) require.NoError(err) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index bffd838d8c..fa7e070331 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -70,9 +70,9 @@ func (i *Import) callProgramFn( ) int64 { ctx, cancel := context.WithCancel(context.Background()) defer cancel() - client := runtime.NewExportClient(caller) + memory := runtime.NewMemory(runtime.NewExportClient(caller)) // get the entry function for invoke to call. - functionBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(function)) + functionBytes, err := runtime.SmartPtr(function).Bytes(memory) if err != nil { i.log.Error("failed to read function name from memory", zap.Error(err), @@ -80,7 +80,7 @@ func (i *Import) callProgramFn( return -1 } - programIDBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(programID)) + programIDBytes, err := runtime.SmartPtr(programID).Bytes(memory) if err != nil { i.log.Error("failed to read id from memory", zap.Error(err), @@ -131,7 +131,7 @@ func (i *Import) callProgramFn( } }() - argsBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(args)) + argsBytes, err := runtime.SmartPtr(args).Bytes(memory) if err != nil { i.log.Error("failed to read program args name from memory", zap.Error(err), @@ -167,7 +167,7 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog if err != nil { return nil, err } - argPtr, err := runtime.ToSmartPtr(uint32(invokeProgramIDPtr), uint32(len(programIDBytes))) + argPtr, err := runtime.NewSmartPtr(uint32(invokeProgramIDPtr), len(programIDBytes)) if err != nil { return nil, err } @@ -187,7 +187,7 @@ func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, prog if err != nil { return nil, err } - argPtr, err := runtime.ToSmartPtr(uint32(ptr), length) + argPtr, err := runtime.NewSmartPtr(uint32(ptr), int(length)) if err != nil { return nil, err } diff --git a/x/programs/examples/imports/pstate/pstate.go b/x/programs/examples/imports/pstate/pstate.go index 8ea4becfc1..c0aeaf5a49 100644 --- a/x/programs/examples/imports/pstate/pstate.go +++ b/x/programs/examples/imports/pstate/pstate.go @@ -59,9 +59,9 @@ func (i *Import) Register(link runtime.Link, meter runtime.Meter, _ runtime.Supp } func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64) int32 { - client := runtime.NewExportClient(caller) + memory := runtime.NewMemory(runtime.NewExportClient(caller)) // memory := runtime.NewMemory(client) - programIDBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(id)) + programIDBytes, err := runtime.SmartPtr(id).Bytes(memory) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -69,7 +69,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 return -1 } - keyBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(key)) + keyBytes, err := runtime.SmartPtr(key).Bytes(memory) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -77,7 +77,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 return -1 } - valueBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(value)) + valueBytes, err := runtime.SmartPtr(value).Bytes(memory) if err != nil { i.log.Error("failed to read value from memory", @@ -101,7 +101,7 @@ func (i *Import) putFn(caller *wasmtime.Caller, id int64, key int64, value int64 func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { client := runtime.NewExportClient(caller) memory := runtime.NewMemory(client) - programIDBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(id)) + programIDBytes, err := runtime.SmartPtr(id).Bytes(memory) if err != nil { i.log.Error("failed to read program id from memory", zap.Error(err), @@ -109,7 +109,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { return -1 } - keyBytes, err := runtime.FromSmartPtr(client, runtime.SmartPtr(key)) + keyBytes, err := runtime.SmartPtr(key).Bytes(memory) if err != nil { i.log.Error("failed to read key from memory", zap.Error(err), @@ -142,7 +142,7 @@ func (i *Import) getFn(caller *wasmtime.Caller, id int64, key int64) int64 { } return -1 } - argPtr, err := runtime.ToSmartPtr(uint32(ptr), uint32(len(val))) + argPtr, err := runtime.NewSmartPtr(uint32(ptr), len(val)) if err != nil { i.log.Error("failed to convert ptr to argument", zap.Error(err), diff --git a/x/programs/examples/token.go b/x/programs/examples/token.go index 479fd87dd5..136d7c2dff 100644 --- a/x/programs/examples/token.go +++ b/x/programs/examples/token.go @@ -63,7 +63,7 @@ func (t *Token) Run(ctx context.Context) error { return err } - programIDPtr, err := runtime.NewSmartPtr(programID, rt) + programIDPtr, err := argumentToSmartPtr(programID, rt.Memory()) if err != nil { return err } @@ -97,7 +97,7 @@ func (t *Token) Run(ctx context.Context) error { } // write alice's key to stack and get pointer - alicePtr, err := runtime.NewSmartPtr(aliceKey, rt) + alicePtr, err := argumentToSmartPtr(aliceKey, rt.Memory()) if err != nil { return err } @@ -109,7 +109,7 @@ func (t *Token) Run(ctx context.Context) error { } // write bob's key to stack and get pointer - bobPtr, err := runtime.NewSmartPtr(bobKey, rt) + bobPtr, err := argumentToSmartPtr(bobKey, rt.Memory()) if err != nil { return err } @@ -125,7 +125,7 @@ func (t *Token) Run(ctx context.Context) error { // mint 100 tokens to alice mintAlice := int64(1000) - mintAlicePtr, err := runtime.NewSmartPtr(mintAlice, rt) + mintAlicePtr, err := argumentToSmartPtr(mintAlice, rt.Memory()) if err != nil { return err } @@ -158,7 +158,7 @@ func (t *Token) Run(ctx context.Context) error { // transfer 50 from alice to bob transferToBob := int64(50) - transferToBobPtr, err := runtime.NewSmartPtr(transferToBob, rt) + transferToBobPtr, err := argumentToSmartPtr(transferToBob, rt.Memory()) if err != nil { return err } @@ -171,7 +171,7 @@ func (t *Token) Run(ctx context.Context) error { zap.Int64("to bob", transferToBob), ) - onePtr, err := runtime.NewSmartPtr(int64(1), rt) + onePtr, err := argumentToSmartPtr(int64(1), rt.Memory()) if err != nil { return err } @@ -217,7 +217,7 @@ func (t *Token) Run(ctx context.Context) error { }, } - mintersPtr, err := runtime.NewSmartPtr(minters, rt) + mintersPtr, err := argumentToSmartPtr(minters, rt.Memory()) if err != nil { return err } @@ -270,7 +270,7 @@ func (t *Token) RunShort(ctx context.Context) error { return err } - programIDPtr, err := runtime.NewSmartPtr(programID, rt) + programIDPtr, err := argumentToSmartPtr(programID, rt.Memory()) if err != nil { return err } diff --git a/x/programs/examples/utils.go b/x/programs/examples/utils.go index abae16e43d..4ccbc1eb0d 100644 --- a/x/programs/examples/utils.go +++ b/x/programs/examples/utils.go @@ -10,6 +10,8 @@ import ( "github.com/ava-labs/avalanchego/database/memdb" "github.com/ava-labs/hypersdk/crypto/ed25519" "github.com/ava-labs/hypersdk/state" + "github.com/ava-labs/hypersdk/x/programs/runtime" + "github.com/near/borsh-go" ) func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { @@ -21,6 +23,22 @@ func newKey() (ed25519.PrivateKey, ed25519.PublicKey, error) { return priv, priv.PublicKey(), nil } +// SerializeParameter serializes [obj] using Borsh +func serializeParameter(obj interface{}) ([]byte, error) { + bytes, err := borsh.Serialize(obj) + return bytes, err +} + +// Serialize the parameter and create a smart ptr +func argumentToSmartPtr(obj interface{}, memory runtime.Memory) (runtime.SmartPtr, error) { + bytes, err := serializeParameter(obj) + if err != nil { + return 0, err + } + + return runtime.BytesToSmartPtr(bytes, memory) +} + var ( _ state.Mutable = &testDB{} _ state.Immutable = &testDB{} diff --git a/x/programs/runtime/memory.go b/x/programs/runtime/memory.go index 997b4790a1..6b6a719cca 100644 --- a/x/programs/runtime/memory.go +++ b/x/programs/runtime/memory.go @@ -15,6 +15,10 @@ type memory struct { client WasmtimeExportClient } +// SmartPtr is an int64 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. +type SmartPtr int64 + func NewMemory(client WasmtimeExportClient) *memory { return &memory{ client: client, @@ -164,3 +168,46 @@ func WriteParams(m Memory, p []CallParam) ([]int64, error) { return params, nil } + +func (s SmartPtr) Get() int64 { + return int64(s) +} + +func (s SmartPtr) Len() uint32 { + return uint32(s >> 32) +} + +func (s SmartPtr) PtrOffset() uint32 { + return uint32(s) +} + +func (s SmartPtr) Bytes(memory Memory) ([]byte, error) { + // read the range of PtrOffset + length from memory + bytes, err := memory.Range(uint64(s.PtrOffset()), uint64(s.Len())) + if err != nil { + return nil, err + } + + return bytes, nil +} + +func BytesToSmartPtr(bytes []byte, memory Memory) (SmartPtr, error) { + ptr, err := WriteBytes(memory, bytes) + if err != nil { + return 0, err + } + + return NewSmartPtr(uint32(ptr), len(bytes)) +} + +func NewSmartPtr(ptr uint32, len int) (SmartPtr, error) { + // ensure length of bytes is not greater than int32 to prevent overflow + if !EnsureIntToInt32(len) { + return 0, fmt.Errorf("length of bytes is greater than int32") + } + + lenUpperBits := int64(len) << 32 + ptrLowerBits := int64(ptr) + + return SmartPtr(lenUpperBits | ptrLowerBits), nil +} diff --git a/x/programs/runtime/utils.go b/x/programs/runtime/utils.go index f75d0c3d91..c65c183a5d 100644 --- a/x/programs/runtime/utils.go +++ b/x/programs/runtime/utils.go @@ -4,10 +4,7 @@ package runtime import ( - "fmt" "math" - - "github.com/near/borsh-go" ) func EnsureInt64ToInt32(v int64) bool { @@ -18,87 +15,6 @@ func EnsureUint32ToInt32(v uint32) bool { return v <= math.MaxInt32 } -// SmartPtr is an int64 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. -type SmartPtr int64 - -// ptrMask is used to get the lower 32 bits of a SmartPtr -var ptrMask = ^uint32(0) - -// FromSmartPtr returns the bytes at [ptr] in [client] memory. -func FromSmartPtr(client WasmtimeExportClient, smartPtr SmartPtr) ([]byte, error) { - memory := NewMemory(client) - - ptr, length := splitSmartPtr(smartPtr) - - // The following [length] bytes represent the bytes to return - bytes, err := memory.Range(uint64(ptr), uint64(length)) - if err != nil { - return nil, err - } - - return bytes, nil -} - -// ToSmartPtr converts [ptr] and [len] to a SmartPtr. -func ToSmartPtr(ptr uint32, len uint32) (SmartPtr, error) { - // ensure length of bytes is not greater than int32 to prevent overflow - if !EnsureUint32ToInt32(len) { - return 0, fmt.Errorf("length of bytes is greater than int32") - } - - // convert to int64 with length of bytes in the upper 32 bits and ptr in the lower 32 bits - smartPtr := int64(len) << 32 - smartPtr |= int64(ptr) - return SmartPtr(smartPtr), nil -} - -// splitSmartPtr splits the upper 32 and lower 32 bits of [smartPtr] -// into a length and ptr respectively. -func splitSmartPtr(smartPtr SmartPtr) (uint32, uint32) { - length := smartPtr >> 32 - ptr := int64(smartPtr) & int64(ptrMask) - - return uint32(ptr), uint32(length) -} - -// NewRuntimePtr allocates memory in the runtime and writes [bytes] to it. -// It returns the pointer of the allocated memory. -func NewRuntimePtr(bytes []byte, rt Runtime) (int64, error) { - amountToAllocate := len(bytes) - - ptr, err := rt.Memory().Alloc(uint64(amountToAllocate)) - if err != nil { - return 0, err - } - - // write programID to memory which we will later pass to the program - err = rt.Memory().Write(ptr, bytes) - if err != nil { - return 0, err - } - - return int64(ptr), err -} - -// SerializeParameter serializes [obj] using Borsh -func SerializeParameter(obj interface{}) ([]byte, error) { - bytes, err := borsh.Serialize(obj) - return bytes, err -} - -// NewSmartPtr creates a SmartPtr by serializing the provided object using Borsh, -// allocating memory for it in [rt], and constructing a SmartPtr -// from the resulting pointer and length of the serialized bytes. -func NewSmartPtr(obj interface{}, rt Runtime) (SmartPtr, error) { - bytes, err := SerializeParameter(obj) - if err != nil { - return 0, err - } - ptr, err := NewRuntimePtr(bytes, rt) - if err != nil { - return 0, err - } - - return ToSmartPtr(uint32(ptr), uint32(len(bytes))) +func EnsureIntToInt32(v int) bool { + return v >= math.MinInt32 && v <= math.MaxInt32 } From f2e9f72d7554404de1c486e8548144b2efb52dcf Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 11 Dec 2023 11:52:35 -0800 Subject: [PATCH 73/74] comments --- x/programs/examples/imports/program/program.go | 1 - x/programs/runtime/memory.go | 6 ++++++ x/programs/runtime/runtime.go | 4 ++-- x/programs/runtime/utils.go | 8 -------- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/x/programs/examples/imports/program/program.go b/x/programs/examples/imports/program/program.go index fa7e070331..1ef54baad7 100644 --- a/x/programs/examples/imports/program/program.go +++ b/x/programs/examples/imports/program/program.go @@ -159,7 +159,6 @@ func (i *Import) callProgramFn( return int64(res[0]) } - // getCallArgs returns the arguments to be passed to the program being invoked from [buffer]. func getCallArgs(ctx context.Context, memory runtime.Memory, buffer []byte, programIDBytes []byte) ([]runtime.SmartPtr, error) { // first arg contains id of program to call diff --git a/x/programs/runtime/memory.go b/x/programs/runtime/memory.go index 6b6a719cca..159b7cecfc 100644 --- a/x/programs/runtime/memory.go +++ b/x/programs/runtime/memory.go @@ -169,18 +169,22 @@ func WriteParams(m Memory, p []CallParam) ([]int64, error) { return params, nil } +// Get returns the int64 value of [s]. func (s SmartPtr) Get() int64 { return int64(s) } +// Len returns the length of the bytes stored in memory by [s]. func (s SmartPtr) Len() uint32 { return uint32(s >> 32) } +// PtrOffset returns the offset of the bytes stored in memory by [s]. func (s SmartPtr) PtrOffset() uint32 { return uint32(s) } +// Bytes returns the bytes stored in memory by [s]. func (s SmartPtr) Bytes(memory Memory) ([]byte, error) { // read the range of PtrOffset + length from memory bytes, err := memory.Range(uint64(s.PtrOffset()), uint64(s.Len())) @@ -191,6 +195,7 @@ func (s SmartPtr) Bytes(memory Memory) ([]byte, error) { return bytes, nil } +// BytesToSmartPtr writes [bytes] to memory and returns the resulting SmartPtr. func BytesToSmartPtr(bytes []byte, memory Memory) (SmartPtr, error) { ptr, err := WriteBytes(memory, bytes) if err != nil { @@ -200,6 +205,7 @@ func BytesToSmartPtr(bytes []byte, memory Memory) (SmartPtr, error) { return NewSmartPtr(uint32(ptr), len(bytes)) } +// NewSmartPtr returns a SmartPtr from [ptr] and [len]. func NewSmartPtr(ptr uint32, len int) (SmartPtr, error) { // ensure length of bytes is not greater than int32 to prevent overflow if !EnsureIntToInt32(len) { diff --git a/x/programs/runtime/runtime.go b/x/programs/runtime/runtime.go index c84cbcaa69..69a85c1d13 100644 --- a/x/programs/runtime/runtime.go +++ b/x/programs/runtime/runtime.go @@ -248,12 +248,12 @@ func mapFunctionParams(input []SmartPtr, values []*wasmtime.ValType) ([]interfac switch v.Kind() { case wasmtime.KindI32: // ensure this value is within the range of an int32 - if !EnsureInt64ToInt32(int64(input[i])) { + if !EnsureIntToInt32(int(input[i])) { return nil, fmt.Errorf("%w: %d", ErrIntegerConversionOverflow, input[i]) } params[i] = int32(input[i]) case wasmtime.KindI64: - params[i] = int64(input[i]) + params[i] = input[i] default: return nil, fmt.Errorf("%w: %v", ErrInvalidParamType, v.Kind()) } diff --git a/x/programs/runtime/utils.go b/x/programs/runtime/utils.go index c65c183a5d..89de3c1741 100644 --- a/x/programs/runtime/utils.go +++ b/x/programs/runtime/utils.go @@ -7,14 +7,6 @@ import ( "math" ) -func EnsureInt64ToInt32(v int64) bool { - return v >= math.MinInt32 && v <= math.MaxInt32 -} - -func EnsureUint32ToInt32(v uint32) bool { - return v <= math.MaxInt32 -} - func EnsureIntToInt32(v int) bool { return v >= math.MinInt32 && v <= math.MaxInt32 } From 7cb99c4aa4ac35d2b17a33464e19a2968f2b7f4c Mon Sep 17 00:00:00 2001 From: samliok Date: Mon, 11 Dec 2023 12:03:03 -0800 Subject: [PATCH 74/74] int64 conversionn --- x/programs/runtime/runtime.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/x/programs/runtime/runtime.go b/x/programs/runtime/runtime.go index 69a85c1d13..4f131bd849 100644 --- a/x/programs/runtime/runtime.go +++ b/x/programs/runtime/runtime.go @@ -253,7 +253,7 @@ func mapFunctionParams(input []SmartPtr, values []*wasmtime.ValType) ([]interfac } params[i] = int32(input[i]) case wasmtime.KindI64: - params[i] = input[i] + params[i] = int64(input[i]) default: return nil, fmt.Errorf("%w: %v", ErrInvalidParamType, v.Kind()) }