-
Notifications
You must be signed in to change notification settings - Fork 25
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
Remove Blockchain.getStorage / Blockchain.putStorage #399
Comments
Might need something a little more nuanced for the case where a contract inherits another contract that uses key-value storage on its own. |
This can be considered, subject to patterns we see being used, in the AVM 2.0 timeframe as it changes (or at least adds) API. |
Thanks for the feedback. An implementation is here and the use site https://github.com/fulldecent/aion-aip010/blob/master/src/main/java/org/aion/AIP010.java#L81 My main concern now is finding if this approach will be considered best practice. |
Talking with people on this side, this sounds like something we would just add to the userlib, as it avoids duplication in a fairly common-case. The only real question of how to best approach this is in what is passed in as the namespace key versus the element key. The easiest answer is We can proceed with a userlib modification (which doesn't require a hard-fork - it is just something packaged with the contract) if we can figure out the right type and |
Thanks for checking into this. At the most general case we are addressing the key-value store using a variable-length tuple (i.e. vector). These tuples should be fully qualified. In other words we must encourage code reuse patterns where methods AND STORAGE KEYS are defined in multiple files. Below is an all-encompassing use case which explains every type of storage situation Aion will ever encounter in a key-value store as a basis for defining how the user lib should work. Here is a great key for storing your token name, which is used once for the whole contract, and which is an implementation detail of the reference implementation of aipXXX:
Here is a great key for storing your token balance for each account:
Here is a great key for storing permission from each account to an authorized operator (a bool for a tuple of account and operator):
Then let's say your application reuses code from the aipXXX token reference implementation (e.g. subclasses, inherits, whatever) and defines its own variable for knowing who most recently received a token. (Hey it's their application, they can do whatever they want.) Here is a great key for that:
Now after that, on a Saturday, before launch week, the CTO decides to switch from aipXXX to aipYYY. So, hopefully, they just swap out one line of code any everything should work, right? Well, the chosen aipYYY implementation also just happens to define a storage slot In Java, an public void putStorage(byte[] value, Enum domain, byte[]... keyTuple);
public void getStorage(Enum domain, byte[]... keyTuple); The implementation of Using AionBuffer would cause the following vulnerability:
The tuple |
I suspect that using an |
I would love to use integers if possible. Here is the use case: code/OwnableContract.java The OwnableContract and FungibleToken code is reused (copy/pasted, imported/subclassed, etc) from an upstream vendor. Is it possible in Java for all three authors to guarantee that their enums will have different ints? |
It is a trade-off between how much of this should be managed as cut-and-paste, versus actual integration decisions. While things like ABI resolution require a very concrete answer (since the method namespace must be the same, no matter what else is included), this one has other potential options. Ideally, I would favour reduced deployment and transaction cost, even at the cost of a somewhat manual integration effort, during deployment. |
We cannot choose whether developers will copy/paste and expect things to work. We can only choose whether there will be disastrous consequences when developers copy and paste. At the moment, fully qualified Strawman approach #2 could be: each contract has exactly one enum (probably in a separate file) and they must concatenate the storage names from each code they are reusing into that file. So it uses an int ( This is a tradeoff. Will somebody please be able to implement a full example using both approach and present the data on how much more wasteful using strings actually is? |
Thinking further about this, I suspect that the |
Nice, great find. Could you please link to documentation that shows the guarantees you are relying on? Are these hash codes deterministic for off-chain analysis? |
Related #409 is a great implementation of this concept here. It adds a type safe API for the values too. |
The function signature for Blockchain.getStorage / Blockchain.putStorage encourages boilerplate code and this results in unsafe implementations.
Therefore, in every case, the boilerplate can be factored out at least to:
where
SUB_SLOT
can be null or any value. And then this new function will applyBlockchain.blake2b
toSUB_SLOT
.In every case it seems that this API would be safer, semantic and reduce verbosity, therefore I recommend that this replace the existing API.
References
The text was updated successfully, but these errors were encountered: