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

Implement AccountComponents #941

Merged
merged 44 commits into from
Nov 4, 2024
Merged

Implement AccountComponents #941

merged 44 commits into from
Nov 4, 2024

Conversation

PhilippGackstatter
Copy link
Contributor

@PhilippGackstatter PhilippGackstatter commented Oct 29, 2024

Description

This PR implements AccountComponents. An AccountComponent defines a Library of code and the initial value and types of the StorageSlots it accesses.

One or more components can be used to built AccountCode and AccountStorage.

Each component is independent of other components and can only access its own storage slots. Each component defines its own storage layout starting at index 0 up to the length of the storage slots vector.

Components define the AccountTypes they support, meaning whether the component can be used to instantiate an account of that type. For example, a component implementing a fungible faucet would only specify support for AccountType::FungibleFaucet. Using it to instantiate a regular account would fail. By default, the set of supported types is empty, so each component is forced to explicitly define what it supports.

The PR implements three pre-defined components:

  • BasicWallet,
  • RpoFalcon512,
  • BasicFungibleFaucet.

These can be combined to build an account from components. Typical usage would look like this:

let (account_code, account_storage) = Account::initialize_from_components(
    AccountType::RegularAccountUpdatableCode,
    &[RpoFalcon512::new(pub_key).into(), BasicWallet.into()],
)?;

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

let account = Account::new(account_seed, account_code, account_storage)?;

Other Noteworthy Changes

  • Remove if statement in validate_procedure_metadata and consistently implement the rule that procedures that do not access storage have offset and size set to 0 (for faucets this was (1, 1) previously).
  • Remove AccountCode::{compile, new} as it should typically be instantiated using Account::initialize_from_components or AccountCode::from_components as a fallback.
  • Renames "default account code" to basic authenticated wallet, as that seems more descriptive.
  • Most mocked AccountCode was replaced with components, often AccountMockComponent.
  • Technically it would be correct to implement the num procedures == 0 or > 256 check in AccountComponent::new, but it seems convenient to not do this and only do it in AccountCode::from_components for two reasons:
    • We might want to have a component with an empty library but some storage slots in testing code to force a certain storage offset and size combination.
    • There is no need to unwrap/expect when impl From<MyComponent> for AccountComponent since AccountComponent::new is infallible.

closes #935

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! Not a review, but I took a quick look and left some comments inline.

@PhilippGackstatter PhilippGackstatter force-pushed the pgackst-account-components branch from 4cf0185 to 7422e80 Compare October 30, 2024 15:53
Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you. I left some comment inline. The two main things are:

  • There seems to be some mixing of test and non-test code going on. We should separate the two so that we retain full functionality when the testing feature is not on.
  • I'm not sure we need the AccountComponent trait. But maybe there is a good reason for it.

@PhilippGackstatter PhilippGackstatter marked this pull request as ready for review October 31, 2024 16:05
@PhilippGackstatter PhilippGackstatter force-pushed the pgackst-account-components branch from 904fbba to bdb5fa9 Compare October 31, 2024 16:49
Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you! Looks good! I reviewed all non-test code (and some test code as well), and left some comments inline.

Overall, I think we are close to merging this. Some issues I bring up (e.g., refactoring Account constructors and/or introducing non-test AccountBuilder) is something we can address in a follow-up PR.

@PhilippGackstatter PhilippGackstatter force-pushed the pgackst-account-components branch 2 times, most recently from 5b77f61 to d73813d Compare November 1, 2024 18:54
@PhilippGackstatter
Copy link
Contributor Author

@bobbinth I addressed all your comments now and am creating new issues for the leftover tasks.

Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! Thank you! I left just a few small comments inline.

Before merging this, @igamigo could you take a look what changes we need to make on the client side to make sure the client does not break?

Comment on lines +758 to +761
// TODO: Temporary fix: Build a native account that has the same code commitment as the foreign
// account which is required for this test to pass right now.
let native_account_id =
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this still applicable? I thought it should be already fixed. cc @Fumuran

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just rebased onto latest next and it still fails for me with the previous code because the foreign account's code isn't being loaded:

--- STDERR:              miden-tx tests::kernel_tests::test_tx::test_load_foreign_account_twice ---
thread 'tests::kernel_tests::test_tx::test_load_foreign_account_twice' panicked at miden-tx/src/tests/kernel_tests/test_tx.rs:912:50:
called `Result::unwrap()` on an `Err` value: EventError("Code commitment 0xb9ee787ee40cfeef9b0b89046122bd0620a9bc309630277906c581da36ddd7c6 is not in the advice provider")
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

If I understood @Fumuran correctly, we don't currently have a way to load foreign accounts in the TransactionContext which is the problem here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we don't currently have a way to load foreign accounts in the TransactionContext which is the problem here

Exactly. The problem is that we can't provide the mast forest of the foreign account's procedures, so we can get the procedure indexes map value, and can't execute the foreign procedure itself. For that purpose we have a load_account_code() procedure in the TransactionExecutor, but we don't have anything similar for the TransactionContext (by the way, should we implement such procedure for it?).
In the new version of the tests I will use the TransactionExecutor instead of TransactionContext, so this won't be a problem in future.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It sounds easiest to just use the TransactionExecutor then in the new tests if it already has the account loading functionality require for this.

Comment on lines +844 to +847
// TODO: Temporary fix: Build a native account that has the same code commitment as the foreign
// account which is required for this test to pass right now.
let native_account_id =
AccountId::try_from(ACCOUNT_ID_REGULAR_ACCOUNT_UPDATABLE_CODE_ON_CHAIN).unwrap();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same comment as above.

@PhilippGackstatter PhilippGackstatter force-pushed the pgackst-account-components branch from e9d29c4 to ba15a7a Compare November 4, 2024 09:24
@PhilippGackstatter PhilippGackstatter linked an issue Nov 4, 2024 that may be closed by this pull request
Copy link
Contributor

@bobbinth bobbinth left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All looks good! Thank you!

@bobbinth bobbinth merged commit 4f3aad4 into next Nov 4, 2024
8 checks passed
@bobbinth bobbinth deleted the pgackst-account-components branch November 4, 2024 19:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Instantiate accounts from account components
4 participants