Great post. I’ll try to address some of the open questions:
It’s impossible to prove if SGX has been compromised after the handshake attestation but the searcher could use decoys that automated frontrunners are likely to bite, and watch the miner’s behavior. For example, include two transactions. One that puts 1 ETH in a contract with an unprotected withdraw() that only works in the current block.number and an ownerOnly withdraw2(), followed by another transaction that calls withdraw(). Any automated miner would frontrun the second transaction, stealing the 1 ETH and revealing that it violated pre-trade privacy. Discarding the block to frontrun it in a later block won’t work because only the ownerOnly withdraw2() can be called on later block.
Simple decoys could reveal miners that figured out how to compromise SGX, but they’ll only work as long as miners are not aware of them and opt to play the long game by not taking the decoy reward. A smart decoy-generator could make them indistinguishable from other MEV opportunities unless the miner uses a whitelist for known MEV calls.
Probably not. What would stop a searcher from spamming miners with valid blocks and then never propagating them or just doing it too slowly? With PoW this is time critical, so timelocks for letting the miner also propagate the block after a while won’t solve it.
However, why is it an issue? The miner already spent resources and successfully found PoW for the block and can collect the honest reward. Attempting to gain more by mining a new block for frontrunning the searcher is a losing proposition, as someone else will probably mine the block by then. The searcher could (should?) send the same block (with different coinbase address) to different miners, so one honest/greedy miner will likely propagate the block. The censoring miner gains nothing, only loses money.
Therefore I’m not sure if this direction is worth pursuing.
It could. See discussion in Proposer/block builder separation-friendly fee market designs
Since you already rely on SGX security and I assume the validator’s private key only exists in SGX, why not use it to prevent the miner from signing a different block with the same number?
When the enclave is running, it keeps the latest block number it released the plaintext of. The number is updated whenever the caller reads a plaintext signed block. The enclave will refuse to sign any block lower or equal to this number.
This prevents the validator from frontrunning in the current slot. It can either propagate the block, or withhold it and let the next validator take the reward. As long as these two random validators are not colluding, the winning strategy for the validator is to propagate the block.
Note on rollback attacks: SGX doesn’t have its own storage and relies on the caller to provide it upon creation. By default it means that the validator could terminate and recreate the enclave with an old state, and have it sign another block with the same number. The “standard” mitigation is to ensure state freshness using SGX’s monotonic counters which are saved to NVRAM. I wouldn’t use it in this case because this memory wears out after ~10000 writes and the hardware needs to be replaced. Instead, add a forced 10 seconds delay when the enclave is created (as in proof of elapsed time). It can only start signing blocks 10 seconds after boot. It doesn’t affect normal operation but prevents a rollback attack from signing two blocks in the same slot. Enclave restart is guaranteed to miss the current slot.
This seems to be the minimal change to support PoS, as it doesn’t change the architecture in any way, and is invisible to honest validators.