# AA Open Questions This is a collection of some of the open questions around account abstraction for Ethereum. ## Nonce / Tx Uniqueness - Q1: protocol-enshrined nonce or up to contracts? - Q2: Allow multiple txs with the same hash? If protocol-enshrined nonce, we get tx uniqueness for free. If no protocol-enshrined nonce, it is not clear how you could ensure tx uniqueness. One would want tx uniqueness as all current Ethereum tech is built around that assumption. One wouldn't want a protocol-enshrined nonce, because: - problematic for contracts with multiple users, if they create txs with conflicting nonces. Some possible mitigations, e.g. what [Vitalik calls sharding the uniqueness-nonce space](https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020) - Limits functionality, e.g. no "cron job" behavior (recurring txs that are periodically valid) possible Question: How to resolve? Quilt preference: No protocol-enshrined nonce, allow multiple txs with the same hash ## Non-Revertable State Updates After an AA tx is confirmed valid (i.e. the `PAYGAS` opcode is called), the main tx execution takes place. If that reverts, all changes are reverted. Question: Does the contract have a way to make state changes that will persist even if the main execution fails? Motivation: - If we don't have a protocol-enshrined nonce (see above), the contract would definitely need a way to update some internal nonce-like accounting state, which cannot be reverted if the main tx fails. - Even if we instead have a protocol-enshrined nonce, it would be very useful for housekeeping operations (that might be relevant for tx validity determination). Possible ways to achieve such functionality: - simplest: allow `SSTORE` before `PAYGAS` is called. If the main tx fails, only revert to `PAYGAS`. - pro: we already introduce a new opcode with `PAYGAS`, might as well use it as best as possible. Also creates a clear separation: Everything before `PAYGAS` is related to tx validity, everything after is main tx - contra: Restrictions before `PAYGAS` are needlessly extended to this housekeeping, might limit functionality. - contra: Housekeeping would count against tx validation gas limit, although not relevant for deciding validity of the current tx - alternative: Introduce another opcode `CHECKPOINT`. Called after `PAYGAS`, main tx only reverts to here. Could optionally have restrictions of some sort (e.g. only usable in AA contracts, can only be called once per tx, restricted functionality before called) - pro: Increased functionality for housekeeping (can read and write) - pro: Does not take away gas from tx validation - contra: Adds complexity ## Efficient Re-Validation of Pending Txs The first time a new tx reaches a node, the node will have to fully validate the tx by executing it until `PAYGAS` is reached (or it fails or runs out of gas). When a new block comes in that touches the same AA contract, the validity of the pending tx is not ensured anymore and has to be re-checked. Question: Can we structure tx validation as to make re-validation more efficient? Ideas: - somehow split validation into "pure" and "state-dependent" part, only re-run state-dependent part. Naive implementation idea: New opcode. Do pure part first, call `VALID_PURE`, then do state-dependent part, call `PAYGAS`. Re-check only from `VALID_PURE`. Maybe even different gas limits (e.g. more gas for first part, as only run once). Q: Would you need to cache the full stack & memory? How much overhead would that be? ## Calling Into AA Contracts Any update to the state of an AA contract requires all nodes with pending txs to that contract to re-validate the txs, which is computationally expensive. Thus, we need some form of restrictions for modifying the state of AA contracts. The most obvious point at which to enforce these restrictions is at the very beginning of the AA contract code, with limitations around who can call into the contract. - In the simplest version (as [proposed by Vitalik](https://ethereum-magicians.org/t/implementing-account-abstraction-as-part-of-eth1-x/4020)), AA contracts cannot be called into from external user accounts or contracts at all, but only directly from a special `ENTRY_POINT` address. This gives us the clear upper bound of "one tx can at most modify the state of one AA contract". This can also be enforced in a backwards-compatible way with a canonical AA prefix, a short bytecode sequence that compares the caller address to the `ENTRY_POINT` address and reverts if those are not identical. This is the variant Quilt is implementing for our MVP. You can see the canonical bytecode [here](https://github.com/adietrichs/aa-tools). - pro: simple, backwards-compatible (old tooling can "understand" AA contracts) - contra: More restrictive than necessary, e.g. no read-only access for other contracts - contra: In the naive implementation, no way to send ETH to an AA contract (so in this version probably not feasible) - contra: No way to have users pay for interactions with AA contracts - contra: Some overhead for every AA contract (currently 2 bytes) - Modification: Allow for receiving ETH. Same idea, but modify the canonical bytecode to allow incoming ETH transfers (optionally ensure empty calldata). - pro: Still simple, now seems feasible. - contra: Same as above, now with higher overhead. - Alternative: AA contracts as a third type of account, with more comprehensive special handling: In addition to transactions from the `ENTRY_POINT`, one could also allow read-only calls from other contracts. In addition, one could allow for "full" (i.e. read-write) access from other contracts or via txs from user accounts, as long as the "one tx can at most modify the state of one (or n) AA contract(s)" invariant holds (or maybe a more precise invariant, e.g. "modifying the state of one AA contract costs at least X gas"). This could e.g. be enforced via "each tx is only allowed to call into at most 1 (or n) AA contract(s) during its execution". Txs would probably have to contain an extra field for the AA contract(s) they want to access, to allow for mempool management. - pro: maximum functionality within the given constraints - contra: more complex, third account type is a huge change ## Understanding the Performance Bottlenecks for AA Question: What exactly is the computational bottleneck for AA? Thoughts: - AA txs are more computationally demanding than normal txs for two reasons: - Higher computational cost for validation - State-dependent validity, so need to re-validate pending txs each time new blocks touch the tx's destination AA contract - Two sources of validation work for a node: - Incoming new AA tx from a peer (that has to be validated) - Incoming new block that touches one or several AA contracts for which the node has pending txs (that have to be re-validated) - Invariant around "Incoming new block" work: Limit on how many txs have to be re-evaluated in the worst case: - "one tx can at most modify the state of one AA contract" together with "only one pending tx per AA contract" => "one tx in a new block can only cause one pending tx to be re-evaluated" - relaxations, e.g.: - "one tx can at most modify the state of n AA contracts" - "only n pending tx per AA contract" or "only xxx total gas for txs pending per AA contract" - Invariant around tx validation in general: gas limit for validation - possible modification: split "pure" and "state-dependent" validation, stricter gas limit for "state-dependent" validation => less gas for re-validation - Possible "Incoming new AA tx from a peer" restrictions: - maximum gas per peer per time - blacklist after xxx invalid txs or gas (maybe communicate block for which tx has to be valid?) - general "slow mode" if computational load too heavy? ## To Add: - how is gasLimit specified - by tx (gasLimit field or calldata?) or via `PAYGAS` (like gasPrice)? - validating multiple txs for same contract - execute full txs or only validity checks? - Efficiently check if contract is AA - maybe store an "AA boolean" as metadata locally together with contract data? - Answer: Probably not necessary? - Tx relay between nodes: attest to validity & gasprice at block height (either before sending full txs or together with txs), drop peer for any incorrect attestation - how does that work with normal txs?