Encrypted Mempool V1
Motivation
Right now there is a lot of MEV in this ecosystem. Previously we locked down tx priority so that can't be exploited, but people are still spying on transactions in the mempool and landing MEV transactions before their target reaches the validator with little to no risk by abusing slippage tolerance and co-locating.
This is why the previous idea of locking transaction ordering based on a secret that is not known until after the block is made would have ultimately failed and actually would have made it easier to MEV -- because the MEVers can spam 0% slippage transactions, they have a much higher chance of succeeding with a random tx ordering than if tx ordering is based on arrival time.
Thus in Bittensor the only way to have truly robust protection against MEV (other than the usual things all users should be doing such as setting slippage tolerance to something reasonable whenever they stake/unstake), would be a solution that makes the mempool iteslf completely opaque to MEVers until the block is already locked in. Any ecosystem with configurable slippage tolerance needs a completely encrypted mempool to be MEV-resistant.
We have a long-term plan for how we might accomplish this under decentralized root validators after we move away from POA that is censorship resistant and completely trustless. The idea involves implementing our own custom League of Entropy across our validator nodes in which the block-maker must cryptographically commit to an ordered set of encrypted transactions before the rest of the league will provide their respective entropies.
This plan, however, would take a long time to implement and we can test the general thesis under POA in a much quicker to implement, simpler way:
The Plan
While we are still under Proof of Authority, we can safely implement the following plan for providing opt-in encrypted staking and unstaking transactions that are impossible to MEV:
- Each block, the POA validators will generate a public/private keypair, which will be gossiped either through a transaction or an event (whichever is easier for light clients to consume continuously). This will also have to be in an easily accessed in a storage so things like smart contracts and clients can read it whenever they need it statelessly.
- We will make a nested call extrinsic (similar to proxy/sudo/etc) that expects the encoded bytes of a call inside of it, but encrypted using the latest public key.
- Client-side when users are submitting their staking transactions, the client will automatically see the latest public key and will be able to use this to encrypt staking/unstaking transactions and anything else that can be MEVed. This will have no effect on existing client code since the encryption behavior is opt-in and completely optional.
- The event that emits the next public key will always happen exactly 7 seconds into the block time. Transactions encrypted with the old key will still be accepted as late as 9 seconds into the block time. At the 9 second deadline, transactions encrypted with the old key will no longer be accepted and will fail, giving clients a 2 second grace period to switch to the new key. Transactions that arrive using the new key before the end of the current block will be held until the next block
- Client-side, the client will watch for the new public key event and will switch to the new key the moment it becomes available, ensuring that no one ever submits a transaction encoded with the old key.
- During the last 3 seconds of the block, the validator will decrypt all encrypted transactions and attempt to execute them along with the unencrypted transactions. Some will fail, which is fine, the user will still pay the fee for the enclosing transaction.
With this setup, anyone can encrypt any transaction in such a way that no one else can read it but the POA validator until it has already executed, making it immune to MEV.
If this works to combat MEV, then we will consider doing the longer/harder version of this when we move away from POA
How will this work after the switch to NPoS?
Will this be an optional encrypted mempool? so if user wants to encrypt his tx, he can? Would be really sweet to switch to nominated proof of stake(NPOS)
@liamaharon
How will this work after the switch to NPoS?
See the notes above about when we move away from POA:
We have a long-term plan for how we might accomplish this under decentralized root validators after we move away from POA that is censorship resistant and completely trustless. The idea involves implementing our own custom League of Entropy across our validator nodes in which the block-maker must cryptographically commit to an ordered set of encrypted transactions before the rest of the league will provide their respective entropies.
Will this be an optional encrypted mempool? so if user wants to encrypt his tx, he can? Would be really sweet to switch to nominated proof of stake(NPOS)
Exactly, it's completely opt-in, another nestable extrinsic type. There will be an EncryptedTransaction call that can embed any transaction inside of it.
As far as NPOS goes, we are moving to decentralized validators and have a more complex model for encrypted mempool when we do that that we will use if this easy-to-implement model proves effective at combating MEV
Will it delay the NPoS? It's ready to go, so wondering if this will require extra work
Naw this will be tacked on afterwards
If NPoS comes out first we can just tack on a centralized beacon until the decentralized solution is ready