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

Reconsider the design of StorageMap and StorageVec to avoid the use of __get_storage_key (while staying backward compatible) #3202

Closed
mohammadfawaz opened this issue Oct 30, 2022 · 3 comments · Fixed by #4464
Assignees
Labels
compiler: frontend Everything to do with type checking, control flow analysis, and everything between parsing and IRgen enhancement New feature or request lib: std Standard library

Comments

@mohammadfawaz
Copy link
Contributor

mohammadfawaz commented Oct 30, 2022

When storage references get implemented, we should move away from using __get_storage_key. This was a hacky way to get StorageMap working but now that we're about to have storage references, I think we can do better.

Currently, the method insert looks like:

    fn insert(self, key: K, value: V) {
        let key = sha256((key, __get_storage_key()));
        store::<V>(key, value);
    }

and is called using storage.map.insert(key, value), which is equivalent to ~StorageMap::insert(storage.map, key, value).

When we have storage references, we can imagine something like:

    fn insert(ref self, key: K, value: V) { // ref self or `StorageRef<Self>` or something like that
        let key = /* extract this from the reference to self */
        store::<V>(key, value);
    }

and the syntax for calling insert would remain the same: storage.map.insert(key, value) and would be equivalent to ~StorageMap::insert(storage.map.ref(), key, value).

Of course, a lot of details and the syntax have to be worked out, but I think this is a much more robust way of implementing StorageMap that does not actually break existing code. This also enables passing storage maps around to functions and also writing:

let map_ref = storage.map.ref();
map_ref.insert(key, value);

One more motivation for the above is that I actually have doubts about the intrinsic __get_storage_key if the method using it (like insert() or get()) is not inlined 🤔

Note

Equivalent Rust code for a simple struct would look like

struct S {
    x: u64,
}

impl S {
    fn foo(&self) -> u64 {
        self.x
    }
}

fn main() {
    let s = S { x: 5 };

    // These two are equivalent
    let x = s.foo(); // Effectively taking the ref here before calling `foo()`
    let x = S::foo(&s);
}
@mohammadfawaz mohammadfawaz added lib: std Standard library compiler: frontend Everything to do with type checking, control flow analysis, and everything between parsing and IRgen enhancement New feature or request labels Oct 30, 2022
@mohammadfawaz mohammadfawaz changed the title Reconsider the design of StorageMap and StorageVec to avoid the use of __get_storage_key Reconsider the design of StorageMap and StorageVec to avoid the use of __get_storage_key (while staying backward compatible) Oct 30, 2022
@mohammadfawaz
Copy link
Contributor Author

@mitchmindtree touched on this subject a bit here #2585

@sezna
Copy link
Contributor

sezna commented Oct 30, 2022

I like this -- the only handwavy part we need to sort out is the "extract the storage key from the reference". I suppose that'd be through StorageRef's stdlib API, which would perhaps use __get_storage_key()?

@mohammadfawaz
Copy link
Contributor Author

mohammadfawaz commented Oct 30, 2022

I like this -- the only handwavy part we need to sort out is the "extract the storage key from the reference". I suppose that'd be through StorageRef's stdlib API, which would perhaps use __get_storage_key()?

I think the reference itself will contain the key(s) needed depending on how we spec it out. Basically, the key is now an argument so that if insert is not inlined, we don't have any issues.

@mohammadfawaz mohammadfawaz self-assigned this Jan 29, 2023
mohammadfawaz added a commit that referenced this issue Apr 21, 2023
…` RFC (#4464)

## Description
Implement FuelLabs/sway-rfcs#23

Closes #3419 (technically via the
RFC)
Closes #3202
Closes #3043
Closes #2639
Closes #2465
Closes #4304

This is a big one but mostly removes stuff. It's hard to review but the
summary of changes below should be sufficient. Most of the changes here
are things that I just had to do to make CI pass.

- Removed the `--experimental-storage` flag and made its
[behavior](#4297) the default. Also
removed everything that was required for the previous storage APIs in
favour of the new ones.
- Break down the `std::storage` into multiple submodules:
 - `storage_key` implements the API for `std::core::StorageKey`
- `storage_api` implements the free functions `read` (previously `get`),
`write` (previously `store`), and `clear`.
- 4 more modules for the dynamic storage types which now use the new
`StorageKey` API.
- `#[storage(write)]` now allows reading from storage as well. This is
needed because the way we pack structs in storage now requires that we
sometimes read from storage first if we were to write a portion of a
slot.
- Removed the "storage only types" checks and the corresponding tests.
- Removed the `__get_storage_key` intrinsic and the `get_storage_key` IR
instruction and all corresponding tests. Also removed the `state_index`
metadata as it is no longer required.
- Added tests and example to showcase nested storage maps and nested
storage vectors.

## Checklist

- [x] I have linked to any relevant issues.
- [x] I have commented my code, particularly in hard-to-understand
areas.
- [x] I have updated the documentation where relevant (API docs, the
reference, and the Sway book).
- [x] I have added tests that prove my fix is effective or that my
feature works.
- [x] I have added (or requested a maintainer to add) the necessary
`Breaking*` or `New Feature` labels where relevant.
- [x] I have done my best to ensure that my PR adheres to [the Fuel Labs
Code Review
Standards](https://github.com/FuelLabs/rfcs/blob/master/text/code-standards/external-contributors.md).
- [x] I have requested a review from the relevant team or maintainers.

Co-authored-by: Joshua Batty <joshpbatty@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compiler: frontend Everything to do with type checking, control flow analysis, and everything between parsing and IRgen enhancement New feature or request lib: std Standard library
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants