-
Notifications
You must be signed in to change notification settings - Fork 47
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
Extend AccountId
to two Felt
s and refactor creation process
#982
base: next
Are you sure you want to change the base?
Conversation
e3c2e11
to
70e705d
Compare
fab8b03
to
f3d649e
Compare
let err = NonFungibleAsset::read_from_bytes(&asset_bytes).unwrap_err(); | ||
assert!(matches!(err, DeserializationError::InvalidValue(_))); | ||
assert_matches!(err, DeserializationError::InvalidValue(msg) if msg.contains("must be of type NonFungibleFaucet")); |
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.
Side note: If we were to change DeserializationError::InvalidValue
to contain a Box<dyn Error>
instead of a String
then we could write such tests in a more resilient way, e.g. downcast the error.
pub fn create_basic_fungible_faucet( | ||
init_seed: [u8; 32], | ||
anchor_block_epoch_and_hash: (u16, Digest), | ||
symbol: TokenSymbol, | ||
decimals: u8, | ||
max_supply: Felt, |
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.
Maybe a question for the client, @igamigo:
To create an account we now need 1) an anchor epoch and 2) the block hash of the anchor epoch block. (Basically the block hash of block AccountBuilder
. Either setting each value individually using AccountBuilder::anchor_epoch
and AccountBuilder::anchor_block_hash
or specifying both at once by passing a BlockHeader
to AccountBuilder::anchor_block_header
. The question is what is best to do here for these convenience functions?
Is it fine to require a BlockHeader
or would that be too restrictive for some reason? My hunch is that the client or any other real world usage would likely always take these values from a block header anyway, so we might as well make it safer and require it. That would be my preferred way to go.
I'm not a huge fan of the current tuple approach, but it is the most flexible (for tests, etc.). I made it a tuple because of the logical connection between the two so making it two separate arguments is probably worse.
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.
Relatedly, I'm also wondering about Account::new
. I just fixed it so it compiles, but it takes the anchor epoch and hash separately as well and is probably not very usable as it is. Interestingly, the method is unused in miden-base, miden-client and miden-node as far as I can tell. So I think we can just remove it and point to AccountBuilder
for building accounts.
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.
Requiring a block header should be fine. Just to clarify, you mean specifically in functions such as create_basic_fungible_faucet()
, correct?
On Account::new()
, I also agree on removing it.
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.
Just to clarify, you mean specifically in functions such as
create_basic_fungible_faucet()
, correct?
Yes, this just relates to create_basic_fungible_faucet
and create_basic_wallet
.
What has changed
AccountId
previously fit into a felt or ~64 bits. Now its representation is two felts:In Rust, the first and second felts are always called as such, typically accessed with
id.first_felt()
andid.second_felt()
.In MASM, the first felt is the
hi
felt and the second felt is thelo
felt and its typical stack representation is [account_id_hi, account_id_lo
].The layout of an ID is:
See the
AccountId
documentation for details on the layout.There is a type
AccountIdPrefix
representing the validated first felt of anAccountId
which is primarily used for non-fungible assets and for asset deserialization. Ideally we would make that private, but for now it must be public for the constructors of non fungible assets.Notable Changes
Here is a quick overview of what changes with this PR. Layouts are in "memory order", that is, stack order would be the reverse of that.
[amount, 0, 0, faucet_id]
[amount, 0, faucet_id_lo, faucet_id_hi]
[hash_0, faucet_id, hash_2, hash_3]
[hash_0, faucet_id_hi, hash_2, hash_3]
[tag, sender_acct_id, encoded_type_and_ex_hint, aux]
[sender_hi, sender_lo_type_and_hint_tag, note_tag_hint_payload, aux]
AfterBlock
can only take values less thanu32::MAX
so that when encoded together with the note tag in a felt (i.e.note_tag_hint_payload
above) felt validity is guaranteed.AccountIdPrefix
is compatible withAccountId
to allow for deserialization of a prefix from a serializedAccountId
. This is used for the next point.AccountIdPrefix
serialization is such that the first byte of the serialized layout contains the metadata. This is used in the asset deserialization to read the type and based on that deserialize the bytes as a fungible or non-fungible asset.NoteTag::from_account_id
effectively takes the most significant bits ofid_first_felt << 1
. This means the high zero bit is ignored with the rationale being that it would not add any value for matching an account ID against a note tag, since all ID's high bits are zero. Let me know if this doesn't make sense.MockChain
due to the dependence of the account ID on an anchor block.[account_nonce, 0, account_id_hi, account_id_lo]
. So anything related to that would be particularly helpful to have reviewed.This PR does not change anything about the account tree, e.g. the
accounts: SimpleSmt<ACCOUNT_TREE_DEPTH>
field inMockChain
.I think a rough sensible review order would be AccountId + AccountIdPrefix followed by the changes to assets, all in Rust.
Then moving over to MASM.
Open Questions
NoteMetadata
that is different from theWord
encoding? We had a different one before this PR, but now the serialization format and word encoding are identical.Follow-Up Tasks
There are still some TODOs in the code and those could mostly be addressed in a follow-up PR so this PR could would not necessarily be blocked by that (checked boxes are included in this PR).
AccountIdError
. There are now new error conditions for IDs and a separate error might be cleaner.AccountId::new_dummy
aconst fn
and then we could possibly replace the somewhat duplicate functionality ofmiden_objects::testing::account_id::account_id
.AccountType
and use it in error messages.generate_account_seed
.build.rs
constants patching for POW which we no longer have.account_id.rs
.miden-lib
#1002).validate_fungible_asset_origin
validates the account ID and then callsvalidate_fungible_asset
which validates it again check if we can remove some redundancy here.NoteExecutionHint::AfterBlock
being constructable by users but it now cannot contain u32::MAX and we might want to prevent that.build_swap_tag
.Why it changed
See #140, although I'd like to ideally add a summary here.
closes #140