-
Notifications
You must be signed in to change notification settings - Fork 970
Inconsistent CU charging for ELF size across loaders #10659
Description
Problem
While debugging into LiteSVM/litesvm#297 I would like to share the following observation.
CPI Callee programs charge differently according to the loader they're loaded with. The code snippet under scrutiny -
agave/program-runtime/src/cpi.rs
Lines 1089 to 1098 in 8d074a7
| #[allow(deprecated)] | |
| if callee_account.is_executable() { | |
| // Use the known account | |
| consume_compute_meter( | |
| invoke_context, | |
| (callee_account.get_data().len() as u64) | |
| .checked_div(invoke_context.get_execution_cost().cpi_bytes_per_unit) | |
| .unwrap_or(u64::MAX), | |
| )?; | |
| } else if let Some(caller_account_index) = |
- If they're loaded with
BPFLoaderUpgradeab1e11111111111111111111111(two accounts used here - program metadata + program data) effectively it's the program metadata account size / 250 (cpi_bytes_per_unit) which is 36 (the metadata account) / 250 = 0 CUs that is charged. For example this is the case with https://solscan.io/account/TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb - now if the program is loaded with
BPFLoader2111111111111111111111111111111111, for example https://solscan.io/account/ATokenGPvbdGVxr1b2hvZbsiqW5xWH25efTNsLJA8knL, then effectively it has one single program account holding the data and in the snippet in questionget_data().len()it's 105032 bytes / 250 = 420 CUs
This seems unfair. Now provided that the majority of deployed programs use BPFLoaderUpgradeab1e11111111111111111111111 and that 36 / 250 calculation always results to 0 and hence nothing is charged here why the BPFLoader2111111111111111111111111111111111 loaded programs get so badly treated with full_program_len / 250?
Proposed Solution
Isn't it fair to actually remove the consume_compute_meter call here? If you like I can file a PR doing the change but I believe it's first best to share as you have more context.