New Ethereum talks, every Monday. The week's conference uploads by event, in your inbox.

Loading player…

Yoav Weiss 🛸 Account abstraction is easy… unless you care about censorship resistance

ETHGlobalWed, Oct 9, 2024, 12:00 AM

Speaker

'censorship.wtf' Talks and workshops took place in both ETHGlobal Istanbul, DCxPrague During Devconnect 2023. A full day was spent discussing censorship resistance in the context of Ethereum L1, rollups, applications, infrastructure, hardware, and more. As Ethereum becomes more consequential and its growing ecosystem complexifies, opportunites & pressures to censor increase. While these risks do get discussed, conversations on censorship resistance often center on a specific part of the stack — censorship.wtf was an attempt at approaching the topic head on. ----------------- Follow us: https://x.com/ETHGlobal?s=20 Check us out: https://ethglobal.com/ Email us at: hello@ethglobal.com

Transcript

[Music] so today I'm going to talk about about account obstruction but not H not as usual about use cases but to focus on a on a censorship resistance and why it is harder with account obstruction so in order to in order to understand this we need to think what what is an account and one way to look at an account is H The Entity that can operate on chain as a that can operate on chain directly without any intermediaries and EA satisfies this requirement with an EA externally owned account you can sign the transaction you send it to a mempool and it gets included a smart contact wallet unfortunately doesn't uh doesn't satisfy this requirement and you cannot use um you cannot use it directly on chain you need the help of another account of an EA in order to operate it and uh this creates a big ux problem because we're not going to be able to bring the next billion users that we like to talk about if we need them to uh keep two funded accounts one for gas one for everything else and to sign each transaction twice once for the Gas payment and once for the actual transaction so um what can we do so the common approach until ERC 4337 was to use a centralized centralized relayer uh and chances are that if you're using a non 437 smart account that you are using such centralized relay the way these relays work is uh by having um is by sending a what's called a meta transaction basically the the user signs a transaction that cannot be used on chain directly it sends a transaction to a sends a transaction to a to a relay the relay signs the transaction with an EA that is funded it's owned by the relay by the Relay operator puts it on chain then this this met meta transaction gets peeled off by the um by the smart contract wallet which handles the transaction and then reimburses the reimburses the relay and uh now that's uh this approach works but clearly it's not great for sensorship resistance because I mean it works as long as it works but what happens if for example the company of the the company that runs the relay goes bust so uh they stop paying their Amazon bill and suddenly you're trying to transact to your account and it doesn't go through so there's a so there may be a liveness issue or maybe uh maybe the server maybe the server gets attacked someone someone attempts to denial to do a denial of service against the server at the at the worst possible time for you and that's exactly when it's going to happen because it's not random uh then the server operator could also extract me because uh you know they they get to delay your transactions when there is price action in order to font run you with 100% success because you cannot win a race against the server you're interacting with so there's the there's this issue and of course the plain old the know simple sensorship because the server is operated by human and humans can be coerced so someone might get the server to censor you at the worst possible time or there's just the Privacy issue where the server the server keeps loged so it knows your IP address which is associated with your real identity and it sees your transactions and you don't know who they're sharing it with so we need a better we need a better approach now the naive solution would be let's have many servers let's say run multiple servers but that's not really decentralized because if these servers are operated by the same entity then uh they are going to censor you together they're going to go down together so the next logical step would be let's make it a decentralized and incentivized network which is what we did a few years ago with the GSN the the gas station network so there's a network of there's a network of relays that uh that get paid to do the work it's a permissionless anyone can join and you can use it to uh you can use it to send meta transactions how however there's a catch there's a catch when using this uh to uh to manage a smart account what if the account behaves inconsistently maybe I me it's not deterministic so when the server uh when the relay when the relay sees the transaction it looks like it's going to H it looks like it's going to reimburse it and to pay to pay it but uh when you put it on chain it actually doesn't it detects that it is now running on chain and it doesn't pay so the Rel can lose money and and we need to mitigate this uh we need to mitigate this risk so there are several mitigations that may seem possible but each of them actually hurts sensorship resistance for example we could have um so we could H we could keep a white list of known account implementations so the server only agrees to serve these accounts that it knows are not going to grief it but then who gets to decide which which account implementations are legit itate and which ones should not be served so that's not a great approach another one is to whitel list users let's have the users open a username with a capture or something open a username on the server and if a user misbehaves and doesn't pay even just once you stop serving that user so that works but it's a permission system and if you can block a user H for not paying then you can also block the user for other for other reasons so we are back to the sensorship problem or you could just try to keep reputation for accounts don't don't require users but if an account doesn't pay then H you stop serving it that approach doesn't work because of H because of a lack of Cil resistance anyone can spin up any number of accounts and keep gripping griffing the server until it's out of funds so the server might try to uh might try to be clever to simulate the transaction make sure that it pays and then use some something like flash Bots send it to the flashboot relay and ask the relay to only include it if it's if it pays if it doesn't uh if it if it really pays the fee so that would work until someone is determined to attack it but when someone does want to sensor it they're going to flood it with the non-deterministic transactions that are going to not pay on chain and flashboot will spend a lot of CPU simulating it but never but these transactions will never never be included after a while H flash boots will h block this uh will block this relay and we are back to square one so clearly we need uh uh we need a better approach we need an approach that takes these things into account otherwise we end up either with a vulnerable Network or with one that is permissioned and uh cannot uh and cannot offer a sensorship resistance so ERC 4337 aims exactly to solve this problem it focuses on fully abstracting uh on fully abstracting the account without compromising on a sensorship resistance so there are no centralized components there's no uh there are no centralized component and nothing is permissioned in the system and because it's h because it's a full account obstruction it means that H the validation is actually an evm bite code getting executed which opens up many attack vectors that we need to address right so what does the protocol need to achieve in order to solve this first of all we need it to be permissionless for bundlers anyone should be able to add bundlers to the mol and uh these bundlers should these bunders should be able to offer their services but not to uh do anything bad to the user operations and we need it to be permissionless for users any user should be able to propagate something into the mol and no one should be able to censor it we need to ensure that bundler are that bundlers get compensated for the work as long as they do it correctly and they cannot be griefed because if they can be griefed then H if they can be griefed they will lose money they will go down and we will not have a network and we need to protect the entire network against denal of service attacks which are which can be surprisingly easy to perform against such a network so uh okay so so first of first of all what we needed to do I mean how do we achieve this the the one thing we had to do first is to split the transaction to two phases we have a validation phase and execution phase in validation you have um so in validation you could have a separate gas limit so let's say you have a 5 million 5 million gas transaction that would be very expensive to simulate but you can limit it you can say that it has a validation gas of only 200k which means that the amount of C CPU you have to spend simulating the transaction to decide whether it's uh whether you should include it is is very limited so the CPU impact the CP CPU impact per transaction is much is much lower this way then we need to also uh we need to also make sure the transaction is deterministic if it is valid if it's valid in simulation it needs to also be valid on chain that means that we cannot allow environment access such as block number during uh during validation you can use any op code you like during execution but certain op codes should not be used during validation and you really don't need them I mean you don't need to look at a block number to validate your signature so um so otherwise you could have a you could have a transaction that uh you could have an account that is for example valid during even blocks and invalid during odd blocks so now someone could propagate a transaction to the mol that is currently valid because the last block was a was a an even one but then when someone tries to include it on chain in the next block which is odd it's going to revert so we prevent that by not accepting the transaction if it accesses the block number even if it's uh uh even even if it would currently be valid so there's so we have a list of these environment op codes that are banned and another problem we had to deal with is mass invalidation that means H doing performing a denial of service attack against the entire network by sending a very large number of transactions that are valid so they do get propagated but then invalidate all of them by front running them with one transaction that makes a state change making them all invalid on chain so that would keep the that would keep all the nodes constantly busy doing unpaid work and unable to perform any any paid work so to prevent that we needed to enforce certain storage rules such as uh the account should not during validation the account can access its own storage or storage associated with this address such as a mapping of H mapping of this address in other contracts but it cannot access anything associated with other accounts so this means that um uh this means that in order to invalidate in order to invalidate end transactions you need to write to to actually write on chain to end slots and that's extremely expensive so this attack doesn't scale then we also need to make sure that if a transaction is valid alone it is also valid on chain together with other uh with other transactions in the same bundle because otherwise someone could produce a transaction that invalidates another transaction now we already established in the previous rule that transactions that validations cannot during validation transactions cannot access ER the storage associated with another account so validations cannot invalidate each other however execution can so if for example we had a transaction that uh we have transaction one which during its execution modifies a state that transaction two uh validation we look at and then transaction one can invalidate transaction two so this would make it very hard to build a to build a valid block or to build a a a valid bundle to prevent that we perform all the validations before any execution so the validations cannot invalidate each other and by the time any execution runs everybody all the accounts already agreed to pay for the gas so now if they're going to mess with each other they could revert each other's transaction but still they pay the gas so the network is safe against this denar of service now uh there are some Global entities in the system such as a pay masters Global entity means that uh it could The Entity could be used in the context of multiple accounts at the same time for example a pay Master sponsoring the transactions of multiple uh of multiple accounts during the same bundle but this means that if it is allowed to access its own storage it could keep a flag to detect that it's running in a bundle that it gets called twice and then uh and then invalidate the bundle since we cannot fully prevent this attack we had to um we had to also add an enforcement through a reputation so if it causes so if a pay Master if a if if such an entity cause causes a lot of validation H then it will get throttled it will get throttled by the by the mol so nodes will stop propagating and serving it but uh it wouldn't work if if we don't have Cil resistance because then someone can keep deploying more and more of these entities so introduce staking now it's not classical staking in the sense that it cannot get uh you cannot get slashed but it has an unstake DeLay So it serves as Cil resistance you can uh if you want to if you get throttled if a pay Master get throttled and it wants to deploy with a new address it has to either wait for the unstake delay in order to restake or it needs to stake an additional amount so to sustain the attack you need to keep staking more and more funds which makes it not scale so I think for for the sake of time I'm going to skip some uh to skip some some other attacks but as you can see we have we had to cover numerous uh attack vectors and try to reach to a to a minimum set of restrictions during validation to keep everything uh permissionless and uh still safe against attacks right U skipping a bit but um so why do why do all the bundlers need to to implement exactly the same protection technically you could would have a slightly different rules that still achieve the same level of protection so the reason the reason to have this as a standard where everyone is enforc the same rules in is related to another form of Dos against the against the network because let's say if you wanted to uh if you wanted to Dos this peer-to-peer Network and remember that it's permissionless you could set a node that keeps spamming other nodes sending them a lot of invalid transactions that uh use that that all use the maximum uh the maximum allowed validation gas and then say no it's not valid and then you could keep the network busy but um so we need to prevent that and the way nodes handle it is if they receive a transaction that is valid the transactions are always propagated together with the block hash they were validated against and if if as a node you receive a you receive a transaction you see that it's invalid when simulated against the same uh the same stay the same block hash it means that someone is trying to Dos you because there is no legitimate reason for it not to be uh not to be valid so in that case you treat it as a spammer and you block it now what happens if the BL if we have slightly different implementations of the rules in different bundlers what would happen is the bundler someone would propagate a transaction that is valid for some but invalid for others so they would treat each other as spammers disconnect from each other and we end up with a lot of small fragmented me pools instead of one big mol is that a problem so it is especially if you if you think about sensorship resistance because each such M Pool is small it has less nodes so the less nodes you have in the mol the easier it is to sensor you it becomes Much More Much More centralized we also lose the robustness of the multic client approach because ERC 437 took the same Approach at ethereum where we have multiple clients uh we have like a multiple bundler implementations with different programming languages so it's unlikely that the same bug will exist everywhere but if each implementation has its own rules then we are going to end up with a a mol per implementation so now a single software bug could take down an entire M Pool and the users will not be able to propagate it and we also lose Economic Security because now each M Pool only has a small subset of the of H of all the of all the available transactions so it cannot construct the most profitable bundle which means that there is less incentive to participate in it so you get less participants so to prevent this we need to have a multiple implementations of the bandler but only compatible ones and ethereum needed to deal with the same problem and found solution for it because ethereum has multiple clients but it uses um but it has very clear specs of how they should behave and we are a and we have a lot of testing we have a reference implementation we have compatibility tests we perform fuzzing to try to detect cases where it would break consensus so ERC 457 takes exactly the same approach we have a we have a specs for the rules we have a reference implementation we have compatibility tests and once the peer-to-peer network is up we're going to fast the hell out of it so to conclude uh with we see that it's really easy to design an account obstruction protocol if you don't care about account obstruction but once you start thinking about it and going down the rabbit hole of decentralization it becomes infinitely harder and that's why it took us a couple of years to get it right and hopefully we did um now uh smart account developers wallet developers generally don't care about censorship resistant they they would they could even use a centralized RPC they don't care about it they only care about user featur and that's okay because they're a product as a product they're building a product when you're building a product you care about user features you don't think about worst case scenario that your users don't care about until it happens so in order to get sensorship resistance they could just use an SDK that makes full use of ERC 437 and then they get sensorship resistance for free and uh but this free sensorship resistance actually is provided by the bundlers so it can it only works if you're using a compatible bundler which unfortunately not all bundlers at the moment are so if you are going to run a bundler you should pick one from the list there's there's a list that gets generated by the tests and it shows you which ones pass the test so you should choose one that is compatible and then soon when the MEO the peer-to-peer Network comes up it will be able to participate and get the full benefit of it uh right and uh thank you very much

Automatic transcript — names and jargon may be misspelled.