![](https://cdn.discordapp.com/attachments/1154872709436690472/1195830576716988546/potuz_censorship_68842344-18c3-4bdb-917f-f958a53964cb.png?ex=65b56b02&is=65a2f602&hm=d92d6256eb4d1cd8aeace8c312e7cd9cb9e075e0a56bcc47fab3b32076d73eb7&) # Heuristics for Detecting Censorship As Ethereum has evolved in the post-merge era, we find ourselves in a mixed status between centralized and decentralized systems for block production and transaction inclusion. While the validator set can be considered reasonably decentralized, even with concerns over staking pool centralization, with 900,000 active validators at the time of writing; the same cannot be said about block producers: According to data from [mevboost.pics](https://mevboost.pics/), over 92% of blocks are being produced via MEv Boost (outsourcing to external builders). Of those, according to [relayscan.io](https://www.relayscan.io/overview?t=7d), 95% were relayed by just 5 relays, and 77% of those blocks were produced by the top 3 builders. Three of the 5 mentioned relays actively censor transactions from certain known addresses, while the other two we must trust not to. Visit [this site](https://censorship.pics/) for more accurate and up-to-date information on the current status of censorship. If Ethereum wants to claim credible decentralization and censorship resistance, we must do better than this. There are several proposals floating around to deal with this situation, ranging from the simplest ([already implemented](https://github.com/ethereum/execution-apis/pull/425)) inclusion of a flag that the local execution client uses to inform the validator node that it must not use MEV-Boost in its next proposal due to active censorship, through inclusion lists, and [ePBS](https://github.com/potuz/consensus-specs/blob/epbs/specs/_features/epbs/design.md). ## The Need for Some Heuristics All three of these approaches require the execution layer to implement some heuristics to inform the validator that there is some form of censorship happening in the network. Let's consider the simplest feature. When a validator is about to propose a block, and assuming it will use MEV Boost to request blocks from a builder, it requests, in fact, two different execution blocks: one from its own execution client and another from the relays (that relay payloads from builders). The beacon node performs some basic comparisons to decide which block to use. For example, by default, proposers will choose to use the local payload if the builder is offering less payment. Other checks are performed to ensure that the builder's block does not contain errors that would render its block invalid. We check that the number of withdrawals is correct, that the timestamps, and other metadata match what is expected, etc. Together with the block, the local execution client returns a boolean flag `shouldOverrideBuilder` that, if set, the beacon node **may** (and should) not use the builder's block and instead fallback to local execution. How does the local execution client decide when to set this flag? A similar construction would arise when using inclusion lists, something that we mostly believe to be mandatory in the path for the protocol enshrined proposer-builder separation. In these setups, the proposer of a block would inform beforehand some transactions that it wants to be included on-chain. There are different designs, perhaps the most liked one is the one that forces these transactions to be included [in the next slot](https://github.com/ethereum/EIPs/pull/7943). In any such construction, the proposer will require first to its local execution client to produce a list of transactions that it thinks are being censored so that they are a requirement for the next builder to include. How does the local execution client decide which transactions to automatically provide? This is the main objective of this short writeup, to give some basic heuristics that can be easily applied in the execution client software, perhaps user-configurable. ## Reasons for Censorship There are different reasons why proposers or builders may incur in censorship, the most common one that is being talked about constantly is to prevent transactions that have interacted with certain contracts or addresses that have been banned in certain jurisdictions. These are transactions that some builders do not want to include in blocks because they fear that they may be legally liable in those jurisdictions. There are other, perhaps more impactful types of censorships. Consider the case of a rollup, be it either an optimistic one or a ZK rollup. Censoring nodes may want to delay information from the rollup arriving in L1, that is, they would censor any transaction where the batch of transactions is being posted (in the optimistic case) or where the proof of state is being posted (in the ZK case). In the optimistic rollup scenario, there is an even more dangerous situation: imagine an L2 with a permissionless challenge protocol where the sequencer decides to post an invalid state transition. Honest validators on L2 would immediately realize this bad state and would want to assert the correct state by sending a challenge to the rollup contract in L1. The sequencer may be trying to extract enough capital from L2 that it may be worth it to coerce with enough validators/builders on L1 as to censor these challenge transactions. ## Ways of Censoring The most naive way of censoring is simply not including these *unwanted* transactions in blocks. This is the common situation for those transactions that interact with some contracts that may be banned in some jurisdictions. Since there is currently at least 8% of validators that still produce local blocks, and it is reasonable to expect that these validators run unmodified software with default configurations. These transactions typically make it on-chain [relatively fast](https://www.mempool.pics). There is, however, a more dangerous form of censorship, which would be applicable, for example, in the case of a rogue L2 sequencer which wants to rug the whole rollup: censor those unwanted transactions whenever the builder is part of the cartel, but even if some proposers/builders are non-censoring and they manage to include these transactions on-chain, then reorg the blocks containing these transactions. This type of censorship is much more complicated to apply in practice as it requires not only a cartel of builders but also a cartel of validators attesting against the non-censoring blocks. We believe the validator set of Ethereum is mostly decentralized, but these claims need to be contrasted constantly with the increasing centralization power of staking pools (at the time of writing, Lido's stake is over 30% of the total stake). With the advent of restaking and other mechanisms, capital locked in rollups or other sidechains may be sufficient enough to entice this type of attacks. ![](https://cdn.discordapp.com/attachments/1154872709436690472/1195834784929292388/potuz_freedom_33713730-cb12-4e8e-ab5b-768b7d8ecc4b.png?ex=65b56eee&is=65a2f9ee&hm=128c3964d7e8acddeb3edeb117224942b812d78505b75dc8cedec651473f9a39&) ## Some Simple Heuristics Fortunately, there are very simple heuristics that can be implemented in the execution client software that would guarantee some sane defaults, both in the case of the `shouldOverrideBuilder` flag as well as the inclusion list mechanism for PBS. ### Track High Paying Transactions If there are transactions that are paying tips much higher than the maximum tips in the last few blocks and haven't been included in two consecutive blocks, then there is active censorship. ### Track Waiting Transactions If there are transactions that have been paying more than the median tip in the last few blocks and have not been included in the last 5 blocks, then there is active censorship. More generally, one could envision a curve tip/waiting-time so that if there are transactions on one side of the curve, there is active censorship. There is an extra dimension to this problem which is the number of such transactions. For lower tips, validators may want to tweak their ELs to allow a minimal number of transactions to be censored, something of the form "if there are more than `x` transactions that pay at least `y%` of the median tip in the last few blocks and have not been included in `z` consecutive slots, then there is censorship". And they may want to put numbers like `x = 3` for `y=50` and `z = 4` while perhaps `x=0` for `y=5000` and `z=2`. ### Tracked Reorged Transactions If we ever find ourselves in the situation where the strong reorging form of censorship is happening, then we most probably have a compromised consensus layer. However, given that this is one of the most important aspects of the blockchain (censorship resistance together with decentralization and permissionless validation), we would do best to have sane defaults. One simple such heuristic would be on each reorg, get the list of transactions that were included in the orphaned block and not in the reorging block. Execution clients do this anyway today by re-adding those transactions to their mempool. If the same transaction is found to have been reorged twice, then a signal of active censorship to the node. ### Track Interactions with Specific Addresses This is a no-brainer. Let the user specify a list of addresses so that if there are enough transactions (again parameters can be tweaked as above) that have not been included long enough and interact with those addresses, then a signal of active censorship to the node. ### Track Addresses Not Being Included If there are enough transactions that are trying to interact with a given contract and have not been included on-chain for enough blocks, signal active censorship to the node. From the whole list, this one seems to be a bit more complicated to implement (at least with my diminute knowledge of mempool implementations) therefore I would not expand on it. ## Client Diversity is a Plus Client diversity plays in our favor here, the entire list of heuristics is completely optional. Some may want to not implement anything and simply return that there is no censorship by default (I hope this is not the case, however). Some may want to implement a subset of the above list, or different ones not included here, and even if clients implement the same list of heuristics, they may have different defaults for the thresholds listed here. Being as diverse as possible helps to make it more difficult for censors to play the system.