CAP: 0009
Title: Linear/Exterior Immutable Accounts
Author: Jeremy Rubin
Status: Draft
Created: 2018-13
Discussion: None
Protocol version: TBD
When we are aspiring to merge an account and remove trustlines, we need to get our account in a predictable state. This CAP introduces Linear Accounts (or Exterior Immutable Accounts) which restricts an account to only allow transactions where the account is the source to modify the account.
Sometimes we want to be sure of exactly what the state of an account is when we are generating certain operations: we want to know exactly how much balance should be available, we want to know that no sequence bumps can occur externally, etc. Currently it's difficult to ensure this.
Linear Accounts are a sort of "critical section" mode for an account which prevents outside operations from taking place.
Currently, when you want to merge an account you send all of the available lumen balance to the merge recipient -- but what if a new payment just came in! They'll get more money than expected! This is ok sometimes, but usually is a big problem!
This problem is even worse for trustlines. Trustlines have a limit. In order to remove a trustline it must have no assets in it, otherwise it will fail. If a transaction sends all the balance in the trustline (which must be explicitly declared) and then reduces the limit to zero, the transaction may fail if another transaction sends funds to the account before it. An attacker can use this to essentially DoS account merging by pinging one stroop of random assets to your account.
This prevents merging because all trustlines must be removed to merge.
For Linear accounts, we introduce three new flags, AUTH_EXTERIOR_IMMUTABLE
,
AUTH_EXTERIOR_IMMUTABLE_ACTION
, and AUTH_PARTIAL_LINEAR
.
If AUTH_EXTERIOR_IMMUTABLE
is set, then transactions which attempt to modify
the state of the account in any way are either invalid or fail (determined by
AUTH_EXTERIOR_IMMUTABLE_ACTION
-- set : fail, unset : invalid), unless the modification occurs as a result of
an offer executing or a transaction with the account as the source.
If AUTH_PARTIAL_LINEAR
is set, then operations which modify the account simply
encumber an additional signature obligation on behalf of the account being
modified. This signature is unique in that if a EdDSA signature, it signs SHA256(AUTH_PARTIAL_LINEAR || TX Hash || Account Modified)
. Such signatures replace signatures from the same key already on the
transaction if present, and must come after all regular signatures in the
DecoratedSignature list.
If AUTH_IMMUTABLE
is set, then the flags may not be changed (continues to work
as before). AUTH_EXTERIOR_IMMUTABLE
, AUTH_EXTERIOR_IMMUTABLE_ACTION
, and
AUTH_PARTIAL_LINEAR
may be set when AUTH_IMMUTABLE
is set.
This design accomplishes several orthogonal goals:
- Temporary suspensions of mutability (achieved via
AUTH_EXTERIOR_IMMUTABLE_ACTION=invalid
) which is assumed to quickly resume. This allowss for whatever critical section to be handled without needing to re-sign transactions - Permanent suspensions of mutability (achieved via
AUTH_EXTERIOR_IMMUTABLE_ACTION=fail
) which permanently prevents the transaction from succeeding. - Receiver-approved transactions via
AUTH_PARTIAL_LINEAR
/not invalidating things which have already been signed via a pre-signed transaction. - Provides a mechanism (via
AUTH_IMMUTABLE
) to prove that this will never be enabled.
The EdDSA signatures are special cased to include the account they are signing on to prevent the 'confused deputy' from accidentally authorizing a transaction linearization where it was not desired. It is not particularly expensive given the mandate that 'confused deputy safe' signatures come after regular signatures. If a future CAP eliminates confused deputy issue, then these signatures shall still be required to explicitly approve the partial linearity.
At first glance, it may seem like this introduces many new ways for transactions to fail or be invalid. But it does not, because simply merging an account has the same types of effects -- if the source account of an operation doesn't exist, then the transaction is invalid, and if the destination of an operation doesn't exist, then the transaction fails.
Therefore this doesn't materially impact the status quo, other than making it possible/easier for developers to control accounts.
None yet.