-
Notifications
You must be signed in to change notification settings - Fork 4.5k
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
Avoid overflow when computing rent distribution #12112
Conversation
let validator_rent_shares = validator_stakes | ||
.into_iter() | ||
.map(|(pubkey, staked)| { | ||
let rent_share = | ||
(((staked * rent_to_be_distributed) as f64) / (total_staked as f64)) as u64; |
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.
From my debug log excerpt:
distributed rent: 120525
staked(374999998287840) / total_staked(2021686897690030)
[1] pry(main)> 120525 * 374999998287840
=> 45196874793641916000
[2] pry(main)> 2 ** 64
=> 18446744073709551616
;)
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.
These are incorporated into a test: https://github.com/solana-labs/solana/pull/12112/files#diff-a7549f152920d85fb44e6a784b8e5e1fR4516-R4517
Alternatively, I think rent distribution just should go to Current implmentation is complex (thus caused this bug). Why does it distribute over all of stacked votes (=~ validators) at every slot, first of all? It costs quite much computing resource.... |
@t-nelson Wdyt? Am I missing something? In other words, why collected lamports is treated differentally?: transaction fee (to the leader atm) vs rent fee (over the all staked validator set). |
If I had to guess, it's because rent is only collected once per epoch and thus validators occurring earlier in the leader schedule will get a disproportionate reward. So we can't rely on it pretty much averaging out over the course of the epoch, like we do for fees. Perhaps @rob-solana has some insight to share on the matter? |
Oh, this is good point. Thanks for the input! So, even if the leader schedule is uniformly distributed even for some short period at the start of epoch, could this be a concern? I guess so. Maybe, because this is easy to grind the leader schedule? If this is true, I'll just fix the overflow. CC: @rwalker-com |
just fix the overflow the rationale for distributing rent according to stake is because fees are already distributed by stake |
@rwalker-com Thanks for confirming! So, just last question so that I can leave a good comment for the rationale for future reference.
Is my understanding correct? |
I don't understand "naively" in the description. Stakes cannot change during an epoch.
Rent is the cost of doing business, everybody has to hold (or have access to) the same list of accounts, so we pay according to stake, which is a rough proxy for value to the network. |
@rob-solana Thanks again for answering!
"naively" here could be replaced with "faithfully" or "strictly proportional to the validator's stake weights". I know stakes cannot change during an epoch. I wanted to contrast the difference of rent's distribution compared to fee's one.
Thanks for explaining. I'm getting clue. :) So, I have another question from new perspective: Should rent be paid according to stake, without considering staked validator's uptime at all? That's because rent should be rewarded for the storage resource utilization cost. And fees should be rewarded for the computing resource utilization cost. These resource utilization costs should separately be rewarded and thus the distribution methods differ between rents and fees. It's a bit extreme, but stakers can earn rent rewards even if they delegate to a validator which has been delinquent for a whole epoch. Is it ok? This means they can earn some small lamports without risk of slashing. (assuming we don't slash for downtime; or is it planned to slash? CC: @carllin). Anyway, this behavior is very irrational. And much could be earned by delegating to a healthy validator (with slight risk of slashing). |
Stakers are not paid with rent, only the validator is paid. But you're right: there is leakage there that could be addressed with an uptime requirement (maybe scale rent by votes/slots during the epoch). |
@rwalker-com Thanks for further clarification! I'll document what I've learnt later as comments while finishing this pr up. |
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
73b6e5b
to
1e73b3b
Compare
Codecov Report
@@ Coverage Diff @@
## master #12112 +/- ##
=======================================
Coverage 82.1% 82.1%
=======================================
Files 358 358
Lines 83580 83629 +49
=======================================
+ Hits 68630 68671 +41
- Misses 14950 14958 +8 |
// Distribute collected transaction fees for this slot to collector_id (= current leader). | ||
// | ||
// Each validator is incentivized to process more transactions to earn more transaction fees. | ||
// Transaction fees are rewarded for the computing resource utilization cost, directly | ||
// proportional to their actual processing power. | ||
// | ||
// collector_id is rotated according to stake-weighted leader schedule. So the opportunity of | ||
// earning transaction fees are fairly distributed by stake. And missing the opportunity | ||
// (not producing a block as a leader) earns nothing. So, being online is incentivized as a | ||
// form of transaction fees as well. | ||
// | ||
// On the other hand, rent fees are distributed under slightly different philosophy, while | ||
// still being stake-weighted. | ||
// Ref: distribute_rent_to_validators |
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.
@rwalker-com I've added comments based on our discussion some days ago. Does this make sense?
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.
lgtm
// - rent fee doesn't need to be incentivized for throughput unlike transaction fees | ||
// - leader schedule could be manipulated to locate certain validators more often at the | ||
// start of epoch to unfairly earn more rent for the epoch. | ||
// Ref: collect_fees |
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.
@rwalker-com I've added comments based on our discussion some days ago. Does this make sense?
cece0ea
to
530c54c
Compare
@t-nelson I think this is finally ready for review! Could you review this in your spare time? :) |
@@ -29,6 +29,10 @@ pub mod bpf_loader2_program { | |||
solana_sdk::declare_id!("DFBnrgThdzH4W6wZ12uGPoWcMnvfZj11EHnxHcVxLPhD"); | |||
} | |||
|
|||
pub mod no_overflow_rent_distribution { | |||
solana_sdk::declare_id!("4kpdyrcj5jS47CZb2oJGfVxjYbsMm2Kx97gFyZrxxwXz"); |
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.
CC: @mvines I have this private key.
runtime/src/bank.rs
Outdated
const VALIDATOR_STAKE: u64 = 374_999_998_287_840; | ||
|
||
let validator_pubkey = Pubkey::new_rand(); | ||
let bootstrap_validator_stake_lamports = VALIDATOR_STAKE; |
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.
nits: don't need this variable.
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.
LGTM! Let's give Rob a day or so to approve the comments, then in it goes!
if enforce_fix { | ||
assert_eq!(leftover_lamports, 0); | ||
} else if leftover_lamports != 0 { | ||
warn!( |
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.
Not a blocker, but something to think about for the future. Perhaps we should be storing capitalization change events like this with more persistence?
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.
@t-nelson Well, once enfoced_fix
is true, non-zero leftover_lamports
is a very hard error:
https://github.com/solana-labs/solana/pull/12112/files#diff-a7549f152920d85fb44e6a784b8e5e1fR2469
Also, capitalization is now periodically checked when creating a new snapshot #11927
You have a point for alerting by events, but we'll have the most hardest one (dead of cluster) if ever this rent distribution has more leftover or bad capitalization in general.
This lethal nature is justified because this is a possible indication of attempted unauthorized transfer of tokens. (ie security breach, or frankly a theft)
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.
Yeah sure! We'll probably notice the cluster halting soon enough 😉
runtime/src/bank.rs
Outdated
// - leader schedule could be manipulated to locate certain validators more often at the | ||
// start of epoch to unfairly earn more rent for the epoch. |
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.
I think these 2 lines can just be removed.
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.
done! thanks for the review!
Pull request has been modified.
5b9d283
to
542210a
Compare
* Avoid overflow when computing rent distribution * Use assert_eq!.... * Fix tests * Add test * Use FeatureSet * Add comments * Address review comments * Tweak a bit. * Fix fmt (cherry picked from commit e3773d9) # Conflicts: # runtime/src/bank.rs # runtime/src/feature_set.rs
* Avoid overflow when computing rent distribution (#12112) * Avoid overflow when computing rent distribution * Use assert_eq!.... * Fix tests * Add test * Use FeatureSet * Add comments * Address review comments * Tweak a bit. * Fix fmt (cherry picked from commit e3773d9) # Conflicts: # runtime/src/bank.rs # runtime/src/feature_set.rs * Fix conflict Co-authored-by: Ryo Onodera <[email protected]>
well, due to my recnet inflation work, this just enabled only recently.... |
I'm going to enable this on mainnet-beta. I believe this is quite safe although it's expected to be activated on weekend:
|
Well, I changed my mind. I'll do this early next week. |
just enabled on mb, finally!:
|
Problem
rent calculation overflows.
Summary of Changes
Fix it. Also, make any native token distribution code a bit talkative...
Context
Found via bank capitalization, which in turn is used for staking rewards calculation.
This bug has been introduced at #7396