This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
Consensus upgrade to allow contracts to read code version of any account #6168
Labels
CONSENSUS
Introduces a change that may modify consensus protocol rules on an existing blockchain.
enhancement
track-in-jira
Background
A smart contract deployed on an EOSIO blockchain may depend on another contract deployed to another account. The dependency can be in the form of read-only access to the tables of the other contract directly or in the form of calling certain actions of the other contract and expecting them to behave in a certain way. However, smart contracts will typically be upgraded over time to fix bugs and add features.
While it is possible for the account that the contract is deployed on to nullify its permissions in a way that makes the contract immutable (short of privileged actions taken by a super-majority of BPs), this is not recommended practice since there will always be bugs discovered or reasons to need to update the contract code in order to just maintain the same behavior that users of the contract expect (note that giving up one extreme of immutability does not require going to the other extreme of a single developer unilaterally and instantly being able to update the contract; EOSIO enables the possibility of middle-ground solutions, but that is beyond the scope of this document). Even for smart contracts that are not meant to change, the specific behavior of the code may need to be tweaked either because: a bug was discovered and the code needs to be modified to match the intent of the code that both the developers and users of the contract agreed upon (as described by the Ricardian contract); or a dependency of the contract (or the platform itself) changes behavior after a sufficient deprecation period in a way that requires the contract to be updated to use new patterns/intrinsics/actions to maintain its same behavior going forward.
A smart contract that depends on another smart contract may wish to play it safe and automatically shut down its functionality (in an effort to protect its users) if a smart contract that it depends on but does not fully control has changed compared to the pinned version that it knows was safe (perhaps because auditors it trusts have fed in a specific version of the contract dependency as safe to use).
For example, it may be desirable for a contract deployed on account
contracta
to only send an inline actioncontractb::foo
authorized with thecontracta@active
permission to the contract deployed on accountcontractb
if it is confident that the behavior ofcontractb::bar
will be identical to that which was concluded by the contract developer at the time of writing the contract. Perhaps they are concerned aboutcontractb
changing its behavior during thecontractb::bar
action to billcontracta
more RAM than expected. So the contract developer may want to include the hash of the WASM code that is deployed oncontractb
in a table accessible tocontracta
and write code in the contract deployed oncontracta
to actually assert that the current code hash ofcontractb
matches the store hash in the table prior to sending the inline action.Or perhaps checking the code hash is not conservative enough. An audit of the contract code that was deployed to
contractb
may have led to the conclusion that calling thecontractb::foo
action is safe (for whatever definition of safety that the developer chose) assuming the deployed contract is the exact same code as the one that was audited AND only that specific code had write access to a specific subset of the contract's tables for the entire lifetime of those particular tables. This may be because the audited code was only proven to be safe if certain invariants about the table records held true. However, a malicious controller of thecontractb
account could replace the original contract (that has hashH1
) with another contract (that has hashH2
) which messes up the tables before then resetting the contract back to the original contract with hashH1
. This would fool the contract deployed tocontracta
if it only pinned to the code hashH1
. However, if the contract instead pinned to a code sequence number (something that incremented on everyeosio::setcode
call), it would be safe from this scenario as well.Furthermore, the ability to check the code hash and/or code sequence number of an arbitrary account (or at least assert that they hold specified values) can be used by an assertion smart contract that assists clients/wallets. A client could craft a transaction to assert that the contract code of the other actions used in the transaction have not changed since the time the transaction was signed.
Consensus upgrade feature
The goal of this consensus upgrade feature is to allow any contract to read the current code hash and code sequence number of any account.
A new consensus upgrade feature will be added to trigger the changes described in this consensus upgrade proposal. The actual digest for the feature understood at the blockchain level is to be determined. For the purposes of this proposal the codename
CODE_VERSION
will be use to stand-in for whatever the feature identifier will actually end up being.New intrinsic
get_code_version
A new intrinsic
uint64_t get_code_version( const account_name& account, int64_t& last_code_update_time, fc::sha256& code_hash )
should be added to theauthorization_api
.The
get_code_version
intrinsic will assert that the specified account exists, set the specified account'scode_version
value fromaccount_object
intocode_hash
, set the specified account'slast_code_update.time_since_epoch().count()
value fromaccount_object
intolast_code_update_time
, and return the specified account'scode_sequence
value fromaccount_sequence_object
.Contracts should only be able to link with this intrinsic after
CODE_VERSION
activation.The text was updated successfully, but these errors were encountered: