-
Notifications
You must be signed in to change notification settings - Fork 298
SIMD: (APExB) Asynchronous Program Execution and Broadcast #45
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7a89774
0f5393f
dbf0775
25d9375
3636f73
c27b675
8472fab
92f953c
247b79b
a16ecc1
5d0a76f
6ca0683
43e1f3b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,371 @@ | ||
| --- | ||
| simd: '0023' | ||
| title: Asynchronous Program Execution and Broadcast | ||
| authors: | ||
| - Anatoly Yakovenko | ||
| category: Standard/Meta | ||
| type: Core | ||
| status: Draft | ||
| created: 2024-03-29 | ||
| feature: (fill in with feature tracking issues once accepted) | ||
| --- | ||
|
|
||
| ## Summary | ||
|
|
||
| This feature changes how the ledger is broadcast and executed. It | ||
| separates proposing blocks full of user transactions from blocks | ||
| with votes. It allows for N concurrent builders of user transaction | ||
| blocks, and it allows for asynchronous execution of user blocks. | ||
|
|
||
| ## Motivation | ||
|
|
||
| 1. Single leader for user transactions is a bottleneck. Leaders | ||
| are in a single spot in the world, while clients are all over the | ||
| world. Latency is therefore based on how close a client is to a | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How would For example, suppose that I am in Wellington, there's a builder in Sydney, and the leader is in Los Angeles. Either way, I want my transaction to be included in the slot, which requires it traveling to Los Angeles. Today, I would send my transaction directly to the Los Angeles leader (134ms). If this proposal is implemented, I would send my transaction to the Sydney builder (35ms). But for me to consider my transaction confirmed, the builder still needs to send it to Los Angeles (180ms), no? This would bring the total latency up to 215ms if so.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think the idea is it reduces latency to nodes choosing which transactions make it into the block, not total confirmation time. Let's re-use the locations in your example, and suppose I see a really great opportunity in some market. There's actually 2 separate aspects in this proposal that seem like they might help you get the opportunity:
Let's say we just have priority re-ordering without multiple leaders. This means if you pay a higher priority fee than anyone else going for the opportunity, you would get it...if limits were not already hit AND you made it in time. 180ms + delay is a significant fraction of the 400ms block-time, and it's possible (maybe likely) your tx doesn't make it into the leader's queue for consideration early enough to get included. Having multiple builders increases your chances that one is closer to you make it to the closest one in time for them to include you in their user block and before limits are hit. Not sure what @aeyakovenko intended here though - because if this There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What is the advantage of having multiple block builders separated from a single leader vs having multiple leaders who are also responsible for buiiding blocks? Multi leader seems a bit more censorship resistant There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What do you mean by "multiple leaders"? Currently, a leader is tasked with producing the next block in the chain. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's actually in the original whitepaper in section 4.4 https://github.com/solana-labs/whitepaper/blob/master/solana-whitepaper-en.pdf Most of my understanding of how it could look like over the past year or so was informed from twitter discussions :) Basically, you'd need the bankless leader setup first, and from there you would go with an architecture similar to that described in the whitepaper.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The multi leader approach will likely create more forks. It's an attributable fault for a leader to produce two blocks for the same slot, but with multiple leaders if there is a turbine failure, the network has a similar partition but no one is at fault. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ahh I see. Makes sense. I had assumed there was some benefit related to ddos resistance with having multiple leaders in the past.... I guess with single leaders what can we do to improve ddos resistance? I worry that there might be a high incentive in the future for competitors to try and "kill" solana with liveness attacks. Maybe could have "sentry nodes" in front of leaders (?). I don't think many validators would upgrade to 100gbps pipes. |
||
| leader. Leaders also have to spend a ton of resources on prioritization | ||
| of transactions. | ||
|
|
||
| 2. Executing programs before voting is a bottleneck. Fork choice | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fork choice does depend on program execution: the stake program can change stake weight of voters which influences fork choice. Stake weight can only change at epoch boundaries though so there must be a 'sync' at epoch boundaries, where validators must have "caught up" on executing all tx at an epoch boundary before they can vote beyond that epoch boundary. Is this wrong?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes. Nodes need to be able to compute a snapshot once an epoch.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Would prefer if this issue was addressed more completely than a one-liner. Given that the whole purpose of this proposal is to increase asynchronous execution, having a big synchronization point once per epoch seems like a big deal. It's not clear to me that having a period of asynchronous execution followed by a synchronization point is an overall win, given that it will introduce a period of time at the beginning of each epoch where "nothing new happens until everyone is caught up". Is asynchronous execution during later parts of an epoch worth the reduction in throughput during early parts of an epoch?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nodes can't fall behind that much because the overall CU limits are set for synchronous execution. But with the option of async execution it is much easier to catch up. Raw ledger processing without dealing with the network is 20-30x times faster. |
||
| doesn't depend on program execution, and delaying voting creates | ||
| forks and also delays the next block producer from starting. | ||
|
|
||
| ## Alternatives Considered | ||
|
|
||
| APEX design that was proposed in https://github.com/solana-labs/solana/pull/24127 | ||
|
|
||
| ## New Terminology | ||
|
|
||
| * UserBlock - a block full of non vote transactions. | ||
|
|
||
| * UserBlockEntry - this is the entry that leader creates in PoH for | ||
| the UserBlock, it contains a hash of the built UserBlock. | ||
|
|
||
| * UserBlockSlot - A slot for builders to transmit the UserBlock to | ||
| the cluster over turbine. Cluster could be configured with more | ||
| then one UserBlockSlots per slot with a default setting of 2. | ||
|
|
||
| * Leader - the current leader for the slot that will build a PoH | ||
| ledger full of Votes and UserBlockEntries. | ||
|
|
||
| * Builder - a node that is scheduled to build a block with non | ||
| vote transactions | ||
|
|
||
| * VoteHash - like BankHash, but for vote only transactions. | ||
|
|
||
| * BundleTransactions - a transaction signed by the builder that can | ||
| list transactions in the builders UserBlock to be executed in | ||
| one ordered batch. This transaction can also add a priority fee | ||
| such that the entire bundle is prioritized for execution as a batch. | ||
| This transaction can only appear in the builders UserBlock and can | ||
| only reference transactions prior to it in the UserBlock. TBD on | ||
| format. | ||
|
|
||
| ## Detailed Design | ||
|
|
||
| ### Overview | ||
|
|
||
| Leaders are scheduled to build blocks as they are currently by | ||
| the LeaderSchedule. | ||
|
|
||
| Builder's are scheduled along side leaders to build UserBlocks - | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. In this vision is the Builder set mutually exclusive with the Leader set? Are these Builders envisioned to be different types of nodes, or just normal validators? If normal validators, how will a Builder be prevented from being scheduled as a Leader in the same slot? (Assuming the sets aren't mutually exclusive) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not the original author, but the way I understand it is:
Currently, there is a function that determines the leader schedule based on the stake balances for the epoch of all the participating nodes. And there could probably be certain details that I am overlooking. |
||
| blocks of non vote transactions. N number of builders can be scheduled | ||
| concurrently to build blocks. | ||
|
|
||
| While a leader is scheduled, they receive and encode votes as normal. | ||
| Any well formed UserBlocks that were received from the previous or | ||
| current UserBlockSlot are added to the leaders PoH ledger as | ||
| UserBlockEntry. | ||
|
|
||
| The N concurrent builders create blocks out of user transactions. | ||
| These are transmitted to the cluster via turbine concurrently with | ||
| the scheduled leader and other builders. The leader receives and | ||
| decodes them and generates a UserBlockEntry, and adds it to PoH as | ||
| soon as the leaders PoH has started the UserBlockSlot. | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. technically turbine is defined as never to forward to the leader. this change needs a bit of clarification, i guess shreds are never forwarded to their builder and the leader becomes the turbine root unless builder = leader? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
I don't really understand how these two work together, I actually understand them as two different consensus mechanisms, could you clarify? a) leader receives shreds over turbine, once a user block slot can be fully decoded locally, it creates a PoH entry. What's the relative order between the UserBlocks in replay? Can the leader still reorder the two UserBlocks? b) leader receives shreds over turbine, once every 200ms a UserBlockSlot starts. the leader adds the decoded UserBlockEntry to poh if it has been received in time. What if the shreds don't arrive in time? What's the relative order between the UserBlocks in replay?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If the shreds don't arrive to the leader in time, they don't add the UserBlockEntry to the block. Similarly, validators don't vote on Blocks that contain UserBlockEntries they haven't received yet.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Leader can add the UserBlockEntry on the next block |
||
|
|
||
| Validators can vote on leader blocks by executing the votes, but | ||
| before completing the execution of UserBlock transactions. | ||
|
|
||
| ### Fork Choice | ||
|
|
||
| If a validator doesn't have the builder's UserBlock, the validator | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. im confused where they repair from here if they're the only one getting the UserBlock. unless its propagated to the entire cluster somehow
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. UserBlocks are sent over turbine. So repair and everything else works as is.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
All validators that would vote on the fork containing the user block must get all user blocks for that fork before voting on it. Voting on a fork without even verifying that the user blocks it references exist would allow attacks on the network by malignant nodes that get user blocks entries inserted into blocks but never provide the actual transaction data. Not sure how anyone can expect to sanely evaluate the state of a fork for which certain transactions are hidden and never made available.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is correct. Before voting on a fork each validator has to have all the data, including all the data form all the user blocks in that fork. Otherwise there is no way to guarantee that everyone can execute because the data could be withheld |
||
| doesn't vote on the proposed block and tries to repair the UserBlock. | ||
| That fork is ignored for fork choice. | ||
|
|
||
| Otherwise the validator evaluates the forks as usual. | ||
|
|
||
| ### UserBlock builder schedule | ||
|
|
||
| Each block is sloted to support N user blocks. Some of these builders | ||
| are randomly scheduled, some of these are persistent. For example, | ||
| there are 10 UserBlock builders per network block, that means 10 | ||
| builders are each assigned 10% of the shreds and 10% of the compute | ||
| available to the block. | ||
|
|
||
| #### Randomized UserBlock builders | ||
|
|
||
| Randomized UserBlock builders are assigned at the same time as the | ||
| leader schedule is created based on stake weighted leader distribution. | ||
|
|
||
| The benefit to more than 1 random UserBlock builder per leader | ||
| block is that they are likely geographically distributed and users | ||
| will be able to pick the closest one. | ||
|
|
||
| The downside is that resource management becomes more complex. Each | ||
| builder has 1/N compute and shred capacity and users have no idea | ||
| which one is saturated when sending their transaction. It's likely | ||
| that priority fee floor will be different at each UserBlock builder. | ||
|
|
||
| #### Persistent UserBlock builders | ||
|
|
||
| Persistent UserBlock slots for the epoch are auctioned of to the top | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. how do you prevent the same N builders from winning every auction. imagine a whale builder bidding at a small loss every epoch pricing everyone out, only to earn all the mev for a volatile epoch
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Someone else can outbid them. As long as the auction process isn't censored it's fine. That's kind of the point of persistent builders. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is kinda the same with flashbots right now with 3 block builders making 70% of the blocks because validators are looking for blocks with higher gas fees and optimized uncle rate and don't care much where the block is coming from. |
||
| N bidders who burn the most lamports. | ||
|
|
||
| In the first half of the epoch each builder deposits the lamports | ||
| they are planning on burning, in the second half the builders may | ||
| withdraw excess lamports. The top N builders are assigned the slots | ||
| in a dutch auction according to their remaining bids. If there are | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you clarify the auction process here? I would have assumed an auction process where we take the top
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are N slots to auction, so a Dutch auction makes the most sense. One bid could get 70% of the block and the other could get 30%
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That doesn't sound like a Dutch auction as I understand them, so maybe I'm just getting confused by the terminology. It'd help to give an example in the document to clarify.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Welp, since I'm the one who was confused I looked it up: https://www.investopedia.com/terms/d/dutchauction.asp Seems to be an overloaded term, I was thinking of it as the first way they describe; i.e. a descending price auction, first bid wins. I'm guessing that you mean the style they describe in the "Understanding Dutch Auctions for Initial Public Offerings (IPOs)" section:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The auction is run for the next epoch. So it takes a full epoch to finish.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Alternative to an auction would be extending staking to pick persistent builders. That choice might be necessary if slashing for duplicate UserBlocks is necessary
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Slashing duplicate UserBlocks shouldn't ever be necessary, since the leader would have picked 1 of the proposed blocks and the network would either accept or reject the leaders fork. Everyone with inconsistent data can dump it and repair the right version. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
how do you prove duplicate user blocks?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as you prove duplicate blocks. Last shred is different There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. any form of unsealed auction can be timed, so not ideal for this use-case.
Can we focus for this SIMD on random builders and then make a new SIMD for a persistent builder auction? If not, why? I didn't see anything motivating this addition to the protocol. |
||
| no bidders the capacity is relinquished to the randomized UserBlock | ||
| builders. | ||
|
|
||
| The benefit to persistent UserBlock builders is predictability of | ||
| scheduling. Applications can request the percentage of block | ||
| bandwidth they need for operation and create dedicated sequencers | ||
| that guarantee eventual settlement into the chain. The drawback | ||
| is censorship, but because some space is available for | ||
| randomized UserBlock builders there is no way for the persistent | ||
| block builders to prevent transactions from eventually landing into | ||
| the chain or to be outbid in the next epoch. | ||
|
|
||
| Future work may include assigning program state to a specific | ||
| persistent builder so only those builders can schedule transactions | ||
| that call those programs. | ||
|
|
||
| #### UserBlock Compute Limits | ||
|
|
||
| If the overall compute capacity for user transactions per leader | ||
| block is 48m CU, and cluster is configured with 2 builders and | ||
| UserBlockSlots are configured to 200ms, then each UserBlock can | ||
| use no more then 48m/4 or 12m CU. | ||
|
|
||
| ### Priority ordering for UserBlock transaction execution | ||
|
|
||
| Execution of UserBlocks can happen asynchronously to voting. When | ||
| voting validators transmit their most recent BankHash, but it may | ||
| be for an older parent slot then the slot they are voting on. | ||
|
|
||
| Each UserBlock is assumed to have been created simultaneously during | ||
| the UserBlockSlot that it was encoded by the leader. | ||
|
|
||
| For each UserBlock in the PoH section spanning the UesrBlockSlot, | ||
| the transactions are ordered by priority fee before execution. | ||
|
|
||
| If two transactions from two different blocks have the same priority, | ||
| they are ordered by which UserBlock appears first in the leaders | ||
| PoH. | ||
|
Comment on lines
+159
to
+164
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does this effectively creates something similar to the Ethereum mempool, but on chain? Or is the assumption that Builders do not share the transaction information until the end of the UserBlockSlot? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @aeyakovenko is that right? can two transactions write to an account in a block? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 200ms is very short for random paths across the globe, I would assume that a naive builder just need to send the block pretty early if they want it to arrive in time for the UBS. if there's a second builder closer to the proposer that could be used to inject txs in the last 20ms. the whole block reorg on the proposer is kinda weird. it opens up for this kind of latency race. this solution is very close to PBS but it violates a fundamental assumption: builders decide on final order. |
||
|
|
||
| If the leader's block is attached to the heaviest fork, | ||
| the validator can start execution of the UserBlocks optimistically. | ||
| Otherwise the validator should only execute UserBlocks on the | ||
| heaviest fork. | ||
|
|
||
| Duplicate transactions in the UserBlock are skipped over without | ||
| any state changes. They must still be retained in the ledger because | ||
| they have been hashed into the UserBlockEntry. | ||
|
Comment on lines
+171
to
+173
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wouldn't this mean that the most optimal behavior for the users would be to send every transaction for inclusion to every Builder? If it is the case, the downside is that it may effectively reduce the effective slot capacity, if too many transactions would turn out to be just duplicates in the final state.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I have this concern as well, and it seems to be that @7layermagik may as well: #45 (comment) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm yeah I guess u could have something in the transaction that specifies which leader it can be included by. If they want it to be processed by both leaders it costs double
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. or charge the fee on both if it is included in multiple user blocks by different leaders. spammer would need to pre fund a bunch of fee payers, which wouldn't be free.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I don't think just charging fees for inclusion by multiple builders is sufficient. We can probably do some combination of hash/bit-based builder routing (like @mschneider suggested elsewhere) so signed message is only includable by certain builders. This approach seems to check most of the boxes I think we want:
If users want to send to multiple builders, they'd want to have some sort of gate on the tx to prevent it from actually executing twice; seems reasonable this could just be done with a sequencer. |
||
|
|
||
| ### UserBlock format | ||
|
|
||
| UserBlock follows the standard solana ledger format, except it | ||
| MUST not contain any PoH ticks or votes. | ||
|
|
||
| Invalid transactions are skipped, including duplicates, or those | ||
| with invalid signatures, or completely malformed, and the rest of | ||
| the block is processed. | ||
|
Comment on lines
+180
to
+182
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A bit confused on this part - why should we begin to allow a builder to include transactions without proper signatures? Shouldn't the builder's be running sigverify and basic checks?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Because if it is asynchronous, nodes may detect the invalid signature much later, well after they vote. The only thing validators need to do to vote on forks is have the UserBlock data and verify the format and the builder signature. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There is still an assumption that Builders validate transactions, making an effort to propose only UserBlocks with something that is valid, right? |
||
|
|
||
| The first entry must start with the value 0, the last entry must | ||
| contain a signature from the builder of the previous entry hash. | ||
| This will ensure that leader cannot manipulate the UserBlock, and | ||
| that the entire block must be included when computing the UserBlockEntry. | ||
|
|
||
| ### UserBlockEntry format | ||
|
|
||
| Contains the hash of all the data in the UserBlock. TBD if the | ||
| hash should contain a vector commitment for data availability | ||
| sampling. | ||
|
|
||
| ### UserBlock broadcast | ||
|
|
||
| Builders can form blocks at any time. Each scheduled builder can | ||
| transmit shreds over a pre-allocated shred range for the slot. | ||
|
|
||
| For example, if the cluster is configured with 5k shred blocks, and | ||
| 2 builders: | ||
|
|
||
| Leader: [0-1000] | ||
| UserBlockSlot 0, Builder 0: [1000-2000] | ||
| UserBlockSlot 0, Builder 1: [2000-3000] | ||
| UserBlockSlot 1, Builder 0: [3000-4000] | ||
| UserBlockSlot 1, Builder 1: [4000-5000] | ||
|
|
||
| Leader must fit their entire block in shreds 0 to 1000, including | ||
| PoH tick entries, votes and UserBlockEntries. | ||
|
|
||
| Builder 0 transmits shreds 1000-2000 and 3000-4000 | ||
| Builder 1 transmits shreds 2000-3000 and 4000-5000 | ||
|
|
||
| UserBlockEntries for UserBlockSlot 1 must be included by the leader | ||
| after the halfway point in the leaders block. | ||
|
|
||
| ### Leader Blocks | ||
|
|
||
| Leader produces blocks as usual, but blocks are valid if they | ||
| only contain Vote transactions and UserBlockEntries and PoH ticks. | ||
|
|
||
| UserBlockEntries in the leaders block must be recent, must not be | ||
| in the future, and must not be duplicates. | ||
|
|
||
| ### BankHash | ||
|
|
||
| Votes must include the most recent computed BankHash along with the | ||
| slot for the BankHash computation. This slot is different | ||
| from the tower vote slot. | ||
|
|
||
| Each validator that is computing a BankHash will be able to verify | ||
| the BankHash values created by block producers for previous slots | ||
| because each BankHash has a link to the previous one. | ||
|
|
||
| During verification, if a validator sees that > 1/3 of the cluster | ||
| has incorrectly computed a state transition, they should halt | ||
| immediately. | ||
|
|
||
| ### VoteHash | ||
|
|
||
| All validators will execute all the vote transactions on every fork, | ||
| as they do now. After computing all the vote state transitions the | ||
| validator will compute the VoteHash, identical to the BankHash in | ||
| structure, but covers only the vote state transitions. The VoteHash | ||
| is included in the vote for the slot that the validator is voting | ||
| for. | ||
|
|
||
| ### Client Confirmations | ||
|
|
||
| Clients connected to a trusted RPC can confirm the transaction as | ||
| soon as the RPC has executed teh UserBlock and the block has been | ||
| optimistically confirmed. | ||
|
|
||
| Client can also wait for a status code weighted by stake weight, | ||
| as each validator's execution catches up to the slot and includes | ||
| a BankHash confirming the state of the execution. | ||
|
|
||
| It may be sufficient to wait for 1/3+ validators executing the state | ||
| transition instead of the full 2/3+, because if 1/3+ are incorrect | ||
| the cluster will halt anyways. | ||
|
|
||
| ### State synchronization | ||
|
|
||
| Nodes must be able to compute a full snapshot at least once an | ||
| epoch. So overall CU limits for the block must be set such that | ||
| synchronous execution is possible. But because asynchronous execution | ||
| is possible, replay can take advantage of much larger batches of | ||
| execution. | ||
|
|
||
| ## Impact | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. looks like we might want to include a bundle primitive in here too to avoid splitting up bundles that get reordered/not guaranteed to execute atomically. can imagine bundle like:
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Added the BundleTransaction |
||
|
|
||
| Multiple nodes can operate as Builder on the cluster concurrently. | ||
| So clients can pick the nearest one, and the bandwidth to schedule | ||
| and prioritize transactions is doubled. There needs to be a design | ||
| for BundleTransactions that allow the bundler to prioritize a batch | ||
| of transactions for execution by paying a priority fee for all of | ||
| them, and executing the whole batch together. | ||
|
|
||
| Priority fees now also imply execution priority. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. LFG |
||
|
|
||
| Fork choice and voting is not blocked by user block propagation or | ||
| execution of user transactions. | ||
|
|
||
| Builders are going to capture all the MEV. | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I do not believe this is correct. Builders will have to transmit some amount of the MEV to validators via priority fees in order to ensure that their BundleTransactions execute. A leader does not have to accept a BundleTransaction, it can ignore it, if the total fees paid by all tx in the bundle + the bundle priority fee do not make the bundle attractive enough to schedule ahead of other tx/bundles. For this reason, builders will have to compete on priority fees for bundles, which will naturally transmit a significant fraction of MEV to validators.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. How can the leader ignore a BundleTransaction? It's part of the UserBlock, so the entire block must be accepted, including the BundleTransaction.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. added some clarifications There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hey kinda confused here, so the builders can reorder txns and capture the MEV but what makes a block attractive for the leader to be included in the slot rather than just aiming for lower latency?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. priority fees and base fees go to the leader |
||
|
|
||
| Votes contain additional data, instead of BankHash, they contain | ||
| (VoteHash, (BankHash, slot)) | ||
|
|
||
| ## Security Considerations | ||
|
|
||
| Validators may include incorrect BankHash values which may not | ||
| be detected instantly. | ||
|
|
||
| Validators may skip evaluating their own BankHash and copy results | ||
| from other validators. | ||
|
|
||
| Network halts if it cannot compute a epoch snapshot hash once an | ||
| epoch because it is overloaded with user transactions. | ||
|
|
||
| Leader could censor or delay the builder. | ||
|
|
||
| Under heavy forking, validators will skip executing all the | ||
| UserBlocks on minor forks. | ||
|
|
||
| ## Slashing UserBlock Builders | ||
|
|
||
| There shouldn't be a reason to slash UserBlock builders. Duplicate | ||
| UserBlocks will be resolved by the leader, and it is up to the | ||
| leader to pick one. If turbine failed and the rest of the network | ||
| has a different UserBlock, the leaders proposed block is dropped. | ||
|
|
||
| If slashing is required, then stakeweighted or a bond based auction | ||
| would be necessary. | ||
|
|
||
| ## Economic Considerations | ||
|
|
||
| Builders should be shuffled and scheduled according to stake weight. | ||
|
|
||
| TBD, deciding how should builders and leaders split the fees from | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Something to consider here is how to handle duplicate transactions. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sorry I might be dumb but don't we already have dedup features?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No problem my previous message was not clear 😄 We have deduping that prevents txs from appearing in multiple different slots. With this proposal, we have multiple builders who could potentially include the same transaction in their My previous comment was mainly highlighting an edge-case for the economics of this deduplication. They both included a valid transaction in their Potentially a few options:
1 seems a better option, but it's also going to entirely depend how we split fees between the leader and builders in general. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Could the transaction being sent contain information specifying which leader to process it? That would avoid duplicates and it's easier to filter the block for transactions referencing one of the particular leaders to know which fee rewards it should receive.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Duplicate TXs are skipped. See line 141 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe being able to specify the leader is also a feature though? Having your transaction processed by a certain leader might be undesirable for mev reasons so there could be reason for specificity? Also, if filling blocks is based on requested/estimated cu's, skipping dupe transactions would lead to empty space whereas this solution wouldnt.
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wdym processed by a certain leader? Either the UserBlcok is included or it's not. The big question is if it can be included in any slot, or only the scheduled slot.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I believe what is meant is a mechanism to make sure a transaction is processed by a specific builder
If there's a certain builder I know does some MEV that is undesirable for my transaction, then I would request my tx is processed by the other. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Sorry again a dumb idea There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
if the builder selection was based on the first few bits of the signature:
|
||
| user transactions. | ||
|
|
||
| ## Capacity Management | ||
|
|
||
| Because capacity is split between UserBlocks, max UserBlock size | ||
| as well as max account limit per UserBlock must be 1/N CUs, where | ||
| N is the number of concurrent builders. | ||
|
|
||
| To prevent under-utilization, unused resources from blocks that are | ||
| partially filled can be used by future blocks up at most N * (block | ||
| or account limit). This would allow the network to handle bursts | ||
| of demand and on average maintain the desired load. | ||
|
|
||
| ## Multi leader spam | ||
|
|
||
| Spammers would be motivated to send the same message to every | ||
| leader. | ||
|
|
||
| 1. builders censor fee payers by most significant bit of the fee | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Am I missing something, shouldn't this be filtering by first If we only look at first bit, then we'd get 2 sets of distinct fee-payers, rather than There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. if we use a power of 2 to limit the number of builders we can use ln(N) bits, as error is always 0. Else using ln(N) + 4 is probably safer from a load shedding perspective (error < 6.5%) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. manipulating the fee payer is really annoying, for signature, I can just add a noop-instruction and rehash. why would we use fee payer and not signature?
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @apfitzge yea, I meant N bits
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @mschneider for well behaving users, I think its more predictable to use a fee payer that is closest to the leader. so latency sensitive users can rotate fee payers automatically |
||
| payer public key | ||
|
|
||
| 2. users generate N fee payers for N concurrent builders and use | ||
| the fee payer that is geographically closest. | ||
|
|
||
| If spammers want to send messages to multiple nodes, they would | ||
| need to use multiple fee payers and pay per node. | ||
|
|
||
| ## Drawbacks | ||
|
|
||
| [TBD] | ||
|
|
||
| ## Backwards Compatibility | ||
|
|
||
| [TBD] | ||
|
|
||
| ## Implementation Roadmap | ||
|
|
||
| 1. Bankless leaders - separate out leader functionality such that | ||
| it doesn't depend on state. This would require relaxing that all | ||
| fee payers must be valid in a block. | ||
|
|
||
| 2. Fixed sized voting committees - configure network to run with | ||
| 400 nodes voting per epoch, this requires consensus changes. Consensus | ||
| then has a fixed resource cost on the network. | ||
|
|
||
| 3. UserBlocks - separate votes from non votes, and transmit non-votes | ||
| in user blocks. Execution is still synchronous. | ||
|
|
||
| 4. Asynchronous execution - nodes skip user block execution before voting. | ||
|
|
||
| 5. Multiple builders - requires capacity management | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is
Nhere meant to be a fixed limit or an arbitrary number?Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Configured by the cluster. Builders need to be scheduled ahead of time.