Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.Sign up
Account abstraction for main chain #859
The following is a copy of the account abstraction proposal discussed here but coalesced into one piece and adapted for the ethereum main chain by adding back in mandatory in-transaction nonces.
A new type of transaction is allowed, with the following format:
Executing a transaction of this format is done according to the following rules:
If any of the asserts fails, the transaction is invalid. Note that this includes the assert in step 5; that is, if a top-level transaction execution fails, and PAYGAS_CALLED is False, then the entire transaction is invalid.
The abstraction is simplified with a new PAYGAS opcode. PAYGAS simultaneously serves two purposes:
We add two variables to the execution context (ie. in a similar position as the selfdestructs list): PAYGAS_CALLED and PAYGAS_GASPRICE, initialized to False and 0 respectively. The PAYGAS opcode takes a single stack argument,
The owner of an account will generally want to have account code that looks something like:
Where the transaction data encodes the signature as well as the destination, value, gasprice and data of the intended message that is to be sent from an account.
It will be possible to send ETH to not-yet-created accounts by simply computing their address from the hash of the init code, and initializing the code for such an account would be done at the same time as sending the first transaction.
We note that any transaction whose execution reaches the PAYGAS opcode is guaranteed to pay for gas, even if the execution exits with an exception after that point, and any transaction that exits with an exception before reaching PAYGAS will not be includeable into a block.
Miners can use the following strategy to accept transactions. Every miner can set a private value, CHECK_LIMIT, eg. to 200000. When a miner or network node sees a transaction, they execute it on top of the current head state for a maximum of CHECK_LIMIT gas (the 200-per-byte cost of creating a new contract does NOT count toward the limit). If the transaction execution hits PAYGAS before this limit, then the miner or network node accepts the transaction and acts as though the gasprice called with PAYGAS is the transaction's gasprice; if it does not, then the miner or network node rejects the transaction.
When a miner actually includes transactions in a block, PAYGAS may pay a different gasprice than when the miner first saw it, for example if the argument to PAYGAS depends on state; in this case, throw out the transaction if the gasprice is lower than it was during the first scan.
Setting CHECK_LIMIT is a simple tradeoff: if CHECK_LIMIT is higher, miners can accept transactions from accounts that make more complex checks before calling PAYGAS (eg. Lamport sigs, threshold sigs), but setting CHECK_LIMIT higher also makes miners more vulnerable to DoS attacks. Miners may want to start off with high CHECK_LIMIT but dynamically adjust it downwards if they detect a DoS attack to keep CPU usage below some threshold.
Specification version 1.1
What does this abstract and what does it not abstract?
referenced this issue
Jan 31, 2018
My notes after reading through this, and asking @vbuterin about some points.
Note, this is the same as
During this step,
This is the step where
The differences here are important; since
Note: Vitalik preferred option 2, reasoning there might be situations where a user submits multiple transactions, and it's difficult to know which will make it in first.
Clarification, if a transaction
: Reorg-attack in brief: When a user creates a contract A (perhaps his own multisig-wallet), a reorg (perhaps created by a malicious contract), can create a replica contract at A. Any transactions the user then makes to the contract (e.g. sending money to it), will now go to a multisig-wallet created by another user.
This was referenced
Feb 9, 2018
No. This design still requires transactions with the same target account to have sequentially incrementing nonces. It's the sharding abstraction proposal that doesn't have that feature, and which doesn't even care (at least at protocol level) if the same transaction gets included in the chain multiple times.
It may be too late, but listening to the last core dev call it sounded like this isn't going to make it into Constantinople. This makes me sad, so I wanted to make an attempt to get people to reconsider.
Requiring non-abstract accounts is an ugly hack that makes a lot of things I want to build hard or impossible. The most obvious is that projects I've worked on have often wanted to pay for their users' gas, so that users aren't required to purchase Ether on an exchange in order to use our application. Without account abstraction, you have to do a difficult and imperfect dance involving sending small amounts of gas to each user's account, reimbursing them over time, topping them up if transaction costs rise, etc.
A related annoyance is that it is harder to experiment with alternative ownership models, like native multisig wallets, zero-knowledge-proof-based contracts, ring signatures, etc. You can mostly do it, but you have to keep an account with a small (but not too small) amount of ether around, to actually send the transactions.
Finally, I've been planning a project that attempted to use account abstraction in conjunction with on-chain decentralized exchanges to pay for gas using ERC-20 tokens (I'm pretty sure you can do it in under 200k gas if you're careful), which I won't get to do until account abstraction is released.
I understand that development time is limited, but account abstraction has much more relevance to my job and my hobby projects than Casper does, so I thought I'd at least make the argument. :)