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

feat: Introduce ComponentPackage and ComponentTemplate #1015

Open
wants to merge 5 commits into
base: next
Choose a base branch
from

Conversation

igamigo
Copy link
Collaborator

@igamigo igamigo commented Dec 11, 2024

Part of #550.
Introduces a first draft of ComponentPackage and ComponentTemplate.

For now it can serialize and deserialize configs such as this one:

name = "Test Component"
description = "This is a test component"
version = "1.0.0"
targets = ["FungibleFaucet"]

[[storage]]
name = "slot0"
description = "First slot"
slot = 0
value = "0x2551340000000000af02000000000000a3db000000000000ffeeff0f00000000"

[[storage]]
name = "multi"
description = "Multi slot entry"
slots = [1, 2, 3]
values = [["3428645", "687", "0xdba3", "0xfffeeff"], "0x2551340000000000af02000000000000a3db000000000000ffeeff0f00000000", "0x2551340000000000af02000000000000a3db000000000000ffeeff0f00000000"]

[[storage]]
name = "map"
slot = [4]
values = [{key="0x1", value="0x2"}]

Most structs down to the element need to have custom (de)serialization due to the different alternatives discussed in #550, but at least now it's easy if we want to add a new away of encoding things such as felts (for instance, if we want to allow for binary representation for elements).

Planned follow-ups:

  • Finish template matching ({{foo.bar.baz}}) for matching whole words or single elements

@igamigo igamigo force-pushed the igamigo-acc-pkg branch 2 times, most recently from 0cee24f to 123e92c Compare December 11, 2024 22:10
@igamigo igamigo changed the title feat: Introduce ComponentPackage feat: Introduce ComponentPackage and ComponentConfig Dec 11, 2024
@igamigo igamigo changed the title feat: Introduce ComponentPackage and ComponentConfig feat: Introduce ComponentPackage and ComponentTemplate Dec 12, 2024
@igamigo igamigo marked this pull request as ready for review December 12, 2024 21:55
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 comments inline.

///
/// Each entry can describe:
/// - A value slot (single word or multiple words).
/// - A multi-slot entry (spanning multiple contiguous slots, with multipe values).
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this point be about storage maps?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Added the storage map entries alongside its functionality

/// The initial value for this slot.
value: WordRepresentation,
Copy link
Contributor

Choose a reason for hiding this comment

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

Should this be just Word? I guess the question is whether it makes sense to keep the original representation at this level as well. The alternative would be to convert WordRepresentation to Word when we go from RawStorageEntry to StorageEntry.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I debated this as well. I think the only real upside of keeping the representation is to be able to get the original representation when unpacking or inspecting packages. Whether this is valuable, I'm not sure. I think whether the value is defined as elements or as a binary number, for instance, could sometimes give some more semantic context to the entry itself, but obviously not sure it will be very useful versus just parsing as words and keeping that (probably less error prone as well, though this is easily tested).
I was thinking of adding some methods for more simply retrieving Word from each entry while keeping the original representation, but again maybe this is too much.

objects/src/accounts/package/mod.rs Outdated Show resolved Hide resolved
#[macro_export]
macro_rules! digest {
($hex:expr) => {{
let felts: [$crate::Felt; 4] = match $crate::utils::parse_hex_string_as_word($hex) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Question: how would this affect the ability to use the digest! macro from other crates?

Comment on lines +103 to +112
if slots.len() != values.len() {
return Err(ComponentMetadataError::InvalidMultiSlotEntry);
}

Ok(StorageEntry::MultiSlot {
name: name.into(),
description: description.map(Into::<String>::into),
slots,
values: values.into_iter().map(Into::into).collect(),
})
Copy link
Collaborator

Choose a reason for hiding this comment

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

The description above says:

  • A multi-slot entry (spanning multiple contiguous slots, with multipe values).

Should we check that the slots are contiguous? (I know we also check it at the ComponentPackage level.

if !slot_present {
return Err(D::Error::missing_field("slot"));
}
if raw.value.is_some() {
Copy link
Collaborator

Choose a reason for hiding this comment

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

nit: could we use value_present here?

Comment on lines +284 to +293
if slot_present {
return Err(D::Error::custom(
"Fields 'slot' and 'slots' are mutually exclusive.",
));
}
if value_present {
return Err(D::Error::custom(
"Fields 'value' and 'values' are mutually exclusive.",
));
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

These checks for mutual exclusivity can be done before the match to reduce code repetition

Comment on lines +244 to +245
slot: raw.slot.expect("was checked to be present"),
value: raw.value.expect("was checked to be present"),
Copy link
Collaborator

Choose a reason for hiding this comment

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

instead of the if + expect we could do .ok_or(...)? here

Comment on lines +294 to +295
let slots = raw.slots.ok_or_else(|| D::Error::missing_field("slots"))?;
let values = raw.values.ok_or_else(|| D::Error::missing_field("values"))?;
Copy link
Collaborator

Choose a reason for hiding this comment

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

If we change the match to be match (raw.slots, raw.values) we could deconstruct in the case to (Some(slots), Some(values)) and remove these ok_or_else.

Comment on lines +137 to +141
impl Default for WordRepresentation {
fn default() -> Self {
WordRepresentation::SingleHex(Default::default())
}
}
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should this be in the previous section?

}
// Enforce and skip the '0x' prefix.
let hex_bytes = match hex.as_bytes() {
[b'0', b'x', rest @ ..] => rest,
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we allow for "0X" prefix like we do for Felts?

Comment on lines -92 to -93
// SAFETY: u8 cast to u64 is safe. We cannot use u64::from in const context so we
// are forced to cast.
Copy link
Collaborator

Choose a reason for hiding this comment

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

We should add this safety comment back to the match case

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.

3 participants