Skip to content

Commit

Permalink
Merge pull request #170 from 0xPolygonMiden/greenhat/i159-tx-kernel-f…
Browse files Browse the repository at this point in the history
…unc-11apr

[5/x] Add bindings to `remove_asset` and `create_note` Miden SDK `tx-kernel` functions
  • Loading branch information
bitwalker authored May 1, 2024
2 parents 4f842b1 + 120d55a commit c053173
Show file tree
Hide file tree
Showing 11 changed files with 810 additions and 249 deletions.
8 changes: 5 additions & 3 deletions frontend-wasm/src/miden_abi/transform.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,11 @@ enum TransformStrategy {
/// Get the transformation strategy for a function name
fn get_transform_strategy(function_id: &str) -> TransformStrategy {
match function_id {
tx_kernel::NOTE_GET_INPUTS => TransformStrategy::ListReturn,
tx_kernel::ACCOUNT_ADD_ASSET => TransformStrategy::ReturnViaPointer,
tx_kernel::ACCOUNT_GET_ID => TransformStrategy::NoTransform,
tx_kernel::note::GET_INPUTS => TransformStrategy::ListReturn,
tx_kernel::account::ADD_ASSET => TransformStrategy::ReturnViaPointer,
tx_kernel::account::REMOVE_ASSET => TransformStrategy::ReturnViaPointer,
tx_kernel::account::GET_ID => TransformStrategy::NoTransform,
tx_kernel::tx::CREATE_NOTE => TransformStrategy::NoTransform,
stdlib::crypto::hashes::BLAKE3_HASH_1TO1 => TransformStrategy::ReturnViaPointer,
stdlib::crypto::hashes::BLAKE3_HASH_2TO1 => TransformStrategy::ReturnViaPointer,
stdlib::crypto::dsa::RPO_FALCON512_VERIFY => TransformStrategy::NoTransform,
Expand Down
33 changes: 7 additions & 26 deletions frontend-wasm/src/miden_abi/tx_kernel.rs
Original file line number Diff line number Diff line change
@@ -1,39 +1,20 @@
//! Function types and lowering for tx kernel API functions
#![allow(missing_docs)]

use std::sync::OnceLock;
pub(crate) mod account;
pub(crate) mod note;
pub(crate) mod tx;

use miden_hir::FunctionType;
use miden_hir_type::Type::*;
use std::sync::OnceLock;

use super::ModuleFunctionTypeMap;
use crate::miden_abi::FunctionTypeMap;

pub const NOTE_MODULE_NAME: &str = "miden:tx_kernel/note";
pub const NOTE_GET_INPUTS: &str = "get_inputs";

pub const ACCOUNT_MODULE_NAME: &str = "miden:tx_kernel/account";
pub const ACCOUNT_ADD_ASSET: &str = "add_asset";
pub const ACCOUNT_GET_ID: &str = "get_id";

pub(crate) fn signatures() -> &'static ModuleFunctionTypeMap {
static TYPES: OnceLock<ModuleFunctionTypeMap> = OnceLock::new();
TYPES.get_or_init(|| {
let mut m: ModuleFunctionTypeMap = Default::default();

let mut note: FunctionTypeMap = Default::default();
note.insert(NOTE_GET_INPUTS, FunctionType::new([Felt], [I32, Felt]));
m.insert(NOTE_MODULE_NAME, note);

let mut account: FunctionTypeMap = Default::default();
account.insert(
ACCOUNT_ADD_ASSET,
// Accepts and returns word
FunctionType::new([Felt, Felt, Felt, Felt], [Felt, Felt, Felt, Felt]),
);
account.insert(ACCOUNT_GET_ID, FunctionType::new([], [Felt]));
m.insert(ACCOUNT_MODULE_NAME, account);

m.extend(account::signatures());
m.extend(note::signatures());
m.extend(tx::signatures());
m
})
}
22 changes: 22 additions & 0 deletions frontend-wasm/src/miden_abi/tx_kernel/account.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use miden_hir::FunctionType;
use miden_hir_type::Type::*;

use crate::miden_abi::{FunctionTypeMap, ModuleFunctionTypeMap};

pub const ADD_ASSET: &str = "add_asset";
pub const REMOVE_ASSET: &str = "remove_asset";
pub const GET_ID: &str = "get_id";

pub(crate) fn signatures() -> ModuleFunctionTypeMap {
let mut m: ModuleFunctionTypeMap = Default::default();
let mut account: FunctionTypeMap = Default::default();
account
.insert(ADD_ASSET, FunctionType::new([Felt, Felt, Felt, Felt], [Felt, Felt, Felt, Felt]));
account.insert(
REMOVE_ASSET,
FunctionType::new([Felt, Felt, Felt, Felt], [Felt, Felt, Felt, Felt]),
);
account.insert(GET_ID, FunctionType::new([], [Felt]));
m.insert("miden:tx_kernel/account", account);
m
}
14 changes: 14 additions & 0 deletions frontend-wasm/src/miden_abi/tx_kernel/note.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use miden_hir::FunctionType;
use miden_hir_type::Type::*;

use crate::miden_abi::{FunctionTypeMap, ModuleFunctionTypeMap};

pub const GET_INPUTS: &str = "get_inputs";

pub(crate) fn signatures() -> ModuleFunctionTypeMap {
let mut m: ModuleFunctionTypeMap = Default::default();
let mut note: FunctionTypeMap = Default::default();
note.insert(GET_INPUTS, FunctionType::new([Felt], [I32, Felt]));
m.insert("miden:tx_kernel/note", note);
m
}
17 changes: 17 additions & 0 deletions frontend-wasm/src/miden_abi/tx_kernel/tx.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
use miden_hir::FunctionType;
use miden_hir_type::Type::*;

use crate::miden_abi::{FunctionTypeMap, ModuleFunctionTypeMap};

pub const CREATE_NOTE: &str = "create_note";

pub(crate) fn signatures() -> ModuleFunctionTypeMap {
let mut m: ModuleFunctionTypeMap = Default::default();
let mut note: FunctionTypeMap = Default::default();
note.insert(
CREATE_NOTE,
FunctionType::new([Felt, Felt, Felt, Felt, Felt, Felt, Felt, Felt, Felt, Felt], [Felt]),
);
m.insert("miden:tx_kernel/tx", note);
m
}
36 changes: 36 additions & 0 deletions sdk/tx-kernel/src/externs.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use miden_prelude::Felt;

use crate::{AccountId, CoreAsset, NoteId, NoteType, Tag};

#[link(wasm_import_module = "miden:tx_kernel/account")]
extern "C" {
#[link_name = "get_id<0x0000000000000000000000000000000000000000000000000000000000000000>"]
pub fn extern_account_get_id() -> AccountId;
#[link_name = "add_asset<0x0000000000000000000000000000000000000000000000000000000000000000>"]
pub fn extern_account_add_asset(_: Felt, _: Felt, _: Felt, _: Felt, ptr: *mut CoreAsset);
#[link_name = "remove_asset<0x0000000000000000000000000000000000000000000000000000000000000000>"]
pub fn extern_account_remove_asset(_: Felt, _: Felt, _: Felt, _: Felt, ptr: *mut CoreAsset);
}

#[link(wasm_import_module = "miden:tx_kernel/note")]
extern "C" {
#[link_name = "get_inputs<0x0000000000000000000000000000000000000000000000000000000000000000>"]
pub fn extern_note_get_inputs(ptr: *mut Felt) -> usize;
}

#[link(wasm_import_module = "miden:tx_kernel/tx")]
extern "C" {
#[link_name = "create_note<0x0000000000000000000000000000000000000000000000000000000000000000>"]
pub fn extern_tx_create_note(
asset_f0: Felt,
asset_f1: Felt,
asset_f2: Felt,
asset_f3: Felt,
tag: Tag,
note_type: NoteType,
recipient_f0: Felt,
recipient_f1: Felt,
recipient_f2: Felt,
recipient_f3: Felt,
) -> NoteId;
}
140 changes: 79 additions & 61 deletions sdk/tx-kernel/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,84 +1,77 @@
#![no_std]
#![allow(dead_code)]

extern crate alloc;

use alloc::vec::Vec;
mod externs;
use externs::*;

use miden_prelude::{Felt, Word};
mod types;
pub use types::*;

#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct AccountId(Felt);

impl From<AccountId> for Felt {
fn from(account_id: AccountId) -> Felt {
account_id.0
}
}
extern crate alloc;

#[link(wasm_import_module = "miden:tx_kernel/account")]
extern "C" {
#[link_name = "get_id<0x0000000000000000000000000000000000000000000000000000000000000000>"]
fn extern_account_get_id() -> AccountId;
#[link_name = "add_asset<0x0000000000000000000000000000000000000000000000000000000000000000>"]
fn extern_account_add_asset(_: Felt, _: Felt, _: Felt, _: Felt, ptr: *mut CoreAsset);
}
use alloc::vec::Vec;

#[link(wasm_import_module = "miden:tx_kernel/note")]
extern "C" {
#[link_name = "get_inputs<0x0000000000000000000000000000000000000000000000000000000000000000>"]
fn extern_note_get_inputs(ptr: *mut Felt) -> usize;
}
use miden_prelude::Felt;

#[inline(always)]
/// Get the account ID of the currently executing note account.
pub fn get_id() -> AccountId {
unsafe { extern_account_get_id() }
}

const MAX_INPUTS: usize = 256;

#[inline(always)]
/// Get the inputs of the currently executing note.
pub fn get_inputs() -> Vec<Felt> {
// The MASM for this function is here:
// https://github.com/0xPolygonMiden/miden-base/blob/3cbe8d59dcf4ccc9c380b7c8417ac6178fc6b86a/miden-lib/asm/miden/note.masm#L69-L102
// #! Writes the inputs of the currently execute note into memory starting at the specified
// address. #!
// #! Inputs: [dest_ptr]
// #! Outputs: [num_inputs, dest_ptr]
// #!
// #! - dest_ptr is the memory address to write the inputs.
unsafe {
#[repr(transparent)]
struct RetArea([Felt; MAX_INPUTS]);
let mut ret_area = ::core::mem::MaybeUninit::<RetArea>::uninit();
let ptr = ret_area.as_mut_ptr();
let num_inputs = extern_note_get_inputs(ptr as *mut Felt);
// Compiler generated adapter function will drop the returned dest_ptr
const MAX_INPUTS: usize = 256;
let mut inputs: Vec<Felt> = Vec::with_capacity(MAX_INPUTS);
let num_inputs = unsafe {
// The MASM for this function is here:
// https://github.com/0xPolygonMiden/miden-base/blob/3cbe8d59dcf4ccc9c380b7c8417ac6178fc6b86a/miden-lib/asm/miden/note.masm#L69-L102
// #! Writes the inputs of the currently execute note into memory starting at the specified
// address. #!
// #! Inputs: [dest_ptr]
// #! Outputs: [num_inputs, dest_ptr]
// #!
// #! - dest_ptr is the memory address to write the inputs.
// Compiler generated adapter code at call site will drop the returned dest_ptr
// and return the number of inputs
Vec::from_raw_parts(ptr as *mut Felt, num_inputs, num_inputs)
}
extern_note_get_inputs(inputs.as_mut_ptr())
};
inputs.truncate(num_inputs);
inputs
}

#[repr(transparent)]
pub struct CoreAsset {
inner: Word,
}

impl CoreAsset {
pub fn new(word: Word) -> Self {
CoreAsset { inner: word }
}

pub fn as_word(&self) -> Word {
self.inner
/// Add the specified asset to the vault.
/// Returns the final asset in the account vault defined as follows: If asset is
/// a non-fungible asset, then returns the same as asset. If asset is a
/// fungible asset, then returns the total fungible asset in the account
/// vault after asset was added to it.
///
/// Panics:
/// - If the asset is not valid.
/// - If the total value of two fungible assets is greater than or equal to 2^63.
/// - If the vault already contains the same non-fungible asset.
pub fn add_asset(asset: CoreAsset) -> CoreAsset {
unsafe {
let mut ret_area = ::core::mem::MaybeUninit::<CoreAsset>::uninit();
extern_account_add_asset(
asset.inner[0],
asset.inner[1],
asset.inner[2],
asset.inner[3],
ret_area.as_mut_ptr(),
);
ret_area.assume_init()
}
}

pub fn add_assets(asset: CoreAsset) -> CoreAsset {
/// Remove the specified asset from the vault.
///
/// Panics:
/// - The fungible asset is not found in the vault.
/// - The amount of the fungible asset in the vault is less than the amount to be removed.
/// - The non-fungible asset is not found in the vault.
pub fn remove_asset(asset: CoreAsset) -> CoreAsset {
unsafe {
let mut ret_area = ::core::mem::MaybeUninit::<CoreAsset>::uninit();
extern_account_add_asset(
extern_account_remove_asset(
asset.inner[0],
asset.inner[1],
asset.inner[2],
Expand All @@ -88,3 +81,28 @@ pub fn add_assets(asset: CoreAsset) -> CoreAsset {
ret_area.assume_init()
}
}

/// Creates a new note. asset is the asset to be included in the note. tag is
/// the tag to be included in the note. recipient is the recipient of the note.
/// Returns the id of the created note.
pub fn create_note(
asset: CoreAsset,
tag: Tag,
note_type: NoteType,
recipient: Recipient,
) -> NoteId {
unsafe {
extern_tx_create_note(
asset.inner[0],
asset.inner[1],
asset.inner[2],
asset.inner[3],
tag,
note_type,
recipient.0[0],
recipient.0[1],
recipient.0[2],
recipient.0[3],
)
}
}
38 changes: 38 additions & 0 deletions sdk/tx-kernel/src/types.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use miden_prelude::{Felt, Word};

#[repr(transparent)]
#[derive(Copy, Clone)]
pub struct AccountId(Felt);

impl From<AccountId> for Felt {
fn from(account_id: AccountId) -> Felt {
account_id.0
}
}

#[repr(transparent)]
pub struct CoreAsset {
pub(crate) inner: Word,
}

impl CoreAsset {
pub fn new(word: Word) -> Self {
CoreAsset { inner: word }
}

pub fn as_word(&self) -> Word {
self.inner
}
}

#[repr(transparent)]
pub struct Recipient(pub(crate) Word);

#[repr(transparent)]
pub struct Tag(pub(crate) Felt);

#[repr(transparent)]
pub struct NoteId(pub(crate) Felt);

#[repr(transparent)]
pub struct NoteType(pub(crate) Felt);
Loading

0 comments on commit c053173

Please sign in to comment.