-
Notifications
You must be signed in to change notification settings - Fork 222
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
svm: skip appending loaders to loaded accounts #3631
base: master
Are you sure you want to change the base?
Conversation
4c6d53b
to
05e9cb9
Compare
incidentally i dont know why the vec for program indexes is created with capacity of 2, or why we need vecs for indexes at all. it is possible something is added to the second position inside transaction execution, but i havent checked, and i doubt it. my guess is this used to be used for the loader but was obviated and not fully refactored away when the program cache was added i dont think its worth messing with right now but when im doing simd186 i will take a look and maybe simplify or eliminate it, since im planning on getting rid of this code block once we dont need to count the loaders against transaction size |
@@ -431,11 +431,11 @@ fn load_transaction_accounts<CB: TransactionProcessingCallback>( | |||
let mut tx_rent: TransactionRent = 0; | |||
let account_keys = message.account_keys(); | |||
let mut accounts = Vec::with_capacity(account_keys.len()); | |||
let mut accounts_found = Vec::with_capacity(account_keys.len()); | |||
let mut validated_loaders = AHashSet::with_capacity(PROGRAM_OWNERS.len()); |
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.
optimization; PROGRAM_OWNERS
is a very small set. I imagine we'd actually spend more time hashing here than we would comparing pubkeys?
We can measure but, we can just directly search PROGRAM_OWNERS
, and store the some small stack-space to see if the programs have been seen yet: [false; PROGRAM_OWNERS.len()]
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.
we need to keep the hashset. the capacity of 4 isnt "there can only be 4 loaders" but "we will typically see 2 or maybe 3 loaders if no one is being annoying on purpose, and if they force us to see 5 loaders they waste like a millisecond of compute so have fun i guess"
the loader validation code is extremely delicate--not because of this pr, but before and after this pr--and cannot safely be changed. this is because:
- the consensus definition of a loader is any executable account owned by
NativeLoader
, including stake/vote/system. in practice, with current features, this shouldnt actually matter, because these pseudo-loaders never mark accounts they own as executable, which makes the program fail validation before we validate the loader. however if we want to uphold the "svm is 100% simd83-compliant now, and simd83 means batching doesnt affect results" ideal then technically you could exploit the program cache executable bypass to get a pseudo-loader past validation to execution (although it is only a violation of our ideals, since you cant actually do it without simd83 lock relaxation) - when
disable_account_loader_special_case
activates this quirk goes away and we can assume "loader" means "contained inPROGRAM_OWNERS
- ...and then when
remove_accounts_executable_flag_checks
activates this assumption is ruined because system/vote/stake are valid loaders and accounts they own are valid programs (according to account loading but not according to program cache) and these kinds of transactions will successfully load and move to execution - finally when
enable_transaction_loading_failure_fees
activates we dont have to care about any of this anymore and can assume again that "loader" means "contained inPROGRAM_OWNERS
" as an implementation detail, rather than a consensus constraint, because it doesnt matter how a pseudo-loader transaction fails anymore
and if we changed the technical definition of a loader we would have to introduce a fourth feature gate or backport and cut a new 2.1 declaring previous 2.1 versions invalid
thankfully this is all getting deleted by simd186 anyway
compute_budget_limits.loaded_accounts_bytes, | ||
error_metrics, | ||
)?; | ||
accounts.push((*owner_id, owner_account)); | ||
validated_loaders.insert(*owner_id); |
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.
github won't let me comment further down - curious if we should add a (debug) assert to make sure that accounts
length matches the message's account_keys.len()
- we have a few things that now rely on that assumption, which was not true in the past. Slightly concerned maybe someone changes it in future and breaks stuff and we commit some extra appended accounts.
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.
hmm we could just keep the old way that clamps it to the length of account keys if thats a concern, it doesnt really cost us anything
0de09a5
to
d7550c3
Compare
d7550c3
to
67b4250
Compare
Problem
after transaction account loading, all bpf loaders required for instruction program ids are loaded, validated, counted against transaction size, and appended to the accounts list. validating and counting them is necessary according to current consensus rules, but adding them to accounts is not. all bpf loaders are resident in the batch-local program cache by design, otherwise cpi would not work
Summary of Changes
stop appending them to the accounts list. we also take the opportunity to do some minor housekeeping:
load_account()
is idempotent in its return value, and the second call for an existing account comes from the intermediate account cache, instead of accounts-dbload_account()
, instead of bypassing normal account loading and going directly to accounts-dboverall this pr is a minor cleanup with no effect on runtime behavior. what this code actually does will change several times in the future as feature gates are activated, but eventually when simd186 is implemented we expect to be able to delete it entirely