Skip to content

refactor: enforce component metadata in account component#2373

Merged
bobbinth merged 14 commits intonextfrom
igamigo-enforce-metadata
Feb 6, 2026
Merged

refactor: enforce component metadata in account component#2373
bobbinth merged 14 commits intonextfrom
igamigo-enforce-metadata

Conversation

@igamigo
Copy link
Copy Markdown
Collaborator

@igamigo igamigo commented Jan 30, 2026

Closes #2297

This PR:

  • Makes AccountComponentMetadata a required parameter in AccountComponent::new(), enforcing that all components have metadata (also adds them to the standard components)
  • Removes supported_types from AccountComponent struct - now delegated to metadata.supported_types()
  • Simplifies AccountComponentMetadata::new() to only require a name, with sensible defaults (empty description, version 0.1.0, empty supported types, empty storage schema); adds mutators for simplicity
  • Changes AccountSchemaCommitment::new() to return AccountError instead of AccountComponentTemplateError
  • Validates that the metadata's storage schema is consistent with the component's actual storage slots during construction. For now, I've made it so metadata can be a subset of the specified account component storage slots.

Error rename was pushed to a different PR: #2395

@igamigo igamigo force-pushed the igamigo-enforce-metadata branch 2 times, most recently from f579a7d to 021d423 Compare February 3, 2026 20:08
@igamigo igamigo force-pushed the igamigo-enforce-metadata branch from 53c8f94 to 7358008 Compare February 3, 2026 20:11
storage_schema,
name: name.into(),
description: String::new(),
version: Version::new(0, 1, 0),
Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

This may be better suited to be a parameter of AccountComponentMetadata::new instead

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe defaulting to 1.0 would be a better approach? Most components will be shipped as that stable version for the first time so it seems it would be the best default. For V2, V3, ... we can then overwrite explicitly.

Where do we actually display or use this version?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I changed it to 1.0. I don't think this gets explicitly used other than just being there for metadata purposes right now.

@igamigo igamigo marked this pull request as ready for review February 3, 2026 20:25
@igamigo igamigo requested review from PhilippGackstatter and bobbinth and removed request for bobbinth February 3, 2026 20:34
Copy link
Copy Markdown
Contributor

@PhilippGackstatter PhilippGackstatter 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 to me!

Comment on lines 63 to 67
pub fn new(
code: impl Into<AccountComponentCode>,
storage_slots: Vec<StorageSlot>,
metadata: AccountComponentMetadata,
) -> Result<Self, AccountError> {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be nice if we could enforce that metadata.name matches the library path of the library, e.g. something like:

let code = code.into();
for export in code.as_library().exports() {
    let path = export.path();
    if !path.as_str().starts_with(metadata.name()) {
        todo!("path {} does not start with {}", path.as_str(), metadata.name())
    }
}

This doesn't work exactly like that (because paths start with ::), but conceptually I think it could. I'm not sure if there's a real downside to enforcing this. I think it could be a nice benefit for DevX to see a component's name be x::y::z and be able to use the same path in code. For example, currently we have things like library_path = ::incr_nonce::auth_incr_nonce and metadata_name = miden::testing::incr_nonce_auth, which don't quite line up and this would enforce consistency.

I think it may make sense to do this after we have changed standard account component paths to be prefixed with miden::standards, e.g. from ::ecdsa_k256_keccak::auth_tx_ecdsa_k256_keccak to something like ::miden::standards::auth::ecdsa_k256_keccak. I have opened #2399 for this. Once we've done that, we could change the component names in one go.

Also, there may be cases where it makes sense for the name to be different, and I just can't think of it, so not really a strong opinion. Just wanted to bring it up.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for opening the issue! I think that makes sense

Comment on lines +168 to +172
pub fn agglayer_faucet_component(storage_slots: Vec<StorageSlot>) -> AccountComponent {
let library = agglayer_faucet_library();
let metadata = AccountComponentMetadata::new("agglayer::faucet")
.with_description("AggLayer faucet component with bridge validation")
.with_supports_all_types();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not from this PR, but the agglayer faucet probably shouldn't support regular accounts? Iiuc, it should only support accounts of type fungible faucet.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I changed this to just be supported on faucets, (ccing @mmagician and @partylikeits1983 as a heads up)

AccountComponent::new(ecdsa_k256_keccak_acl_library(), storage_slots)
.expect(
"ACL auth component should satisfy the requirements of a valid account component",
let metadata = AccountComponentMetadata::new("miden::auth::ecdsa_k256_keccak_acl")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I think it would make sense to make these names constants on their respective types, e.g.:

impl AuthEcdsaK256KeccakAcl {
    pub const NAME: &str = "miden::auth::ecdsa_k256_keccak_acl";
}

I think we might want to access the name from other contexts as well and this would easily allow for that, e.g. for #2399. It may also be useful when we implement an AccountComponentInterface trait that has a name method. Applies to all standard components.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Good point as well, changed

Comment on lines +19 to +20
/// Creates a test metadata for account components that supports all account types.
pub fn test_metadata(name: &str) -> AccountComponentMetadata {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nit: Could this be AccountComponentMetadata::mock instead, defined somewhere in crates/miden-protocol/src/testing/? This would be more consistent with other such mock methods like NoteScript::mock, StorageSlotName::mock, AccountStorage::mock, etc.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

I debated removing this altogether but kept it for now at least

Base automatically changed from igamigo-init-refactor-followups to next February 4, 2026 14:19
@igamigo
Copy link
Copy Markdown
Collaborator Author

igamigo commented Feb 4, 2026

All comments should be addressed so leaving it up in case @bobbinth wants to take a look

Copy link
Copy Markdown
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!

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nit: in other places we name this just metadata.

Copy link
Copy Markdown
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 a couple of comments above - but we can also do them in a follow-up PR.

Comment on lines +210 to +225
let token_symbol_type =
SchemaTypeId::new("miden::standards::fungible_faucets::metadata::token_symbol")
.expect("valid");
let storage_schema = StorageSchema::new([(
BasicFungibleFaucet::metadata_slot().clone(),
StorageSlotSchema::value(
"Token metadata",
[
FeltSchema::felt("token_supply").with_default(Felt::new(0)),
FeltSchema::felt("max_supply"),
FeltSchema::u8("decimals"),
FeltSchema::new_typed(token_symbol_type, "symbol"),
],
),
)])
.expect("storage schema should be valid");
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

A couple of comments here:

  1. It may be good to define miden::standards::fungible_faucets::metadata::token_symbol as a constant at the top of the file.
  2. To improve readability, it may be good to create accessor methods that return the slot schema - something like BasicFungibleFaucet::metadata_slot_schema(). And then the cod here could look like:
let storage_schema = StorageSchema::new([
    BasicFungibleFaucet::metadata_slot_schema(),
])
.expect("storage schema should be valid");

Comment on lines +209 to +215
let pub_key_type =
SchemaTypeId::new("miden::standards::auth::falcon512_rpo::pub_key").expect("valid");
let storage_schema = StorageSchema::new([
(
AuthFalcon512RpoMultisig::threshold_config_slot().clone(),
StorageSlotSchema::value(
"Threshold configuration",
Copy link
Copy Markdown
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. And this is also applicable to other standard components.

@igamigo igamigo force-pushed the igamigo-enforce-metadata branch from b33dbe4 to d40b962 Compare February 6, 2026 20:45
Copy link
Copy Markdown
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 33aff09 into next Feb 6, 2026
17 checks passed
@bobbinth bobbinth deleted the igamigo-enforce-metadata branch February 6, 2026 22:45
afa7789 pushed a commit to afa7789/miden-base that referenced this pull request Mar 9, 2026
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.

Account component metadata follow-ups

3 participants