we could potentially remove the key from the ABI output altogether if we standardise and document how storage type nesting maps to key construction. E.g.
Top-level storage "fields" are prefixed by a single word field index.
Array elements are prefixed by a single word array index.
Tuple elements are prefixed by a single word tuple index.
Map entries are prefixed by the map key encoded as words.
This might also make it a bit easier to support dynamically sized keys (e.g. strings or byte arrays) in the future, as the current key representation in the ABI output (Vec<Option<Key>> with Nones for map keys) can't support unknown sized keys.
@mohammadfawaz pointed out that we will likely want to continue flattening tuples and arrays. While these complicate the rules slighlty, it should still be doable as long as the necessary context required for flattening is provided during traversal.
Steps
[x] Move the pint-abi-gen refactor commit from #761 with the visit mod into its own PR.
Done: #767.
[x] Move the visit module into its own pint-abi-visit crate that can be shared between pint-abi and pint-abi-gen for handling traversals of the KeyedTypeABI tree.
[x] Change KeyElem to Nesting in pint-abi-visit crate.
[x] In Nesting type, change Fixed to Var for storage/pub-key var, and add a TupleIx variant.
[x] Change the key stack in generated Mutations to be Vec of type enum KeyElem { MapKey(Vec<Key>), ArrayIx(Word) } (declared in pint-abi).
[x] Update pint_abi::merge_key to merge [KeyElem] into a [Nesting].
This is where key flattening can happen - e.g. consecutive Nesting::ArrayIxs can be collapsed into a single Word.
This still requires some thought around how to derive the flattened key from nested tuples. The Nesting::TupleField will likely need both index and flattened_index fields...
[x] Change abi_key_exprs to be nesting_exprs with type [Nesting] rather than [Option<Word>] for use with the updated merge_key function.
These changes will also help to separate the concept of keys (which can sometimes be flattened) from the concept of type nesting which is required for human-readable API generation that matches the user's storage/pub var declarations.
Opening a dedicated issue for the approach originally described here: https://github.com/essential-contributions/pint/issues/752#issuecomment-2212460367.
@mohammadfawaz pointed out that we will likely want to continue flattening tuples and arrays. While these complicate the rules slighlty, it should still be doable as long as the necessary context required for flattening is provided during traversal.
Steps
pint-abi-gen
refactor commit from #761 with thevisit
mod into its own PR.visit
module into its ownpint-abi-visit
crate that can be shared betweenpint-abi
andpint-abi-gen
for handling traversals of theKeyedTypeABI
tree.KeyElem
toNesting
inpint-abi-visit
crate.Nesting
type, changeFixed
toVar
for storage/pub-key var, and add aTupleIx
variant.Mutations
to beVec
of typeenum KeyElem { MapKey(Vec<Key>), ArrayIx(Word) }
(declared inpint-abi
).pint_abi::merge_key
to merge[KeyElem]
into a[Nesting]
.Nesting::ArrayIx
s can be collapsed into a singleWord
.Nesting::TupleField
will likely need bothindex
andflattened_index
fields...abi_key_expr
s to benesting_expr
s with type[Nesting]
rather than[Option<Word>]
for use with the updatedmerge_key
function.These changes will also help to separate the concept of keys (which can sometimes be flattened) from the concept of type nesting which is required for human-readable API generation that matches the user's storage/pub var declarations.