Add AccountComponent::from_package() method#1802
Conversation
greenhat
left a comment
There was a problem hiding this comment.
Looking good! Just a minor note.
| let metadata_bytes = package | ||
| .account_component_metadata_bytes | ||
| .as_deref() | ||
| .expect("no account component metadata present"); |
There was a problem hiding this comment.
Should we return AccountError here instead of panicking?
There was a problem hiding this comment.
replaced the panic with proper error handling by adding a new error variant to the AccountError enum
There was a problem hiding this comment.
If the metadata is optional in the Package, why do we need it? An AccountComponent doesn't require an AccountComponentMetadata, so I think we should consider it optional here.
I don't think we need to create an AccountComponentTemplate here, we can just pass the library and the storage slots to AccountComponent::new.
For the supported types, we can:
- check if metadata is present on the package, if not, default to regular accounts.
- if metadata is present but fails to be deserialized, return
AccountError::other_with_sourceas we do now. - if metadata is present and valid, use the supported types from
AccountComponentMetadata.
Aside: It would be nicer if the mast package was able to contain a valid AccountComponentMetadata so we wouldn't even have to deserialize it. Then the function could be made infallible, but I know there'd be a dependency cycle if we did this :(
There was a problem hiding this comment.
I don't think we need to create an
AccountComponentTemplatehere, we can just pass the library and the storage slots toAccountComponent::new.
Regarding this, it'd still be nice if there were a separate API for instantiating an AccountComponentTemplate. Some of the rationale is explained in this issue (and comment): 0xMiden/miden-client#1132 (comment)
There was a problem hiding this comment.
it'd still be nice if there were a separate API for instantiating an
AccountComponentTemplate(I wish we had a better name for it).
I agree. AccountComponentTemplate is basically a typed version of Package. That is, Package is a generic object that can have some custom metadata, and when we are talking about account components, this custom metadata should be sufficient to describe AccountComponentMetadata. So, ideally, we'd have something like:
impl TryFrom<Package> for AccountComponentTemplate {
...
}A more general question about this PR: under what circumstances would we have the package and have the right storage slots for it? Is the use case here that we get the package by compiling a Rust crate, and then programmatically build Vec<StorageSlot> because we know storage layout that the package is in?
The reason I'm asking is that this is not very "type safe" - i.e., if the package changes, or we specify the wrong package, or make a mistake in building the Vec<StorageSlot> we'll build an invalid account component and we won't get any errors about this until we try to use it.
A safer way would be to instantiate the component using InitStorageData. That is:
- We'd first build
InitStorageDatawhich is basically a key-value map. - Then we convert
PackageintoAccountComponentTemplate. - Then we call
AccountComponent::from_template().
This would throw errors if the provided storage data is incompatible with the package.
The main limitation here is that maybe building InitStorageData is not that convenient or maybe it can't express everything the way we'd want to express it. But in this case, it would be good to figure out how to make this approach more user-friendly. For example, maybe we could have better ways for instantiating InitStorageData (e.g., via macros?), or maybe the internal types should be more flexible (and not be just strings).
PhilippGackstatter
left a comment
There was a problem hiding this comment.
Looks good to me!
I think I'd allow missing metadata. See inline comment.
| let metadata_bytes = package | ||
| .account_component_metadata_bytes | ||
| .as_deref() | ||
| .expect("no account component metadata present"); |
There was a problem hiding this comment.
If the metadata is optional in the Package, why do we need it? An AccountComponent doesn't require an AccountComponentMetadata, so I think we should consider it optional here.
I don't think we need to create an AccountComponentTemplate here, we can just pass the library and the storage slots to AccountComponent::new.
For the supported types, we can:
- check if metadata is present on the package, if not, default to regular accounts.
- if metadata is present but fails to be deserialized, return
AccountError::other_with_sourceas we do now. - if metadata is present and valid, use the supported types from
AccountComponentMetadata.
Aside: It would be nicer if the mast package was able to contain a valid AccountComponentMetadata so we wouldn't even have to deserialize it. Then the function could be made infallible, but I know there'd be a dependency cycle if we did this :(
Co-authored-by: Philipp Gackstatter <PhilippGackstatter@users.noreply.github.com>
| None => { | ||
| // Create default metadata for packages without explicit metadata |
There was a problem hiding this comment.
Question: should we actually do this? If a package does not have account component metadata, it could be a package for something else entirely (e.g., a note or a tx script).
|
@bobbinth In the recent commit I fixed the unsafe default metadata handling in Summary of changes:
All conversions of packages now follow the safe Edit: |
bobbinth
left a comment
There was a problem hiding this comment.
Looks great! Thank you! I left just one small nit inline.
I'm curious how easy this will be to use with the current form of InitStorageData. Currently it is a map that maps a string key to a string value, but maybe one or both of these should change.
For example, the value could be a bit more structured. Right now we keep it as a string because parsing happens when we reconcile it with account template, but it may also be convenient to specify the values as word (or as maps) directly.
Similarly, once we have named storage slots, maybe the keys could also be storage slot names (or at least based on storage slot names).
Let's create an issue for this.
Opened an issue here: #1860 Is there anything outstanding on this PR? |
|
@greenhat - could you take another look? I think this should be good to merge. |
This PR adds a useful method to the
AccountComponenttype that allows creating account components directly frommiden-mast-package::Packageinstances.This enables easier integration with the Miden compiler toolchain by providing a direct path from compiled packages to account components.
Changes
AccountComponent::from_package()method that extracts metadata and library from a packagemiden-mast-packagedependency (v0.17.0) to workspacefrom_package()method