You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.
CONSENSUSIntroduces a change that may modify consensus protocol rules on an existing blockchain.SNAPSHOTSRequires introducing a new version for snapshots and/or ends support for old versions of snapshots
Deferred transactions make it difficult to sell an EOSIO account to a new owner. An atomic transaction which simply includes two actions, one to change the owner permission of the account and another to transfer tokens to compensate the original owner, is vulnerable to various tactics that could be employed by the original owner to steal back the account.
One of these tactics is for the original owner to propose and approve a transaction in the eosio.msig contract which changes the authority of the owner permission of their account back to something that allows them to get back in control of it. Then after completing the sale of the account, the original owner can simply eosio.msig::exec that pre-approved transaction and get back the account. The eosio.msig::invalidate action was added (EOSIO/eosio.contracts#59) to deal with this particular loophole with selling EOSIO accounts. So the atomic transaction to sell the account discussed earlier could also include a third action eosio.msig::invalidate that invalidates any prior authorizations by the sold account within the eosio.msig contract.
However, another loophole still remains using deferred transactions. This tactic is very similar to the previous one: the original owner creates a delayed deferred transaction which changes the authority of the owner permission of their account back to something that allows them to get back in control of it. The original owner of the account then makes sure to complete the sale prior to the delay_until time of the deferred transaction, and then simply waits until the deferred transaction retires and reverts control of the account back to the original owner.
Unfortunately a change to contract code (even to the system contract) is not sufficient to patch this loophole with selling accounts in a way similar to what was done with the eosio.msig::invalidate action. Deferred transactions are a native feature of EOSIO blockchains, and creating an invalidation action that affects deferred transactions requires a consensus upgrade.
Consensus upgrade feature
The goal of this consensus upgrade feature is to add a new privileged intrinsic that enables the creation of an action which invalidates any authorizations of a particular account within deferred transactions that were scheduled prior to the call of that action. This action (along with the similar eosio.msig::invalidate action) would enable closing the remaining loopholes with selling EOSIO accounts that could allow the original owner to change back the owner permission of the account after the sale has completed.
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 INVALIDATE_DEFERRED will be use to stand-in for whatever the feature identifier will actually end up being.
This consensus upgrade feature will require a new uint64_t field deferred_invalidation to be added to account_object (or more likely account_sequence_object to be efficient with undo state size). The extra 8 bytes of overhead per account should be small enough to not require changing how much fixed RAM overhead each account is already charged.
This consensus upgrade feature will also require a new uint64_t field sender_action_sequence to be added to generated_transaction_object. It may be the case that do to rounding up to the nearest multiple of 16, the current amount of RAM that is billed for sending deferred transactions is sufficient to include this extra field at no additional cost to accounts. More careful analysis is needed regarding this point. It may turn out to be the case that the total rounded-up billed amount would need to increase by at most 16 bytes. If that is the case, then additional logic will need to be added to maintain the old billing size prior to INVALIDATE_DEFERRED activation and switch to the new billing size after INVALIDATE_DEFERRED activation.
A new chain_snapshot_header version is necessary (e.g. version 2) to handle the changes of this consensus upgrade feature. Version 2 of the snapshot will include the new sender_action_sequence field in the rows of the index for generated_transaction_object and include the new deferred_invalidation field in the rows of the corresponding affected index. The new version of nodeos supporting the INVALIDATE_DEFERRED consensus upgrade feature should not be able to read a snapshot with a chain_snapshot_header version of 1 (this forces the necessary replay from genesis to occur). The new version of nodeos should support version 2 of the snapshot when reading or writing a snapshot.
New intrinsic invalidate_deferred_authorizations
A new intrinsic called invalidate_deferred_authorizations which takes an account name should be added to the privileged_api. Contracts should only be able to link with this intrinsic after INVALIDATE_DEFERRED activation.
When this intrinsic is called passing in some account name as the argument, the deferred_invalidation field of that account (it should assert it exists) should be set to the global action sequence number of the action that called the intrinsic (should be global_action_sequence + 1).
Changes to apply_context::schedule_deferred_transaction
When both creating and modifying the generated_transaction_object, the gtx.sender_action_sequence field should be set to the global action sequence number of the action that called the send_deferred intrinsic (should be global_action_sequence + 1). This should happen regardless of whether INVALIDATE_DEFERRED was activated or not.
Changes to transaction_context::init_for_deferred_trx
The transaction_context::init_for_deferred_trx function should take a second argument enforced_deferred_invalidation of type uint64_t.
If and only if INVALIDATE_DEFERRED has been activated, then (prior to the init call) the init_for_deferred_trx function should iterate through all the authorizations in all actions in the transaction and assert that the actor of the authorization has a deferred_invalidation value less than or equal to enforced_deferred_invalidation.
Changes to controller_impl::push_scheduled_transaction
The call trx_context.init_for_deferred_trx( gtrx.published ) should be replaced with trx_context.init_for_deferred_trx( gtrx.published, gtrx.sender_action_sequence ).
How the new intrinsic is intended to be used
A system contract upgrade after INVALIDATE_DEFERRED activation could be deployed which introduces a new action invaliddefer that just takes one eosio::name. The action would require_auth on the provided account name and then call the invalidate_deferred_authorizations intrinsic passing it that account name.
An atomic transaction to carry out an account sale would then need to include the following actions:
eosio::updateauth to change the authority of the owner permission of the account to be sold.
eosio::invaliddefer to invalidate all authorizations by the account to be sold in any prior scheduled deferred transactions (whether delayed input transactions or contract-generated transactions).
eosio.msig::invalidate to invalidate all approvals by the account to be sold on any proposed multisig transactions.
eosio.token::transfer to transfer the tokens to the original owner of the account as compensation for selling the account.
The text was updated successfully, but these errors were encountered:
This issue depends on #6429 and #6437. It will also be setup by default to be a protocol feature requiring pre-activation, thus it also depends on #6431.
In order to focus our efforts on issues that are currently creating difficulty for the community we are closing tickets that were created prior to the EOSIO 2.0 release. If you believe this issue is still relevant please feel free to reopen it or create a new one. Thank you for your continued support of EOSIO!
Sign up for freeto subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Labels
CONSENSUSIntroduces a change that may modify consensus protocol rules on an existing blockchain.SNAPSHOTSRequires introducing a new version for snapshots and/or ends support for old versions of snapshots
Background
Deferred transactions make it difficult to sell an EOSIO account to a new owner. An atomic transaction which simply includes two actions, one to change the owner permission of the account and another to transfer tokens to compensate the original owner, is vulnerable to various tactics that could be employed by the original owner to steal back the account.
One of these tactics is for the original owner to propose and approve a transaction in the
eosio.msig
contract which changes the authority of the owner permission of their account back to something that allows them to get back in control of it. Then after completing the sale of the account, the original owner can simplyeosio.msig::exec
that pre-approved transaction and get back the account. Theeosio.msig::invalidate
action was added (EOSIO/eosio.contracts#59) to deal with this particular loophole with selling EOSIO accounts. So the atomic transaction to sell the account discussed earlier could also include a third actioneosio.msig::invalidate
that invalidates any prior authorizations by the sold account within theeosio.msig
contract.However, another loophole still remains using deferred transactions. This tactic is very similar to the previous one: the original owner creates a delayed deferred transaction which changes the authority of the owner permission of their account back to something that allows them to get back in control of it. The original owner of the account then makes sure to complete the sale prior to the
delay_until
time of the deferred transaction, and then simply waits until the deferred transaction retires and reverts control of the account back to the original owner.Unfortunately a change to contract code (even to the system contract) is not sufficient to patch this loophole with selling accounts in a way similar to what was done with the
eosio.msig::invalidate
action. Deferred transactions are a native feature of EOSIO blockchains, and creating an invalidation action that affects deferred transactions requires a consensus upgrade.Consensus upgrade feature
The goal of this consensus upgrade feature is to add a new privileged intrinsic that enables the creation of an action which invalidates any authorizations of a particular account within deferred transactions that were scheduled prior to the call of that action. This action (along with the similar
eosio.msig::invalidate
action) would enable closing the remaining loopholes with selling EOSIO accounts that could allow the original owner to change back the owner permission of the account after the sale has completed.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
INVALIDATE_DEFERRED
will be use to stand-in for whatever the feature identifier will actually end up being.This consensus upgrade feature will require a new
uint64_t
fielddeferred_invalidation
to be added toaccount_object
(or more likelyaccount_sequence_object
to be efficient with undo state size). The extra 8 bytes of overhead per account should be small enough to not require changing how much fixed RAM overhead each account is already charged.This consensus upgrade feature will also require a new
uint64_t
fieldsender_action_sequence
to be added togenerated_transaction_object
. It may be the case that do to rounding up to the nearest multiple of 16, the current amount of RAM that is billed for sending deferred transactions is sufficient to include this extra field at no additional cost to accounts. More careful analysis is needed regarding this point. It may turn out to be the case that the total rounded-up billed amount would need to increase by at most 16 bytes. If that is the case, then additional logic will need to be added to maintain the old billing size prior toINVALIDATE_DEFERRED
activation and switch to the new billing size afterINVALIDATE_DEFERRED
activation.A new
chain_snapshot_header
version is necessary (e.g. version 2) to handle the changes of this consensus upgrade feature. Version 2 of the snapshot will include the newsender_action_sequence
field in the rows of the index forgenerated_transaction_object
and include the newdeferred_invalidation
field in the rows of the corresponding affected index. The new version of nodeos supporting theINVALIDATE_DEFERRED
consensus upgrade feature should not be able to read a snapshot with achain_snapshot_header
version of 1 (this forces the necessary replay from genesis to occur). The new version of nodeos should support version 2 of the snapshot when reading or writing a snapshot.New intrinsic
invalidate_deferred_authorizations
A new intrinsic called
invalidate_deferred_authorizations
which takes an account name should be added to theprivileged_api
. Contracts should only be able to link with this intrinsic afterINVALIDATE_DEFERRED
activation.When this intrinsic is called passing in some account name as the argument, the
deferred_invalidation
field of that account (it should assert it exists) should be set to the global action sequence number of the action that called the intrinsic (should beglobal_action_sequence + 1
).Changes to
apply_context::schedule_deferred_transaction
When both creating and modifying the
generated_transaction_object
, thegtx.sender_action_sequence
field should be set to the global action sequence number of the action that called thesend_deferred
intrinsic (should beglobal_action_sequence + 1
). This should happen regardless of whetherINVALIDATE_DEFERRED
was activated or not.Changes to
transaction_context::init_for_deferred_trx
The
transaction_context::init_for_deferred_trx
function should take a second argumentenforced_deferred_invalidation
of typeuint64_t
.If and only if
INVALIDATE_DEFERRED
has been activated, then (prior to theinit
call) theinit_for_deferred_trx
function should iterate through all the authorizations in all actions in the transaction and assert that the actor of the authorization has adeferred_invalidation
value less than or equal toenforced_deferred_invalidation
.Changes to
controller_impl::push_scheduled_transaction
The call
trx_context.init_for_deferred_trx( gtrx.published )
should be replaced withtrx_context.init_for_deferred_trx( gtrx.published, gtrx.sender_action_sequence )
.How the new intrinsic is intended to be used
A system contract upgrade after
INVALIDATE_DEFERRED
activation could be deployed which introduces a new actioninvaliddefer
that just takes oneeosio::name
. The action wouldrequire_auth
on the provided account name and then call theinvalidate_deferred_authorizations
intrinsic passing it that account name.An atomic transaction to carry out an account sale would then need to include the following actions:
eosio::updateauth
to change the authority of the owner permission of the account to be sold.eosio::invaliddefer
to invalidate all authorizations by the account to be sold in any prior scheduled deferred transactions (whether delayed input transactions or contract-generated transactions).eosio.msig::invalidate
to invalidate all approvals by the account to be sold on any proposed multisig transactions.eosio.token::transfer
to transfer the tokens to the original owner of the account as compensation for selling the account.The text was updated successfully, but these errors were encountered: