Skip to content
This repository has been archived by the owner on Aug 2, 2022. It is now read-only.

Consensus upgrade to allow invalidating all prior authorizations in deferred transactions #6118

Closed
arhag opened this issue Oct 23, 2018 · 4 comments
Labels
CONSENSUS Introduces a change that may modify consensus protocol rules on an existing blockchain. SNAPSHOTS Requires introducing a new version for snapshots and/or ends support for old versions of snapshots

Comments

@arhag
Copy link
Contributor

arhag commented Oct 23, 2018

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 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.
@arhag arhag added HARDFORK SNAPSHOTS Requires introducing a new version for snapshots and/or ends support for old versions of snapshots labels Oct 23, 2018
@hama
Copy link

hama commented Oct 25, 2018

Great

@arhag
Copy link
Contributor Author

arhag commented Dec 7, 2018

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.

@StarryJapanNight
Copy link

This is an excellent proposal. Any timeline plan?

@arhag arhag added CONSENSUS Introduces a change that may modify consensus protocol rules on an existing blockchain. and removed HARDFORK labels Mar 22, 2019
@aclark-b1
Copy link

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 free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
CONSENSUS Introduces a change that may modify consensus protocol rules on an existing blockchain. SNAPSHOTS Requires introducing a new version for snapshots and/or ends support for old versions of snapshots
Projects
None yet
Development

No branches or pull requests

4 participants