0xPolygonMiden / miden-base

Core components of the Polygon Miden rollup
MIT License
68 stars 42 forks source link

Add `create_wallet_with_custom_code` wallet helper function in miden-lib #766

Open partylikeits1983 opened 3 months ago

partylikeits1983 commented 3 months ago

Feature description

Adding a create_wallet_with_custom_code function would make it easier to create wallets with custom code when using the miden-client.

I propose adding a function in miden-lib/src/accounts/wallets/mod.rs that allows to pass in custom logic when creating a wallet. This function is pretty much a copy of create_basic_wallet but allows to pass in custom masm code when creating the wallet:

pub fn create_wallet_with_custom_code(
    init_seed: [u8; 32],
    auth_scheme: AuthScheme,
    account_type: AccountType,
    account_storage_type: AccountStorageType,
    custom_code: String,
) -> Result<(Account, Word), AccountError> {
    if matches!(account_type, AccountType::FungibleFaucet | AccountType::NonFungibleFaucet) {
        return Err(AccountError::AccountIdInvalidFieldElement(
            "Basic wallet accounts cannot have a faucet account type".to_string(),
        ));
    }

    let (auth_scheme_procedure, storage_slot_0_data): (&str, Word) = match auth_scheme {
        AuthScheme::RpoFalcon512 { pub_key } => ("basic::auth_tx_rpo_falcon512", pub_key.into()),
    };

    let account_code_string: String = format!(
        "
        {custom_code}

        export.{auth_scheme_procedure}
    "
    );
    let account_code_src: &str = &account_code_string;

    let account_code_ast = ModuleAst::parse(account_code_src)
        .map_err(|e| AccountError::AccountCodeAssemblerError(e.into()))?;
    let account_assembler = TransactionKernel::assembler();
    let account_code = AccountCode::new(account_code_ast.clone(), &account_assembler)?;

    let account_storage =
        AccountStorage::new(vec![SlotItem::new_value(0, 0, storage_slot_0_data)], BTreeMap::new())?;

    let account_seed = AccountId::get_account_seed(
        init_seed,
        account_type,
        account_storage_type,
        account_code.root(),
        account_storage.root(),
    )?;

    Ok((Account::new(account_seed, account_code, account_storage)?, account_seed))
}

Why is this feature needed?

Makes it easier to create wallets with custom logic when using Miden client.

partylikeits1983 commented 3 months ago

The PR: https://github.com/0xPolygonMiden/miden-base/pull/767

Dominik1999 commented 3 months ago

this is related https://github.com/0xPolygonMiden/miden-base/issues/550

The problem is storage and the reserved dataslots. However, I don't see why we can't merge a workaround until we have the correct package format

bobbinth commented 3 months ago

If not critical, I'd prefer not to merge this as we should have a more general solution to accounts with custom code relatively soon (i.e., within the next month or so).

partylikeits1983 commented 3 months ago

If not critical, I'd prefer not to merge this as we should have a more general solution to accounts with custom code relatively soon (i.e., within the next month or so).

Ok no worries. The partially fillable swap note for the order book note is working and has been extensively tested using mock-datastore.

Is there a way to deploy a custom account to the miden localhost instance? I just need two extra "read-only" procedures in addition to the default account code, get_balance and get_id.

I want to deploy to miden-node this account:

use.miden::contracts::wallets::basic->basic_wallet
use.miden::contracts::auth::basic->basic_eoa
use.miden::account

export.basic_wallet::receive_asset
export.basic_wallet::send_asset
export.basic_eoa::auth_tx_rpo_falcon512

export.account::get_balance
export.account::get_id
bobbinth commented 3 months ago

Is there a way to deploy a custom account to the miden localhost instance? I just need two extra "read-only" procedures in addition to the default account code, get_balance and get_id.

The only way to do that is to create an account programmatically (e.g., instantiate the Account struct with the code you'd like), the serialize it into .mac file (via the AccountData struct), and then import the .mac file in the client using the import command.

I think given the code you have above, instantiating AccountData struct and serializing it should be relatively straight-forward.