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

Update genesis processing to have a fallback collector id for tests #34135

Merged
merged 4 commits into from
Jan 10, 2024

Conversation

jstarry
Copy link
Member

@jstarry jstarry commented Nov 17, 2023

Problem

When creating bank 0 for tests, oftentimes the genesis config doesn't include a staked node. This means that bank creation has to arbitrarily pick a node id for block 0 in order for bank creation to succeed. The arbitrary node id was recently updated to be a random unique pubkey in #33887 but as discussed here we need to make sure this path is never hit by tests.

Summary of Changes

  • Add the arg test_collector_id: Option<Pubkey> to Bank::new_with_paths which can be used as a fallback collector id if no staked nodes are defined in the genesis. This arg is set to None in call-sites that aren't related to testing or benchmarks.

Fixes #

@github-actions github-actions bot added the stale [bot only] Added to stale content; results in auto-close after a week. label Dec 1, 2023
@jstarry jstarry force-pushed the test/cleanup-highest-stake branch 4 times, most recently from d1f78fa to c89ddda Compare December 8, 2023 09:19
@jstarry jstarry marked this pull request as ready for review December 8, 2023 09:19
@jstarry jstarry removed the stale [bot only] Added to stale content; results in auto-close after a week. label Dec 8, 2023
@jstarry jstarry marked this pull request as draft December 8, 2023 13:44
@jstarry jstarry changed the title test cleanup: remove usages of incomplete genesis creation Update genesis processing to have a fallback collector id for tests Dec 8, 2023
@jstarry jstarry marked this pull request as ready for review December 8, 2023 14:49
Copy link

codecov bot commented Dec 18, 2023

Codecov Report

Attention: 1 lines in your changes are missing coverage. Please review.

Comparison is base (b814497) 81.8% compared to head (258244d) 81.8%.

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #34135   +/-   ##
=======================================
  Coverage    81.8%    81.8%           
=======================================
  Files         824      824           
  Lines      222394   222405   +11     
=======================================
+ Hits       181957   181973   +16     
+ Misses      40437    40432    -5     

@t-nelson
Copy link
Contributor

is there something stopping us from fixing up the GenesisConfig instantiation to always include at least one staked node? seems less brittle

@jstarry
Copy link
Member Author

jstarry commented Dec 21, 2023

is there something stopping us from fixing up the GenesisConfig instantiation to always include at least one staked node? seems less brittle

That was my initial approach but it was too unruly. One thing I ran into is that it should still be possible to create a GenesisConfig without staked nodes if you want to unit test the struct and don't instantiate a bank with it. This leaves open constructor methods that can be misused. And many of the tests that need a basic bank don't care about the collector id or staked nodes at all. So I was doing a lot of work to refactor a million tests that really just needed a placeholder collector id. Since test_collector_id can only be set by test methods, this seemed the most sane way.

runtime/src/bank.rs Outdated Show resolved Hide resolved
self.collector_id = self
.stakes_cache
.stakes()
.highest_staked_node()
.unwrap_or_else(Pubkey::new_unique);
.or(test_collector_id)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it be worse to create-and-store this collector id instead? (And maybe manually add it to stakes cache too.) Then it would actually be a proper stake account.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The collector id is the "node id" but yeah we could create a stake account and vote account which delegate stake to the collector id. I'll play around with this.. just wary of breaking dozens of tests with brittle assumptions

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[..] wary of breaking dozens of tests with brittle assumptions

I definitely understand this...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this more, wouldn't it be strange if extra accounts were stored that weren't defined in the genesis?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

is a genesis with no collector a reasonable thing? barring tests that don't strictly need one, that is. this is almost certainly yet another case of data structure abuse that would justify refactor

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would like to just add a genesis_collector_id to the genesis but we can't make backwards incompatible changes to that struct

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we can make a wrapper for tests and a trait though, right?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, we can. It involves updating hundreds of tests and I don't have the time for that.

t-nelson
t-nelson previously approved these changes Jan 4, 2024
Copy link
Contributor

@t-nelson t-nelson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just gross enough to prevent overuse and encourage a refactor 👍

@jstarry
Copy link
Member Author

jstarry commented Jan 9, 2024

I'd like to merge as is, I would also like to this be a bit cleaner but cleaning up the tests is too much of a burden and it's inconvenient that genesis can't be modified to specify an initial collector.

Copy link
Contributor

@brooksprumo brooksprumo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me (but I'm biased a bit). One open question on my end.

@@ -1041,7 +1041,7 @@ impl Bank {
debug_do_not_add_builtins: bool,
accounts_db_config: Option<AccountsDbConfig>,
accounts_update_notifier: Option<AccountsUpdateNotifier>,
#[cfg(feature = "dev-context-only-utils")] collector_id_for_tests: Option<Pubkey>,
#[allow(unused)] collector_id_for_tests: Option<Pubkey>,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess something in the build didn't like marking this parameter as DCOU?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there was a call-site that didn't have DCOU handling and then I just figured it was easier to handle internally. What do you think? Is it confusing that the parameter is ignored?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there was a call-site that didn't have DCOU handling and then I just figured it was easier to handle internally.

Gotcha, thanks.

What do you think? Is it confusing that the parameter is ignored?

I think it's a little confusing, but... the whole codebase is a little confusing, heh. So doesn't seem too confusing IMO.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"easier" is not really what we should be optimizing for at this point in the project's maturity

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah "easier" is not the best word to use there. The main issue is that Rust doesn't let you conditionally add parameters to a function call and so it means duplicating the call site which is a worse dev experience than having an unused parameter.

@jstarry jstarry merged commit 5f74fc4 into solana-labs:master Jan 10, 2024
35 checks passed
@jstarry jstarry deleted the test/cleanup-highest-stake branch January 10, 2024 00:34
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.

3 participants