Skip to content

Add examples/counter-contract and expose incr_nonce in the Miden SDK #492

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

Open
wants to merge 8 commits into
base: i431-acc-storage-high
Choose a base branch
from
Open
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
1,791 changes: 1,791 additions & 0 deletions examples/counter-contract/Cargo.lock

Large diffs are not rendered by default.

45 changes: 45 additions & 0 deletions examples/counter-contract/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[package]
name = "counter-contract"
description = "A simple example of a Miden counter contract using the Account Storage API"
version = "0.1.0"
edition = "2021"

[lib]
# Build this crate as a self-contained, C-style dynamic library
# This is required to emit the proper Wasm module type
crate-type = ["cdylib"]

[dependencies]
miden = { path = "../../sdk/sdk" }
wit-bindgen-rt = "0.28"

[package.metadata.component]
package = "miden:counter-contract"

[package.metadata.miden]
supported-types = ["RegularAccountUpdatableCode"]

[package.metadata.component.target.dependencies]
"miden:base" = { path = "../../tests/rust-apps-wasm/rust-sdk/wit-sdk/miden.wit" }
"miden:core-import" = { path = "../../tests/rust-apps-wasm/rust-sdk/wit-sdk/miden-core-import.wit" }


[profile.release]
# optimize the output for size
opt-level = "z"
# Explicitly disable panic infrastructure on Wasm, as
# there is no proper support for them anyway, and it
# ensures that panics do not pull in a bunch of standard
# library code unintentionally
panic = "abort"

[profile.dev]
# Explicitly disable panic infrastructure on Wasm, as
# there is no proper support for them anyway, and it
# ensures that panics do not pull in a bunch of standard
# library code unintentionally
panic = "abort"
opt-level = 1
debug-assertions = true
overflow-checks = false
debug = true
7 changes: 7 additions & 0 deletions examples/counter-contract/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Counter Contract

## Build

```bash
cargo miden build --release
```
63 changes: 63 additions & 0 deletions examples/counter-contract/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// Do not link against libstd (i.e. anything defined in `std::`)
#![no_std]

// However, we could still use some standard library types while
// remaining no-std compatible, if we uncommented the following lines:
//
extern crate alloc;

// Global allocator to use heap memory in no-std environment
#[global_allocator]
static ALLOC: miden::BumpAlloc = miden::BumpAlloc::new();

// Define a panic handler as required by the `no_std` environment
#[cfg(not(test))]
#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
// For now, just loop indefinitely
loop {}
}

mod bindings;

use bindings::exports::miden::counter_contract::counter::Guest;
use miden::{account, component, felt, Felt, StorageMap, StorageMapAccess, Word};

/// Main contract structure for the counter example.
#[component]
struct CounterContract {
/// Storage map holding the counter value.
#[storage(slot(0), description = "counter contract storage map")]
count_map: StorageMap,
}

bindings::export!(CounterContract with_types_in bindings);

impl Guest for CounterContract {
/// Returns the current counter value stored in the contract's storage map.
fn get_count() -> Felt {
// Get the instance of the contract
let contract = CounterContract::default();
// Define a fixed key for the counter value within the map
let key = Word::from([felt!(0); 4]);
// Read the value associated with the key from the storage map
contract.count_map.get(&key)
}

/// Increments the counter value stored in the contract's storage map by one.
fn increment_count() -> Felt {
// Get the instance of the contract
let contract = CounterContract::default();
// Define the same fixed key
let key = Word::from([felt!(0); 4]);
// Read the current value
let current_value: Felt = contract.count_map.get(&key);
// Increment the value by one
let new_value = current_value + felt!(1);
// Write the new value back to the storage map
contract.count_map.set(key, new_value);
// Increment the nonce of this Miden account
account::incr_nonce(1);
new_value
}
}
19 changes: 19 additions & 0 deletions examples/counter-contract/wit/counter.wit
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package miden:[email protected];

use miden:base/[email protected];

interface counter {
use core-types.{felt};

/// Returns the current counter value stored in the contract's storage.
get-count: func() -> felt;
/// Increments the counter value stored in the contract's storage by one
//and return the new counter value
increment-count: func() -> felt;
}

world counter-world {
include miden:core-import/[email protected];

export counter;
}
4 changes: 3 additions & 1 deletion frontend/wasm/src/miden_abi/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,9 @@ fn get_transform_strategy(path: &SymbolPath) -> Option<TransformStrategy> {
symbols::Miden => match components.next()?.as_symbol_name() {
symbols::Account => {
match components.next_if(|c| c.is_leaf())?.as_symbol_name().as_str() {
tx_kernel::account::GET_ID => Some(TransformStrategy::NoTransform),
tx_kernel::account::GET_ID | tx_kernel::account::INCR_NONCE => {
Some(TransformStrategy::NoTransform)
}
tx_kernel::account::ADD_ASSET
| tx_kernel::account::REMOVE_ASSET
| tx_kernel::account::GET_STORAGE_ITEM
Expand Down
2 changes: 2 additions & 0 deletions frontend/wasm/src/miden_abi/tx_kernel/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ pub const GET_STORAGE_ITEM: &str = "get_item";
pub const SET_STORAGE_ITEM: &str = "set_item";
pub const GET_STORAGE_MAP_ITEM: &str = "get_map_item";
pub const SET_STORAGE_MAP_ITEM: &str = "set_map_item";
pub const INCR_NONCE: &str = "incr_nonce";

pub(crate) fn signatures() -> ModuleFunctionTypeMap {
let mut m: ModuleFunctionTypeMap = Default::default();
Expand Down Expand Up @@ -57,6 +58,7 @@ pub(crate) fn signatures() -> ModuleFunctionTypeMap {
[Felt, Felt, Felt, Felt, Felt, Felt, Felt, Felt],
),
);
account.insert(Symbol::from(INCR_NONCE), FunctionType::new(CallConv::Wasm, [I32], []));
m.insert(SymbolPath::from_iter(MODULE_PREFIX.iter().copied()), account);
m
}
5 changes: 5 additions & 0 deletions sdk/base-sys/masm/miden/account.masm
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,8 @@ export.set_map_item
end


export.incr_nonce
push.1
assertz
end

12 changes: 12 additions & 0 deletions sdk/base-sys/src/bindings/account.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ extern "C" {
pub fn extern_account_add_asset(_: Felt, _: Felt, _: Felt, _: Felt, ptr: *mut CoreAsset);
#[link_name = "remove-asset"]
pub fn extern_account_remove_asset(_: Felt, _: Felt, _: Felt, _: Felt, ptr: *mut CoreAsset);
#[link_name = "incr-nonce"]
pub fn extern_account_incr_nonce(value: i32);
}

/// Get the account ID of the currently executing note account.
Expand Down Expand Up @@ -61,3 +63,13 @@ pub fn remove_asset(asset: CoreAsset) -> CoreAsset {
ret_area.assume_init()
}
}

/// Increments the account nonce by the provided value.
///
/// Panics:
/// - If the underlying kernel procedure panics.
pub fn incr_nonce(value: u32) {
unsafe {
extern_account_incr_nonce(value as i32);
}
}
Loading