Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

seal: Storage rent for code #6596

Closed
athei opened this issue Jul 7, 2020 · 6 comments · Fixed by #7935
Closed

seal: Storage rent for code #6596

athei opened this issue Jul 7, 2020 · 6 comments · Fixed by #7935
Labels
I2-security The client fails to follow expected, security-sensitive, behaviour.

Comments

@athei
Copy link
Member

athei commented Jul 7, 2020

Currently, no rent is collected for code that is stored on-chain. Only the state of the individual contracts is subject to rent payments. This is because code is deployed independently of a contract and can then be used by any contract without further costs. There is also no way (apart from governance) to remove code stored on the chain.

This opens up the chain to DoS because anyone can clutter the storage with code with only a one time cost that covers the computation costs of uploading the code.

For that reason, we propose that contracts should pay for the code they use. To incentives code sharing the costs are also shared between all users of a code blob. We change the rent formula that is calculated on contract access or claim_surcharge to:

rent = storage_rent + (code_size / num_code_users)

The costs for code storage converge against zero with more users using it. Due to integer arithmetic is reaches zero once num_code_users > code_size.

One issue is that the rent is not collected every block but only when the contract is accessed or claim_surcharge is called. The num_code_users can change in between blocks making the calculation inaccurate. However, we argue despite the inaccuracy we cannot come up with an attack that turns this into a DoS vector.

Steps that are necessary for implementation:

  • Count the number of users per code hash and delete the code hash once the counter reaches zero
  • The set_code dispatchable is replaced with instantiate_with_code because every code_hash needs at least one user. The seal_instantiate contract callable function stays untouched. Contracts cannot deploy code.
  • Change the rent formula of contracts to also account for the code size.
@athei athei added the I2-security The client fails to follow expected, security-sensitive, behaviour. label Jul 7, 2020
@Robbepop
Copy link
Contributor

Naming proposal:

seal_instantiate -> seal_instantiate_from
seal_put_code -> seal_instantiate

@seanyoung
Copy link

At some point in the future, it would be great to have libraries stored on chain. For example, a wasm dynamic linked library could be available as code. Maybe we seal_instantiate doesn't make much sense in this context.

@athei
Copy link
Member Author

athei commented Sep 28, 2020

Those would get an additional set of interface functions anyways. Alone for the reason that we can't change the semantics of existing interface functions once deployed.

In order to make sure that someone pays for the code of the shared lib we would add a function that supplies two code blobs: The code of the lib and the code of a contract that is its first user. The latter code would be automatically instantiated and that is the contract that pays rent for both the lib and its own code. Adding more users of that lib though seal_instantiate_from or seal_instantiate would then distribute the rent costs among all users.

@athei
Copy link
Member Author

athei commented Oct 25, 2020

Naming proposal:

seal_instantiate -> seal_instantiate_from
seal_put_code -> seal_instantiate

This rename would change the semantic of an existing name. I don't want to cause confusing and code churn by doing so. Keeping seal_instantiate the way it is, is my only condition. By doing so we do not have to touch host functions in any way right now because there is no host function that can deploy new code. We can add this later if it turns out that contracts want to generate new contract code but this is an entirely different topic.

I would just replace the put_code dispatchable with a new function. Ideas:

instantiate_with_code
instantiate_with_upload
instantiate_uploading

@Robbepop
Copy link
Contributor

How about instantiate_new?

@athei
Copy link
Member Author

athei commented Oct 25, 2020

I did not consider that because it is misleading: It is not guaranteed that the instantiated code is new. If you upload a code and the code hash already exists this existing code will be used.

This issue was closed.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
I2-security The client fails to follow expected, security-sensitive, behaviour.
Projects
Status: No status
Development

Successfully merging a pull request may close this issue.

3 participants