-
Notifications
You must be signed in to change notification settings - Fork 42
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 AccountComponent
s
#941
base: next
Are you sure you want to change the base?
Conversation
There was a problem hiding this 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.
// TODO Document everything, add section separators. | ||
#[derive(Debug, Clone, PartialEq, Eq)] | ||
pub struct AccountComponent { | ||
pub(crate) code: Library, | ||
pub(crate) storage_slots: Vec<StorageSlot>, | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not for this PR, but one thing that may be good to add here is a filed which specifies whether the component is valid for all accounts or only for special type of accounts (e.g., a fungible faucet). This way, we can prevent errors when trying to add non-faucet components to faucets etc.
Let's create an issue for this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
On the other hand, if it is not too difficult, we may consider doing it in this PR as it may simplify account construction as mentioned in #941 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I added an AccountComponentType::{Faucet, Any}
now to address this. I'm not sure if Any
is correct or sufficient though. Some components like authentication can be added to any account, so it seems correct to have it there. But maybe a third category like Regular
(or something more descriptive) is needed for things like BasicWallet
?
Then any account instantiated from multiple components would fail if any Faucet
and Regular
components are mixed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another way to do this could be to use a BTreeSet<AccountType>
and explicitly specify the types of account a component can be applied to. Then, we can have convenience methods like is_valid_for(account_type)
and is_only_for_faucet()
.
objects/src/accounts/code/mod.rs
Outdated
// TODO: Document. | ||
pub fn from_components( | ||
components: &[AccountComponent], | ||
account_type: AccountType, | ||
) -> Result<Self, AccountError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once everything is ready, this will replace AccountCode::new()
, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it's replaced almost everywhere now, only internal references left to cleanup 👍
component_storage_offset = component_storage_offset.checked_add(component_storage_size) | ||
.expect("account procedure info constructor should return an error if the addition overflows"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We also need to check that the offset does not exceed 255 (I believe) as this is the maximum number of storage slots per account.
objects/src/accounts/mod.rs
Outdated
// TODO: Document. | ||
pub fn from_components( | ||
seed: Word, | ||
account_type: AccountType, | ||
components: &[AccountComponent], | ||
) -> Result<Self, AccountError> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will replace Account::new()
right?
Also, a couple of thoughts:
- If we have a way to infer account type from the underlying components (i.e., if it is a faucet or not), we can avoid passing it as a parameter.
- If we do pass account type as a parameter, we need to add a check to make sure the generated ID matches this type.
objects/src/accounts/storage/mod.rs
Outdated
// TODO Document. | ||
pub fn from_components( | ||
components: &[AccountComponent], | ||
) -> Result<AccountStorage, AccountError> { | ||
let storage_slots = components | ||
.iter() | ||
.flat_map(|component| component.storage_slots()) | ||
.cloned() | ||
.collect(); | ||
|
||
Self::new(storage_slots) | ||
} | ||
|
||
pub fn from_components_with_faucet_metadata( | ||
components: &[AccountComponent], | ||
faucet_metadata: Word, | ||
) -> Result<AccountStorage, AccountError> { | ||
let mut storage_slots = vec![StorageSlot::Value(faucet_metadata)]; | ||
storage_slots | ||
.extend(components.iter().flat_map(|component| component.storage_slots()).cloned()); | ||
|
||
Self::new(storage_slots) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Potentially, I'd move this logic into the account constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I agree that would be nice, but given the dependence of the AccountId on the code and storage, I don't know how we could efficiently rewrite places like these:
miden-base/miden-lib/src/accounts/faucets/mod.rs
Lines 105 to 116 in 4cf0185
let account_code = AccountCode::from_components(&components)?; | |
let account_storage = AccountStorage::from_components(&components)?; | |
let account_seed = AccountId::get_account_seed( | |
init_seed, | |
AccountType::FungibleFaucet, | |
account_storage_mode, | |
account_code.commitment(), | |
account_storage.commitment(), | |
)?; | |
let account = Account::new(account_seed, account_code, account_storage)?; |
We can of course call Account::from_components
on the same components again, but that will redo work we've just done (including MastForest::merge
which is expensive).
4cf0185
to
7422e80
Compare
TODO
closes #935