-
Notifications
You must be signed in to change notification settings - Fork 254
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
Two NearMaps can write into the same storage independently #182
Comments
Update: As discussed with @SkidanovAlex below, it is easier to fix it rather than make API for complex. We need to introduce an explicit boolean flag for the constructor argument, which specifies whether the user intends to alias an existing map. If they did not intend to alias the contract should panic. Specifically, it will look like: let a = NearMap::new("x", false);
// Lots of code.
let b = NearMap::new("x", true); <--- specifies the intention to alias and so it does not panic. while let a = NearMap::new("x", false);
// Lots of code.
let b = NearMap::new("x", false); <-- panics because the user did not intend to alias This would require keeping track of all currently created collections in a static variable |
@evgenykuzyakov WDYT? |
@nearmax I think that complicates stuff for the user even further? |
We can make aliased collections work. The issue comes from the fact that
I don't think the proposed solution is good either, it is just first that came to mind. Overall, I think we should revisit this interface from the DevX perspective. Should we hide it from the users that these collections alias the kvdatabase or should we make it very explicit? #183 I am leaning towards making it very explicit, since we cannot fully reproduce interface fo |
I'm for https://medium.com/cryptologic/memory-and-storage-in-solidity-4052c788ca86 |
I'd vote for performance. This is super rare when you need to have 2 persistent collections in memory at the same time, so making it explicit through a different constructor is fine. E.g. |
Indeed we need some kind of a storage which supports references. |
@nearmax @evgenykuzyakov how does "reuse" would work if |
Can someone give me the use case of why you would want to reuse the same structure twice? This just seems like it would cause data races and application-specific bugs to do this. Although allowing multiple structures to reference the data may be slightly easier to have read and write access to underlying storage, it would just become a foot gun where the compiler can't check the logic is sound. One other note is that if you allow this reusing by creating multiple data structures, it does not allow you to add a caching layer on these types without introducing breaking changes and rug pull this functionality later. cc: @matklad as he also recently had the suggestion to move this I'm indifferent about the naming because with an updated API these collections can be close to drag and drop with the |
Yeah, I am not sure if we need to support aliasing at all in the library. If the user wants aliasble thing, they can wrap it in |
Closing this, the base patterns to avoid are documented in https://docs.near.org/sdk/rust/contract-structure/collections#error-prone-patterns and there isn't anything here actionable as the tradeoffs to writing the length back to storage after each operation and encouraging this pattern isn't feasible |
Example:
Observe that code fails with `HostError(GuestPanic
{ panic_msg: "Index out of bounds" }
)`.
Also if you comment
y.insert(&"x".to_string(), &"2".to_string());
observe a different error:` HostError(GuestPanic
{ panic_msg: "The collection is an inconsistent state. Did previous smart contract execution terminate unexpectedly?" }
)`
These errors are unexpected for developer and don't provide clear guidance how to fix this.
Even though it's user error, this types of usage can be hidden very deeply in the code and hard to track.
The text was updated successfully, but these errors were encountered: