-
Notifications
You must be signed in to change notification settings - Fork 4.3k
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
Network Stability rollout for quic/qos/fee markets #23211
Comments
Can you elaborate "loaded"? AFAIK we have several notions
It seems unlikely that these all have the same solution. I'm not necessarily convinced that these are root causes or even have a single root cause at this point |
the pipeline between the TPU and where banking state puts an entry of TXs into PoH, any place in there could be saturated to the point that it has more stuff to process then time before PoH ends the block. we want TXs to be prioritized as early as possible by 'fee/cu'. If forwarders are doing the prioritization right, and leaders QoS by forwarder stake weight, then valid txs that have a verified fee payer that can afford the TX should get ahead of the queue on the leader most of the time. |
This will require some changes to TX submission since validators only send to TPUFwd. They shouldn't be a major contributor if at all on the TPU port today, so stake-weighted priority will have little effect
I think we need to be deliberate with wording here that these are requested CUs. The effectiveness of this treatment will hinge on both the coverage and assigned-cost accuracy of our measure of true CU usage. Given that "CU" has become a fairly nebulous term, it's hard to be confident that that's the case or even that we're always talking about the same thing.
"Forward" here is to the next leader or down the pipeline? Any thoughts on how we'll balance fee-based priority with parallelization maximization?
Since fees are no longer fully deterministic, it seems like there are a lot of games both validators and users can play to influence this. I'll have to think on it before elaborating |
both TPU and fwd ports
yep, CUs need to be as accurate as gas is in eth.
forward to the next leader
keep filling account buckets and forward each bucket to the next leader to avoid starving accounts on forwards. The idea here is to keep sorting txs into account buckets and then pull from N queues.
They are deterministic, user signs exactly what they pay for. CUs are specified in the TX, what they request is what they get charged for. |
where does |
Should be the CU bin they bought |
Yeah the sorting is what I'm interested in details about. Seems like we need to sort by multiple things they may not have the same ideal weights in all conditions
Right. What they're going to spend is still deterministic, but whether the fee they specify is sufficient for block inclusion is not |
In #23257, assuming one packet has one transaction, packets with same |
does https://github.com/solana-labs/solana/blob/master/runtime/src/bank.rs#L3257-L3274 returns |
This doesn't address my concern. I'm wondering how parallelization will contribute to the sort. We shouldn't find ourselves in a situation that whether through malice or incentives motivated usage, users are buying sub-optimal parallelization |
Total fee, aka, includes additional fee |
It takes a |
@taozhu-chicago @t-nelson I was thinking we sort by fee, then bucket by account/CU limit. then forward by bucket. so if there are N buckets, we round robin between each bucket up to the block limit and take some X CU's for forward. |
Right, after sorting the transactions in buffer by fee-per-cu, leader starts to fill block from highest fee-per-cu TXs, to ensure each write-accounts are always filled higher paid TXs first. We don't really need to create wrt forwarding, I am thinking to do following: |
FeeStructure is not fixed and will be modified at epoch boundaries over time. It probably falls into a similar category as the compute_budget and congestion where both of those will also be bank-specific based on various conditions (feature activation, congestion, etc...) |
Understood. Was hoping to calculate fee-per-cu for each packet upfront when it was received, so the results can be reused. It'd be easier to do if not requiring a bank. |
Or just cache the things you need and yes that is probably the best predictor without looking at current state |
Yea, so just cache |
@taozhu-chicago @aeyakovenko if this round robin is done naively, does this open up a way for low transaction fees to starve higher transaction fee transactions? Imagine I had two buckets, with pending transactions of the form (Write Accounts, Fee/CU) Bucket 1: [(A, 1000000), (AB, 1000000)] If we are doing round robin by first nonconflicting transaction, then we could get a schedule like
Seems like to prevent this, you should also have higher fee transactions that are blocked prevent other lower fee transactions from grabbing the same accounts it needs, even if those lower fee transactions could run without conflict at this moment |
the bucket is by writable-account.
This is assume account_limit >= 2000000;
|
Hmmm, does this mean every account that tries to grab a write lock on
How would these be organized into buckets?
Hmm in this example, why is only |
Right now, if (
Oops, mistakenly flipped outcome. Sorry ... you are right |
So from the above statement, the buckets would actually looks like this?
|
Go through the example in steps:
this continues until either block_limit is met, or went through entire buffer. At the end of iteration, these transactions are submitted to bank for execution, and their outcomes:
And the remaining buffer (after sorted by fee-per-cu) looks like this:
Note, if AB was paid more so that its fee/cu > 1000000, then it would be at the top of the sorted list (in step 1), wherefore would land in first block (in step 2). Also note, this same sorting/fitting/filtering process apply to both block producing in current leader, and packets forwarding. |
It's starting to feel like this needs a full fledged proposal rather than a bunch of adhoc discussions |
Got it, thanks!
Hmm I think with the higher fees, it's no longer sufficient to just uphold current guarantees. We have to guarantee that higher fees land with much higher priority than lower fee transactions whenever possible.
I think in your example where the account limit is hit, then the delay on the In this example, supposed the Say now we have the same queue:
This seems like a starvation scenario we should actively avoid. |
Hmm, isn't this why we have block-limit and account-limit to help such scenario? Plus allowing additional-fee to give I feel I am missing something. Can you describe what do you see about to actively avoid this starvation scenario? |
Based on my understanding thus far, it doesn't seem these limits will help.
I was thinking maybe you would need to reserve accounts that are touched by higher paying transactions, even if you could schedule another non-conflicting transaction. So going back to the example above:
It may also be good to factor in estimated compute. For instance it might be fine to schedule |
@behzadnouri do you have any input on this? This seems like a variation of the job-shop scheduling problem with
And we need to find a valid schedule that maximizes the total weight of the tasks executed. Are you familiar with any of the latest heuristic based algorithms for this type of problem? |
I am taking it as a simple scheduling issue. I interpret the issues as: within banking stage, 1. there are many packets want to be scheduled to be processed by bank, 2. there are way more packets than block capacity; Proposed solution is simple: to prioritized buffered packets with their fee/cu. Higher paid packet get to "see" bank first. Want to clarify that the prioritization, eg sorting by fee/cu, is done before loading and locking accounts, which is before bank executing. |
With block and account limits,
"reserve" isn't really a status for lock. I mean what does "reserved" different from "read locked"? |
@taozhu-chicago @carllin @t-nelson This shouldn't be that complicated. The sorter creates N queues, each queue represents a writable account. The forwarder should forward in RR from the N queues, taking some amount of CU's up to the block limit On the leader side we should get a mix of the highest paying TXs from the top accounts from all the validators so we shouldn't see anyone starved.
Basically, however we are packing the block now, we can continue to do so, except instead of moving TXs into banking stage they are just forwarded, and the current node observes the same block limits, etc... |
For this to be true, In this round robin, for each queue For instance if you have two queues:
If the order of events is doing round robin:
|
Seems like you also need top level prioritization of which bucket to look at first based on fees, it shouldn't be a blind round robin. You could easily have 100,000 buckets for different write accounts, majority of them being low fees, and only a couple containing high fees transactions that we need to prioritize |
Thinking it might be simpler to select TXs from sorted list that can fill up a block (with account limits), without worrying about account contention yet. Then submit selected TXs to bank for execution, from this point on, it works the same way as it is today - TX can't get its account(s) locked will be put back to buffered as |
In my opinion, this problem is inherently complicated because packing conflicting transactions efficiently by fee weight is not trivial. We are going to have to make some tradeoffs here and I think we just need to get aligned on what those tradeoffs are (including attack vectors) in a proposal. |
the fact that we're dealing with an np-hard problem for which we want an online, time-constrained solution, should preclude "simple" |
(hi, let's make the party even merrier. lol) here's another rando idea: on-chain per-account auctioned mempool with deterministic scheduling (this is like a pre-proposal; did we consider like this?) pros
cons
current num-of-sigs tx fee is re-interpreted as block-inclusion-fee (bi-fee). this fixed fee is now strictly modeled as sig verify cost and the tx blob propagation cost across the cluster. now, no execution is guaranteed; older contentious txes will be pruned from the mempool according to additionally, users can now tip more as expedite-execution-fee (ee-fee) with bidding mechanism detailed below. background/thoughts:
(for simplicity, assume that only write accounts and tx runtime is rather uniform)
so, a single execution batch packing algorithm is simple:
lastly, the scheduled batch would be like this:
finally, the tx submitters can plan ee-fee for their urgency and prevalent bidding info, and re-adjust ee-fee if their tx are in the mempool for too long. |
Proposal to review Leader QoS #23369 |
We're looking for less complex solutions, ATM. This sounds cool though! Maybe a future effort 😂 |
Here's a proposal @t-nelson and I were brainstorming on: https://github.com/solana-labs/solana/blob/539cb5c857982444d4d5b238638e8028471e3c70/docs/src/proposals/fee_transaction_priority.md, please take a look as it goes into more detail |
The proposal looks great! 👍🏼
|
Let's move this discussion to the proposal! 😄 |
What about txs involving the same address that need to be ran serially? Is there some way to up fees on them or something like that. Seems like it creates a bottleneck but I've never analyzed Solana traffic so I can't say 100% |
How do we GUARANTEE a leader will process transactions through QoS? |
Hey had a question been going through this report and saw the test results in quic-go/quic-go#2586 (comment) was a bit a confused isn't quic supposed to be ore performant than TCP? and what are the effects of quic on QOS? |
Problem
Users need to land TXs into a block even when the leader is loaded. This is a summary of the solution so everyone is on the same page.
Proposed Solution
implement quic so bots can't send unbounded traffic (1.10)
pull txs proportionally from staked nodes, both the TPU and TPUfwd ports. The goal is to prevent anyone from starving the pipeline for proposing txs to the leader. There should be some mechanism for a validator to set a preferred RPC node that overrides the staked list. (v0 in 1.10.15)
sort txs by (additional_fee)/(requested compute units). CU's should be deterministic since they are completely specified by the ComputeBudget instruction. Users that are willing to pay more, and devs that can make their TXs more efficient, should be prioritized first. (V0 in 1.10.15)
fill the account buckets up to the account write CU limits and the block CU limits. (1.9)
keep filling account buckets and forward each bucket to the next leader to avoid starving accounts on forwards. As the account buckets are filled with CUs, forwards should start sending txs from multiple accounts, not just the one with the highest fees. Naive implementation would forward highest paid TXs first, which are likely to be only for a single hot account. Otherwise a single congested market with a ton of demand will saturate the forward queues. (forward packets by prioritization in desc order #25406)
design, https://github.com/solana-labs/solana/blob/master/docs/src/proposals/fee_transaction_priority.md
testnet release with 1.10.x
mainnet-beta upgrade to 1.10.x
backport of quic fix Backport ghsa x236 qc46 7v8j #26671 released
quic is turned on on mb
Priority fee rollout. All major features activated! cli and rpc apis are left Prioritization Fee function enabling #26017
rpc provides switched to quic boot with
--tpu-use-quic
wallets rolled out with compute budget additional fee
UDP is disabled on mb
TBD: optimizations
tag @jackcmay @taozhu-chicago @carllin @t-nelson @sakridge
The text was updated successfully, but these errors were encountered: