Skip to content
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

stake-pool: Check transient stake state explicitly during increase / decrease / redelegate #3987

Merged
merged 1 commit into from
Jan 27, 2023

Conversation

joncinque
Copy link
Contributor

Problem

During increase additional, decrease additional, and redelegate, the stake pool program relies on the stake program to check that the merge is correct.

During the epoch in which a validator is added, however, its stake will be "activating", so if you "increase" and then "decrease additional", the decreased stake will actually be added back in since the additional stake is deactivated and then merged into an activating stake, which is valid.

Solution

Don't lean on the runtime, and just do the check explicitly.

@2501babe
Copy link
Member

ok this is very fiddly so i want to make sure i understand it right

this pr adds three checks:

  • when increasing, if additional exists, it must be activating or active
  • when decreasing, if additional exists, it must be deactivating or inactive
  • when redelegating, if additional exists for the destination validator, it must be activating or active

but in the active and inactive cases the stake program rejects it anyway to prevent epoch-jumping

in a normal world, where the validator stake is active, without this pr:

  • increase creates an activating transient stake account out of the reserve
  • decrease additional moves active stake from the validator to ephemeral, puts it into a deactivating state, and attempts to merge it into the activating transient. but because of the state mismatch, this fails

but if the validator stake is activating, again without this pr:

  • increase creates an activating transient stake account out of the reserve
  • decrease additional moves activating stake from the validator to ephemeral (stake_split), and attempts to put it into a deactivating state (stake_deactivate)... but this actually terminates the activation and renders it inactive? so it successfully merges into the activating transient stake?
  • update list balance moves active stake in the next epoch from transient to validator, which includes the "deactivated" portion

but with this pr, increase behaves normally, but decrease additional checks the state of the transient account before creating the ephemeral account and aborts if its flowing in the opposite direction. also you called it "roughly" because you fail on the StakeState::Initialized case, because this is never relevant at the sites you use it

@joncinque
Copy link
Contributor Author

You've got the whole thing correct, thanks for the careful eyes!

decrease additional moves activating stake from the validator to ephemeral (stake_split), and attempts to put it into a deactivating state (stake_deactivate)... but this actually terminates the activation and renders it inactive? so it successfully merges into the activating transient stake?

That's exactly correct. If you deactivate stake that's activating, it just becomes inactive. And when you merge inactive stake into activating stake, the whole thing becomes activating.

@joncinque joncinque merged commit c7a1e98 into solana-labs:master Jan 27, 2023
@joncinque joncinque deleted the sp-explicitcheck branch January 27, 2023 15:09
HaoranYi pushed a commit to HaoranYi/solana-program-library that referenced this pull request Jul 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants