Conversation
ec4d8cb to
c92c16f
Compare
|
@bitwalker @otrho @bobbinth I think I cracked the WIT generation for an account. Here is a brief description of how it works. Please check it out if I'm missing something. Overall, I think it'd work and the DX is quite nice. The user writes only the Rust code like - https://github.com/0xMiden/compiler/blob/681d52ab02f52c1536cc4d30ff89e9d5dfe8c344/examples/basic-wallet/src/lib.rs?plain=1
impl self::bindings::exports::miden::basic_wallet::basic_wallet::Guest for MyAccount {
#[doc = " Adds an asset to the account."]
#[doc = ""]
#[doc = " This function adds the specified asset to the account\'s asset list."]
#[doc = ""]
#[doc = " # Arguments"]
#[doc = " * `asset` - The asset to be added to the account"]
fn receive_asset(asset: Asset) {
let __component_instance = MyAccount::default();
__component_instance.receive_asset(asset);
}
#[doc = " Moves an asset from the account to a note."]
#[doc = ""]
#[doc = " This function removes the specified asset from the account and adds it to"]
#[doc = " the note identified by the given index."]
#[doc = ""]
#[doc = " # Arguments"]
#[doc = " * `asset` - The asset to move from the account to the note"]
#[doc = " * `note_idx` - The index of the note to receive the asset"]
fn move_asset_to_note(asset: Asset, note_idx: NoteIdx) {
let __component_instance = MyAccount::default();
__component_instance.move_asset_to_note(asset, note_idx);
}
fn test_custom_types(
a: self::bindings::exports::miden::basic_wallet::basic_wallet::StructA,
_b: self::bindings::exports::miden::basic_wallet::basic_wallet::EnumA,
) -> self::bindings::exports::miden::basic_wallet::basic_wallet::StructB {
let __component_instance = MyAccount::default();
let a: StructA = (a).into();
let _b: EnumA = (_b).into();
let result = __component_instance.test_custom_types(a, _b);
(result).into()
}
}EDIT: Please ignore the red CI. It's PoC. The one test that matters (tests basic-wallet and P2ID note compilation) is green. |
|
Very cool! This looks great! Regarding the Also, I wonder if at some point in the future, we could also use pub fn receive_asset(&self, asset: Asset) {
self.add_asset(asset);
}The assumption here is that
Assuming we the bindings generator @bitwalker is working on can generate WIT based on type signatures in MASM, I don't think we'll need to write WIT manually. |
Yes, exactly! Like in the storage example - compiler/examples/storage-example/src/lib.rs Lines 47 to 60 in 681d52a self instead of my_account instance.
We can generate it in the macro if we can define what tx kernel functions we want to wrap this way. I don't think asking the user is a suitable option. The DX problem I see here is how to convey to the user what functions the macros add. Alternatively, we can define these wrappers in the trait BaseWallet {
fn add_asset(&mut self, a: Asset) {
account::add_asset(a);
}
}And then a user would simply add |
|
Following up on the discussion elsewhere we need to have an option to disable WIT generation and a way to provide the WIT file(s) to have an escape hatch for edge cases (bring a WIT-defined type and use it in Rust code, etc.) that we cannot support in our WIT generation. |
4e9f81d to
f98c5b6
Compare
I think these would be all functions that are exposed for the "active account" - like getting the account ID, reading account vault, adding assets to the vault etc. (we won't need to function for storage because storage would be accessed through the fields). We could have something like pub trait Account {
fn id(&self) -> AccountId {
miden::account::get_id()
}
...
}And then have the user implement it manually - e.g.: #[component]
struct MyAccount;
impl Account for MyAccount { }But I think it may be better if the
I think this could work too - but I was trying to address a different issue that is not related to the basic wallet: every account component "inherits" functions provided by the transaction kernel, and so, when we are inside the functions of the account component, it would be more natural to say something like |
Works for me. The
Oh, I meant exactly what you described above with the |
30ac789 to
ad85c48
Compare
bitwalker
left a comment
There was a problem hiding this comment.
LGTM, I didn't go crazy deep into the macro code, but this stuff is still in flux and I'm comfortable with what I've seen so far. Nice work!
…`miden:base/core-types`
…in `miden::generate`
…ace in the `impl Guest`
…]` macro instead of explicit conversion between WIT and user types.
…e when user defines the type in a sub-module
…port_type]` macros Move types and methods from the basic-wallet example
…ort!` macro , support nested module in WIT generation.
…e`, `metadata` modules
c99a11d to
ea299d5
Compare
Close #720
Corresponding template repo PR that switches new project templates to the WIT generation: 0xMiden/rust-templates#30
The notes below are put as doc and module comments as well.
How to use it
#[component]on youimpl MyAccountType {.#[export_type]on every defined type that is used in the public(exported) method signature.Example:
Foreseeing the case where a user forgets to put
#[export_type]on their type the friendly error message with a hint is displayed.How it works
#[export_type]collects the type descriptions.#[component]onimplgenerates a WIT interface with all public methods, callswit_bindgen::generate!and implements theGuesttrait.The WIT file is written in a subfolder under the
targetfolder.Escape hatch
In a small fraction of the cases where the WIT generation is not possible (think a type defined only in an external WIT file) or not desirable, the WIT generation can be disabled:
To disable WIT interface generation:
#[component]attribute macro in theimpl MyAccountTypesection;To use the manually crafted WIT interface:
witfolder;miden::generate!();andbindings::export!(MyAccountType);impl Guest for MyAccountType;These steps are described in the doc comments to the
#[component]macro.See the storage-example using this escape hatch and opting out of the WIT generation.
Next steps
enumand noVecandOptionsupport since there is no support for them in the frontend yet. In this PR I implementedenumwithout the data constructors, and it works fine. I'm pretty sure at this point thatVecandOptionare also doable.Tests
The new test module for macros-related tests is created at
rust_sdk::macroswith a test for various shapes of the user-defined types and an account <> note script execution test.