Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constants for WASM parsing and sample counter contract #56

Merged
merged 9 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
663 changes: 663 additions & 0 deletions pykwasm/src/pykwasm/kdist/wasm-semantics/binary-parser.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions tests/ulm/counter/rust/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
target/
130 changes: 130 additions & 0 deletions tests/ulm/counter/rust/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

26 changes: 26 additions & 0 deletions tests/ulm/counter/rust/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
[package]
name = "counter"
version = "0.1.0"
edition = "2021"

[lib]
crate-type = ["cdylib"]

[dependencies]
wasm-bindgen = "0.2"
bytes = "1.9"

#[profile.dev]
#panic = "abort"

[profile.release]
# this flag removes debug symbols
strip = true
# this flag and the one below optimizes for size, experiment with both and find the one that works better!
# opt-level = "z"
opt-level = "s"
# the flags below instruct the compiler to try harder to do whole-program optimization
lto = true
codegen-units = 1
# this flag tells the compiler to replace helpful debug behavior with calls to abort
panic = "abort"
24 changes: 24 additions & 0 deletions tests/ulm/counter/rust/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Rust/Wasm Counter Contract

This directory contains a Rust implementation of an Counter contract that is compiled into Wasm.

As is the case with many chains that use Wasm contracts, we compile this Rust project as a library;
that way, functions referenced in external libraries become host functions which can be provided via Wasm module imports.

In order to reduce the size of the compiled Wasm library, we referred to this guide:

https://github.com/johnthagen/min-sized-rust

To build the contract with all of the size minimization options, first, ensure that a recent build of the Rust compiler is installed with the Wasm32 target, which can be done with:

```sh
rustup install nightly
rustup target add wasm32-unknown-unknown --toolchain nightly
rustup component add rust-src --toolchain nightly-x86_64-unknown-linux-gnu
```

Then run the build script as follows:

```sh
./build.sh
```
7 changes: 7 additions & 0 deletions tests/ulm/counter/rust/build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/bin/bash
LOC_FLAG="-Zlocation-detail=none" # removes debugging info from binary
FMT_FLAG="-Zfmt-debug=none" # removes formatter code from binary
# the last two lines build stdlib for target with minimal panic handling and optimized for size
RUSTFLAGS="$LOC_FLAG $FMT_FLAG" cargo +nightly build --release --target wasm32-unknown-unknown \
-Z build-std=std,panic_abort \
-Z build-std-features="optimize_for_size,panic_immediate_abort"
99 changes: 99 additions & 0 deletions tests/ulm/counter/rust/src/address.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
use bytes::Bytes;
use core::cmp::Ordering;

use crate::decoder::Decodable;
use crate::encoder::{Encodable, EncodingType};
use crate::unsigned::{U160, U256};

#[derive(Debug)]
pub struct Address {
value: U160,
}

impl Address {
fn new(value: U160) -> Self {
Address { value }
}

pub fn zero() -> Self {
Address::new(U160::from_u64(0))
}

pub fn is_zero(&self) -> bool {
self.value == U160::from_u64(0)
}

pub fn into_u160(self) -> U160 {
self.value
}
pub fn into_u256(self) -> U256 {
self.value.into()
}
}

impl From<U160> for Address
{
fn from(value: U160) -> Self {
Address::new(value)
}
}
impl TryFrom<U256> for Address
{
type Error = &'static str;
fn try_from(value: U256) -> Result<Self, Self::Error> {
Ok(Address::new(value.try_into()?))
}
}
impl From<Address> for U160
{
fn from(value: Address) -> Self {
value.into_u160()
}
}
impl From<Address> for U256
{
fn from(value: Address) -> Self {
value.into_u256()
}
}

impl Ord for Address {
fn cmp(&self, other: &Self) -> Ordering {
self.value.cmp(&other.value)
}
}
impl PartialOrd for Address {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl PartialEq for Address {
fn eq(&self, other: &Self) -> bool {
self.cmp(other) == Ordering::Equal
}
}
impl Eq for Address {}
impl Clone for Address {
fn clone(&self) -> Self {
Address { value: self.value.clone() }
}
}

impl Encodable for Address
{
fn encode(&self) -> (EncodingType, Bytes) {
self.value.encode()
}
}
impl Decodable for Address
{
fn encoding_type() -> EncodingType {
U160::encoding_type()
}
fn head_size() -> usize {
U160::head_size()
}
fn decode(bytes: Bytes) -> Self {
Address::new(U160::decode(bytes))
}
}
15 changes: 15 additions & 0 deletions tests/ulm/counter/rust/src/assertions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

use crate::ulm;

pub fn fail(msg: &str) -> ! {
ulm::failWrapper(msg);
}

#[macro_export]
macro_rules! require {
( $cond:expr , $msg:expr ) => {
if ! $cond {
fail($msg);
}
}
}
37 changes: 37 additions & 0 deletions tests/ulm/counter/rust/src/contract.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use std::cell::RefCell;
use std::rc::Rc;

use crate::storage::{SingleChunkStorage, SingleChunkStorageBuilder};
use crate::ulm::Ulm;
use crate::unsigned::U256;

pub struct Contract {
api: Rc<RefCell<dyn Ulm>>
}

impl Contract {
pub fn new(api: Rc<RefCell<dyn Ulm>>) -> Self {
Contract { api }
}

// ---------------------------

fn s_counter<'a>(&self) -> SingleChunkStorage<'a, U256> {
SingleChunkStorageBuilder::new(self.api.clone(), &("counter".to_string())).build()
}

// ---------------------------

pub fn init(&self) {
self.s_counter().set(U256::from_u64(0));
}

pub fn inc_counter(&self) -> bool {
self.s_counter().set(self.s_counter().get() + U256::from_u64(1));
true
}

pub fn get_counter(&self) -> U256 {
self.s_counter().get()
}
}
Loading
Loading