Author: Anatoly Yakovenko

Compiled by: TechFlow

Overview

MEV is a fundamental problem in permissionless blockchains. Like most permissionless blockchains, Solana aims to minimize the amount of MEV that chain operators extract from users.

Solana’s approach is to reduce MEV by maximizing competition between leaders (i.e., block producers). This means shortening slot times, reducing the number of slots a single leader schedules consecutively, and increasing the number of concurrent leaders per slot.

Generally speaking, more leaders per second means users have more options to choose the best offer from the incoming leaders after waiting T seconds. More leaders also means that it is cheaper for good leaders to provide block space, and it is easier for users to trade only with good leaders and exclude transactions from bad leaders. The market should decide what is good and what is bad.

Solana’s larger vision is to build a global permissionless price discovery engine capable of competing with the best of any centralized exchange (CEX).

If a market-impacting event occurs in Singapore, the message still needs to be transmitted at the speed of light over fiber optics to the CEX in New York. The leaders in the Solana network should have broadcast the message in a block before the message arrives in New York. Unless a physical internet partition occurs at the same time, by the time the message arrives in New York, the state of Solana will already reflect the message. Therefore, there should be no arbitrage opportunities between the CEX in New York and Solana.

To fully achieve this, Solana requires many concurrent leaders with highly optimistic confirmation guarantees.

Configuring multiple leaders

Just like the current leader schedule, the system will be configured with 2 leaders per slot instead of 1 leader. To distinguish the two leaders, one channel is labeled A and one is labeled B. A and B can rotate independently. The questions that need to be answered to implement this schedule are:

  • What if blocks A and B arrive at different times or fail?

  • How to merge the order of transactions in blocks A and B?

  • How to allocate block capacity between A and B?

Transferring concurrent blocks

To understand the exact process, we need to take a quick look at Turbine.

Leaders split blocks into shards as they build them. Batches of 32 shards are erasure coded with 32 shards. Batches of 64 shards are merklized and signed with a root, which is chained with the previous batch.

Each shard is sent via an independent deterministic random path. The retransmitter of each last batch signs the root.

From the receiver's perspective, each receiver needs to receive 32 fragments from verified retransmitters. Any missing fragments are repaired randomly.

This number can be increased or decreased with minimal impact on latency.

Assuming that the retransmitters' sampling of fragment paths is sufficiently random and weighted by stake, the stake required to co-partition the network will be much more than ε stake, both in terms of arrival time and data. If the receiver detects that 32/64 (configurable) fragments of each batch arrived in time T, then it is very likely that every node did too. This is because 32 random nodes are large enough that it is unlikely that they will all be in the same partition by chance.

If a partition occurs, consensus needs to resolve it. This does not affect security, but is relatively slow.

Multi-block production

If a single block is transmitted, every receiver (including the next leader) will see the batch of fragments for each block arrive. If the block is not complete within T milliseconds, the current leader will skip the block and build a fork without it. If the leader is faulty, all other nodes will vote on the block and the leader's block will be skipped. The non-faulty leader will immediately switch to the heaviest fork indicated by the vote.

In case of multiple block transfers, each node will need to wait at most T milliseconds before voting on the observed block partition. For two concurrent leaders, the possible cases are: A, B, or A and B. Additional latency is added only in case of block delays. Under normal operation, all blocks should arrive at the same time, and each validator can vote as soon as both arrive. Therefore, T is likely to be close to zero in practice.

The key defense for this attack is whether a leader with a very small amount of tokens staked can transmit a block slightly late on a slot boundary, reliably causing the network to split and force the network to spend a lot of time to resolve the problem through the consensus mechanism. Part of the network will vote for A, part will vote for B, and part will vote for both A and B. All three splits need to be resolved through the consensus mechanism.

Specifically, the goal of zero-neighborhood should be to ensure that nodes recover blocks at the same time. If an attacker has a cooperating node in the zero-neighborhood, they can transmit 31/64 fragments normally, and have the attacker selectively transmit the last fragment, trying to create a partition. Honest nodes can detect which retransmitters are delayed and push the missing fragments to them as soon as any single honest node recovers the block. Retransmitters can continue if they receive the fragment from anywhere or recover it. Therefore, blocks should be recovered by all nodes shortly after an honest node recovers. Testing is needed to determine how long to wait, and whether it should be absolute, or weighted by the arrival time of each fragment, and whether stake node reputation should be used.

The probability of a co-leader and retransmitter in each block is approximately P leader shares (64P retransmitter shares). 1% of the shares can attempt an attack in a batch of ½ shards that the attacker schedules as a leader. Therefore, detection and mitigation need to be sufficiently robust.

This attack has little impact on the next leader because asynchronous execution allows unused capacity to be carried forward. Therefore, if the current leader forces the next leader to skip a slot, and the next leader has 4 consecutive slots, the unused capacity of the skipped slot can be carried forward, allowing the leader to re-include the transaction for the skipped slot.

Merge concurrent blocks

This will lead to a waste of resources if users send the same transaction to both leaders A and B in order to increase their chances of being included or to be first in a block. If this happens, increasing the number of concurrent leaders will have very limited effect on performance, as they are just processing twice as much junk transactions.

To avoid duplicate transactions, the top N bits of the fee payer will determine which leader channel the transaction is valid in. In this example, the top bit will choose A or B. The fee payer must be assigned to an exclusive channel so that the leader can be sure that the fee payer is valid and has not spent all of its lamports (the smallest unit of currency in the Solana blockchain) on other leaders.

This will force spammers to pay fees for logically identical transactions at least twice, but in order to increase the probability of being the first transaction, spammers may still send logically identical transactions.

To discourage this behavior, users can choose to include an additional 100% destroy order fee in addition to the leader's priority fee. The highest order fee is executed first. Otherwise, first-in-first-out (FIFO) ordering is used. In the case of a tie, the order is resolved using a deterministic random permutation. It is therefore more cost-effective for spammers to raise their order fee and have it executed first than to pay the inclusion fee twice.

In order to handle bundling and reordering of transaction sequences, the system needs to support bundling transactions, which can add an order fee to cover the ordering cost of the entire transaction sequence. The fee payer is only valid in the channel it is reserved for, so the bundle can only manipulate the sequence within its own channel.

Alternatively, order fees may not be necessary. If FIFO ordering is used, and spammers are always charged priority fees in all channels, it may be possible to simply allow the market to determine the cost of paying N leaders to increase the chance of inclusion vs. the cost of paying the closest leader who is most likely to include the transaction first.

Managing Block Resources

In a blockchain network, when there are two concurrent leaders, each system-wide block capacity limit needs to be evenly distributed. Specifically, not only the total capacity, but also each specific limit, such as the write lock limit - no account can write more than 6 million computing units (CUs), and each leader can only schedule transactions for a maximum of 24 million CUs. In this way, even in the worst case, the merged block will not exceed the total capacity limit of the system.

This mechanism may lead to fluctuations in costs and underutilization of resources, because the cost of scheduling priority will be determined by the capacity of each leader, and each leader has little knowledge of the scheduling status of other concurrent leaders.

To mitigate underutilization of resources and resulting fee spikes, any unused block capacity should be rolled to future blocks. That is, if the current merged block uses less than X in write locks, total bytes, or total compute units (CUs), then K*X should be added to the next block, where 0 < K < 1, up to some maximum. Asynchronous execution can lag behind the chain tip by up to one epoch, so capacity rolling can be quite aggressive.

Based on recent block data, most blocks are typically 80% filled, while the write lock limit is well below 50%. In general, there should always be some spare capacity for future blocks. Since blocks may temporarily exceed the capacity limit, execution must occur asynchronously with the consensus process. For more information on the asynchronous execution proposal, see the APE article.