This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
Consensus protocol upgrade to access account permission authorities #6657
Labels
CONSENSUS
Introduces a change that may modify consensus protocol rules on an existing blockchain.
Background
It is useful to some contracts to be able to check the existence of a permission and, assuming it exists, get the actual authority of that permission. For example, this can help a permission management contract that allows controlled modifications to a user's permissions according to some on-chain policy. Or it can be used by an asserter contract to assert the old authority of a permission so that the permission modification policy can be moved off-chain to user applications that do not necessarily trust the full nodes they need to communicate with to get blockchain state such as the original permission authority.
Consensus upgrade feature
The goal of this consensus protocol upgrade feature is to allow any contract to read the permission objects (particularly the authority) of any account.
A new consensus protocol 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
GET_PERMISSION
will be used to stand-in for whatever the feature identifier will actually end up being.New intrinsic
get_permission_lower_bound
A new intrinsic
int32_t get_permission_lower_bound( const account_name& account, const permission_name& permission, array_ptr<char> buffer, size_t buffer_size )
should be added to theauthorization_api
. The C intrinsic for the WebAssembly side would have a signature such asint32_t get_permission_lower_bound( capi_name account, capi_name permission, char* buffer, uint32_t buffer_size )
.The idea is for contracts to be able to use this intrinsic to check for the existence of a particular permission, and if it exists, get the relevant information. A contract can do so by providing the name of the permission (
permission
) within the specific account (account
) that it is interested in searching for.The system will instead try to find a permission of the specified account that has the smallest permission name value among the set of permissions of the account that have names with a value no smaller than the value of the provided
permission
(i.e. a lower bound search). If there is no such set, then the intrinsic will return -1, otherwise it will return the size (in bytes) of the serialized data representing the found (lower bound) permission.The returned serialized data is a record of type
eosio::permission_record
(defined below) packed according to the regular compactly packed serialization rules done by theEOSLIB_SERIALIZE
macro. The definition ofeosio::permission_record
and the other new types it depends on is provided below:If a contract wants to find an exact match, it must parse the returned serialized data enough to verify the permission name of the returned permission matches the permission name provided to the intrinsic. Because of how the
permission_record
is serialized, it is sufficient to simply check the first 8 bytes of the serialized data (representing thepermission
field of thepermission_record
type) and compare it to thepermission
argument provided to the intrinsic. The intrinsic makes it convenient for the caller to specify only the first N bytes of the serialized record to be copied into the contract's WebAssembly memory (which can improve performance compared to copying the whole thing in when only the first few bytes are relevant). The system will copy in at mostbuffer_size
bytes of the serialized data intobuffer
even ifbuffer_size
is smaller than the actual size of the full serialized data.This enables the eosiolib to include a C++ wrapper over the intrinsic to provide an exact lookup of a particular permission as follows:
The implementation of the intrinsic can be optimized for
buffer_size
values of 0 and 8 to avoid actually doing any serialization of apermission_record
type. It can calculate the size of what the serialized data would be by usingfc::raw::pack_size
to quickly compute the size ofauth.to_authority()
(whereauth
is the authority in thepermission_object
), or better yet add a methodshared_authority::serialized_size
to do a faster calculation of the serialized size that does not require conversion to anauthority
type. Ifbuffer_size == 0
it would just return this calculated size rather than doing any actual serialization. Ifbuffer_size == 8
it would simply copy thename
field of thepermission_object
tobuffer
prior to returning the calculated size as before.By enabling the raw intrinsic to be a lower bound search rather than an exact match, it also enables contract authors to write their contracts to iterate through all the permissions of an account if they so choose. A C++ wrapper function like
eosio::get_permission
defined above hides from the contract developer all of the complexity associated with implementing an exact lookup given only the lower bound intrinsic. Furthermore, implementing the intrinsic as a lower bound search as described above adds negligible overhead (if any at all) compared to an intrinsic designed to only do exact lookups.Contracts should only be able to link with this intrinsic after
GET_PERMISSION
activation.The text was updated successfully, but these errors were encountered: