-
Notifications
You must be signed in to change notification settings - Fork 137
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
Shared contract code #556
Comments
I like this mechanism. It is fairly straightforward and seems to be a good MVP. Processing A potential future direction to consider could be that we do not eagerly download all permanent contracts to all shards / validators. Instead, a validator only fetches the permanent contract when |
Related discussion about a more general approach to a global key-value storage: #93 |
No it will not. The current mechanism does not distribute contract code to all validators, but only to validators assigned to that shard.
Complexities like "home shard" are what this design aim to simplify. If you want a smart contract to be domiciled on some shard, then you inevitably have to either complicate the state structure or deal with questions such as what if the last account with this contract deployed is deleted. The beauty of this design is that it does not make any change to the state representation and therefore avoids a number of complexities. |
@bowenwang1996 (ex: 300kb -> 310kb) scenario 1: Pay 30 NEAR + Pay 31 Near = Total 61 NEAR scenario 2: Pay 30 NEAR + Pay 1 Near = Total 31 NEAR |
This is an awesome addition! I would also want to know how upgrades are handled (and if they are possible at all under this mechanism), and if smart contracts stay upgradable, then how are storage migrations handled? |
@nujabes403 this design does not allow one to upgrade permanently deployed contract, so you need to deploy a new contract. To implement upgradability is not trivial because of two reasons: 1) currently the contract is identified by its hash and that is how a regular account can deploy a permanent contract on their account. If there is a need for upgradability this needs to be changed. 2) There needs to be a permission management system that specifies who can upgrade the contract. Because the contract is not deployed on any specific account, it becomes very messy. What do you think is a contract that needs to be deployed on many user accounts and also need to be upgraded frequently? |
The proposal above describes a global contract code that doesn't have any label which means there is no permissions and upgradability that have been enjoyed by NEAR smart contracts. One option to extend proposal with:
|
A commonly used method in EVM-based chains is: This method is widely adopted by EVM-based developers. If NEAR also supports this, developers could develop more easily. For example, if we declare a NEP 141 contract with custom logic as a Permanent Contract, and allow all deployed NEP 141 tokens to point to �the contract, when we want to change the Logic of all deployed contracts, we only need to modify the Logic Contract declared as a Permanent Contract. This would provide great convenience for developers. In this regard, if upgradeability of permanent contracts is supported, it would be very powerful. |
@ilblackdragon the main problem here with upgrades based on some sort of label other than contract hash is that it requires a nontrivial change to the state format and the runtime implementation. Basically, instead of storing contract hash in account state, we now need to store an account id and resolve it to a specific contract at runtime. This requires introducing another account version, which is doable but requires extra efforts. I think it is probably beneficial to implement the proposal without contract upgradability in the first version. If there is a strong demand from contract developers for the upgradability feature, it can be implemented on top of the first version. |
Given this will be the same method that will power both shared and sharded smart contracts, I think making sure that you have the There is a pretty simple way to implement support this without any changes to state/contract runtime: the table with shared contracts is keyed by |
I agree that it is simple. However, it does not offer the option to not have the contract be controlled by a remote account. In comparison, if you specify a contract hash, you know for sure that this will be the contract deployed on your account and only you have the permission to modify it. |
You as a developer can deploy only contracts that were globally
deployed by an account that doesn't have any access keys. That gives
you this exact guarantee.
If there is a contract that is deployed by a managed account and you
want to make sure it doesn't get upgraded - you can re-deploy it
yourself from an account that doesn't have access keys.
…On Sun, Aug 11, 2024 at 10:43 PM Bowen Wang ***@***.***> wrote:
There is a pretty simple way to implement support this without any changes to state/contract runtime: the table with shared contracts is keyed by hash(account_id) and DeployExistingContractAction uses hash(account_id).
I agree that it is simple. However, it does not offer the option to not have the contract be controlled by a remote account. In comparison, if you specify a contract hash, you know for sure that this will be the contract deployed on your account and only you have the permission to modify it.
—
Reply to this email directly, view it on GitHub, or unsubscribe.
You are receiving this because you were mentioned.Message ID: ***@***.***>
--
Best regards,
Illia Polosukhin
|
I agree with @bowenwang1996 that simplicity is a benefit here. As a developer, I can check the code deployed, link it to my account, and know that it will never change (which removed any chance of new bugs being introduced in the future without my explicit consent) If I need to update my contract in the future there are 3 options:
I would expect most contracts to not update frequently. When I spoke with developers about this need, they were more worried about storage cost than upgradeability With that being said, if this is a common pattern in Ethereum, we might add another layer of friction on their onboarding journey |
Adding notes from a discussion with @ewiner @alexauroradev @ilblackdragon:
|
I think we should make the global contract semantics as similar as possible to existing contracts. For instance, AFAIK this proposal would be the first place we have a concept of a separate 'deployer' account used to refer to a contract, but I don't think that's necessary. So here's my mental model for how this feature could work:
To upgrade a global contract (which takes effect for all account-referenced copies ASAP), you can call Similarly, even if the global contract is meant to be just a template/factory that gets copied to other accounts, it might still have a working Other transition rules:
|
I'm trying to understand the motivation. Is it this one: Using global contracts deployed by third parties is unsafe because they can upgrade them at any time. Instead, you should first copy the contract and then reference the copy for your contracts. Is this correct? An alternative to copy: Another contract can indicate that its code is either:
I think you should be able to move from any state to any other state. In case a critical issue is found on the global contract and you have FAK for your account, you should be able to redeploy a new contract code. |
Kind of. But yes, the issue here is who is allowed to upgrade the contract on your behalf. Consider a situation where
@mfornet You can always deploy a new global contract to upgrade your previous global contract. But if you try to convert from global to local, then any copies on different accounts that were pointing to the latest copy of your global contract would break. |
A common use case on NEAR is to deploy the same smart contract many times on many different accounts. For example, a multisig contract is a frequently deployed contract. However, today each time such a contract is deployed, a user has to pay for its storage and the cost is quite high. For a 300kb contract the cost is 3N. With the advent of chain signatures, the smart contract wallet use case will become more ubiquitous. As a result, it is very desirable to be able to reuse already deployed contract without having to pay for the storage cost again. At the same time, the new stateless validation architecture also needs to better way to distribute contract code so that it doesn't bloat state witness.
The proposal is as follows. A new deploy contract action will be introduced (tentatively called
DeployPermanentContractAction
). This action, when processed, has a few differences from theDeployContractAction
:After runtime process this
DeployPermanentContractAction
, it generates a list ofpermanent_contracts
. The chunk producer for this chunk is then repsonsible for broadcasting these contracts to all validators. Chunk headers include a vector of hashes of new permanently deployed contracts. In the block header, apermanent_contracts_root
is maintained as the merkle root of hashes of all permanently deployed contracts. When a new validator node joins the network, it can synchronize all permanently deployed contracts from other nodes using thepermanent_contracts_root
of a specific block.We will also introduce a new action
DeployExistingContractAction
, which, instead of taking the whole contract as an argument, simply takes a contract hash. This action attempts to deploy a permanent contract onto an account and will fail if no such permanent contract exists. The gas cost of this action should be the same as the gas cost of updating an account, since no deployment actually happens when this action is processed.Because permanently deployed contract code is now stored on every validator node, it does not need to be included as part of state witness. Permanently deployed contract code is not stored as part of the state. They, alongside with their compilation results, are stored separately in a key value based storage.
A summary of changes/addition of new structs can be found below:
The text was updated successfully, but these errors were encountered: