From af0ed22174999cb62579a0621f6b274c85ebf267 Mon Sep 17 00:00:00 2001 From: Pankaj Garg Date: Wed, 20 Nov 2024 13:21:55 -0800 Subject: [PATCH] Remove SVM's dependency on vote crate (#3671) * Remove SVM's dependency on vote crate * remove dep from json-rpc example * use callback to get epoch vote stake --- Cargo.lock | 3 -- program-runtime/Cargo.toml | 1 - program-runtime/src/invoke_context.rs | 25 +++++++------ programs/bpf_loader/Cargo.toml | 1 - programs/bpf_loader/src/syscalls/mod.rs | 37 +++++++------------ programs/sbf/Cargo.lock | 2 - runtime/src/bank.rs | 11 +++++- .../bank/builtins/core_bpf_migration/mod.rs | 4 +- svm/Cargo.toml | 1 - svm/doc/spec.md | 5 ++- svm/examples/Cargo.lock | 3 -- svm/examples/Cargo.toml | 1 - svm/examples/json-rpc/server/Cargo.toml | 1 - .../json-rpc/server/src/rpc_process.rs | 14 +------ svm/examples/paytube/src/lib.rs | 3 +- svm/src/message_processor.rs | 28 +++++++------- svm/src/transaction_processing_callback.rs | 4 ++ svm/src/transaction_processor.rs | 23 ++++++++---- svm/tests/conformance.rs | 4 +- 19 files changed, 79 insertions(+), 92 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 56919530c26252..33bf1644a402a7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -6225,7 +6225,6 @@ dependencies = [ "solana-sdk", "solana-timings", "solana-type-overrides", - "solana-vote", "solana_rbpf", "test-case", "thiserror 2.0.3", @@ -7893,7 +7892,6 @@ dependencies = [ "solana-sdk", "solana-timings", "solana-type-overrides", - "solana-vote", "solana_rbpf", "test-case", "thiserror 2.0.3", @@ -8854,7 +8852,6 @@ dependencies = [ "solana-system-program", "solana-timings", "solana-type-overrides", - "solana-vote", "solana_rbpf", "test-case", "thiserror 2.0.3", diff --git a/program-runtime/Cargo.toml b/program-runtime/Cargo.toml index 4e764de35b5854..b3a6228cee1be7 100644 --- a/program-runtime/Cargo.toml +++ b/program-runtime/Cargo.toml @@ -35,7 +35,6 @@ solana-metrics = { workspace = true } solana-sdk = { workspace = true } solana-timings = { workspace = true } solana-type-overrides = { workspace = true } -solana-vote = { workspace = true } solana_rbpf = { workspace = true } thiserror = { workspace = true } diff --git a/program-runtime/src/invoke_context.rs b/program-runtime/src/invoke_context.rs index a54e0839ab8036..f6e0e4630a8d3f 100644 --- a/program-runtime/src/invoke_context.rs +++ b/program-runtime/src/invoke_context.rs @@ -40,7 +40,6 @@ use { }, solana_timings::{ExecuteDetailsTimings, ExecuteTimings}, solana_type_overrides::sync::{atomic::Ordering, Arc}, - solana_vote::vote_account::VoteAccountsHashMap, std::{ alloc::Layout, cell::RefCell, @@ -151,8 +150,8 @@ impl BpfAllocator { pub struct EnvironmentConfig<'a> { pub blockhash: Hash, pub blockhash_lamports_per_signature: u64, - epoch_total_stake: Option, - epoch_vote_accounts: Option<&'a VoteAccountsHashMap>, + epoch_total_stake: u64, + get_epoch_vote_account_stake_callback: &'a dyn Fn(&'a Pubkey) -> u64, pub feature_set: Arc, sysvar_cache: &'a SysvarCache, } @@ -160,8 +159,8 @@ impl<'a> EnvironmentConfig<'a> { pub fn new( blockhash: Hash, blockhash_lamports_per_signature: u64, - epoch_total_stake: Option, - epoch_vote_accounts: Option<&'a VoteAccountsHashMap>, + epoch_total_stake: u64, + get_epoch_vote_account_stake_callback: &'a dyn Fn(&'a Pubkey) -> u64, feature_set: Arc, sysvar_cache: &'a SysvarCache, ) -> Self { @@ -169,7 +168,7 @@ impl<'a> EnvironmentConfig<'a> { blockhash, blockhash_lamports_per_signature, epoch_total_stake, - epoch_vote_accounts, + get_epoch_vote_account_stake_callback, feature_set, sysvar_cache, } @@ -658,13 +657,15 @@ impl<'a> InvokeContext<'a> { } /// Get cached epoch total stake. - pub fn get_epoch_total_stake(&self) -> Option { + pub fn get_epoch_total_stake(&self) -> u64 { self.environment_config.epoch_total_stake } - /// Get cached epoch vote accounts. - pub fn get_epoch_vote_accounts(&self) -> Option<&VoteAccountsHashMap> { - self.environment_config.epoch_vote_accounts + /// Get cached stake for the epoch vote account. + pub fn get_epoch_vote_account_stake(&self, pubkey: &'a Pubkey) -> u64 { + (self + .environment_config + .get_epoch_vote_account_stake_callback)(pubkey) } // Should alignment be enforced during user pointer translation @@ -765,8 +766,8 @@ macro_rules! with_mock_invoke_context { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); diff --git a/programs/bpf_loader/Cargo.toml b/programs/bpf_loader/Cargo.toml index 8fb86df6d28ab3..3c62ccc69fcfa1 100644 --- a/programs/bpf_loader/Cargo.toml +++ b/programs/bpf_loader/Cargo.toml @@ -35,7 +35,6 @@ assert_matches = { workspace = true } memoffset = { workspace = true } rand = { workspace = true } solana-sdk = { workspace = true, features = ["dev-context-only-utils"] } -solana-vote = { workspace = true, features = ["dev-context-only-utils"] } test-case = { workspace = true } [lib] diff --git a/programs/bpf_loader/src/syscalls/mod.rs b/programs/bpf_loader/src/syscalls/mod.rs index 4255463ce66992..3438c819c74bbe 100644 --- a/programs/bpf_loader/src/syscalls/mod.rs +++ b/programs/bpf_loader/src/syscalls/mod.rs @@ -2071,7 +2071,7 @@ declare_builtin_function!( // - Compute budget is exceeded. // - Otherwise, the syscall returns a `u64` integer representing the total active // stake on the cluster for the current epoch. - Ok(invoke_context.get_epoch_total_stake().unwrap_or(0)) + Ok(invoke_context.get_epoch_total_stake()) } else { // As specified by SIMD-0133: If `var_addr` is _not_ a null pointer: // @@ -2103,16 +2103,7 @@ declare_builtin_function!( let check_aligned = invoke_context.get_check_aligned(); let vote_address = translate_type::(memory_mapping, var_addr, check_aligned)?; - Ok( - if let Some(vote_accounts) = invoke_context.get_epoch_vote_accounts() { - vote_accounts - .get(vote_address) - .map(|(stake, _)| *stake) - .unwrap_or(0) - } else { - 0 - }, - ) + Ok(invoke_context.get_epoch_vote_account_stake(vote_address)) } } ); @@ -2147,8 +2138,7 @@ mod tests { last_restart_slot::LastRestartSlot, }, }, - solana_vote::vote_account::VoteAccount, - std::{collections::HashMap, mem, str::FromStr}, + std::{mem, str::FromStr}, test_case::test_case, }; @@ -4801,8 +4791,8 @@ mod tests { invoke_context.environment_config = EnvironmentConfig::new( Hash::default(), 0, - Some(expected_total_stake), - None, // Vote accounts are not needed for this test. + expected_total_stake, + &|_| 0, // Vote accounts are not needed for this test. Arc::::default(), &sysvar_cache, ); @@ -4845,18 +4835,19 @@ mod tests { compute_budget.compute_unit_limit = expected_cus; let vote_address = Pubkey::new_unique(); - let mut vote_accounts_map = HashMap::new(); - vote_accounts_map.insert( - vote_address, - (expected_epoch_stake, VoteAccount::new_random()), - ); - with_mock_invoke_context!(invoke_context, transaction_context, vec![]); + let callback = |pubkey: &Pubkey| { + if *pubkey == vote_address { + expected_epoch_stake + } else { + 0 + } + }; invoke_context.environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, // Total stake is not needed for this test. - Some(&vote_accounts_map), + 0, // Total stake is not needed for this test. + &callback, Arc::::default(), &sysvar_cache, ); diff --git a/programs/sbf/Cargo.lock b/programs/sbf/Cargo.lock index ab98c6647a3e41..6f4f4ab57c76e8 100644 --- a/programs/sbf/Cargo.lock +++ b/programs/sbf/Cargo.lock @@ -6217,7 +6217,6 @@ dependencies = [ "solana-sdk", "solana-timings", "solana-type-overrides", - "solana-vote", "solana_rbpf", "thiserror 2.0.3", ] @@ -7477,7 +7476,6 @@ dependencies = [ "solana-system-program", "solana-timings", "solana-type-overrides", - "solana-vote", "thiserror 2.0.3", ] diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 47769392453a7b..a115b62a5b5d86 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -1464,6 +1464,7 @@ impl Bank { .unwrap() .stats .reset(); + new } @@ -3768,8 +3769,7 @@ impl Bank { let processing_environment = TransactionProcessingEnvironment { blockhash, blockhash_lamports_per_signature, - epoch_total_stake: Some(self.get_current_epoch_total_stake()), - epoch_vote_accounts: Some(self.get_current_epoch_vote_accounts()), + epoch_total_stake: self.get_current_epoch_total_stake(), feature_set: Arc::clone(&self.feature_set), fee_lamports_per_signature: self.fee_structure.lamports_per_signature, rent_collector: Some(&rent_collector_with_metrics), @@ -7146,6 +7146,13 @@ impl TransactionProcessingCallback for Bank { self.inspect_account_for_accounts_lt_hash(address, &account_state, is_writable); } } + + fn get_current_epoch_vote_account_stake(&self, vote_address: &Pubkey) -> u64 { + self.get_current_epoch_vote_accounts() + .get(vote_address) + .map(|(stake, _)| (*stake)) + .unwrap_or(0) + } } #[cfg(feature = "dev-context-only-utils")] diff --git a/runtime/src/bank/builtins/core_bpf_migration/mod.rs b/runtime/src/bank/builtins/core_bpf_migration/mod.rs index ec960847e2350f..28308499f3851f 100644 --- a/runtime/src/bank/builtins/core_bpf_migration/mod.rs +++ b/runtime/src/bank/builtins/core_bpf_migration/mod.rs @@ -202,8 +202,8 @@ impl Bank { EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, self.feature_set.clone(), &sysvar_cache, ), diff --git a/svm/Cargo.toml b/svm/Cargo.toml index 7d757e27f86b68..4b7d48332e4eed 100644 --- a/svm/Cargo.toml +++ b/svm/Cargo.toml @@ -38,7 +38,6 @@ solana-svm-transaction = { workspace = true } solana-system-program = { workspace = true } solana-timings = { workspace = true } solana-type-overrides = { workspace = true } -solana-vote = { workspace = true } thiserror = { workspace = true } [lib] diff --git a/svm/doc/spec.md b/svm/doc/spec.md index a3e0c4b09ac574..5a16428102c178 100644 --- a/svm/doc/spec.md +++ b/svm/doc/spec.md @@ -133,6 +133,8 @@ pub trait TransactionProcessingCallback { fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option; fn add_builtin_account(&self, _name: &str, _program_id: &Pubkey) {} + + fn get_current_epoch_vote_account_stake(&self, _vote_address: &Pubkey) -> u64; } ``` @@ -171,9 +173,8 @@ The transaction processor requires consumers to provide values describing the runtime environment to use for processing transactions. - `blockhash`: The blockhash to use for the transaction batch. -- `epoch_total_stake`: The total stake for the current epoch. -- `epoch_vote_accounts`: The vote accounts for the current epoch. - `feature_set`: Runtime feature set to use for the transaction batch. +- `epoch_total_stake`: The total stake for the current epoch. - `fee_structure`: Fee structure to use for assessing transaction fees. - `lamports_per_signature`: Lamports per signature to charge per transaction. - `rent_collector`: Rent collector to use for the transaction batch. diff --git a/svm/examples/Cargo.lock b/svm/examples/Cargo.lock index 0f1ad06541fb77..7063039b4739bd 100644 --- a/svm/examples/Cargo.lock +++ b/svm/examples/Cargo.lock @@ -2597,7 +2597,6 @@ dependencies = [ "solana-system-program", "solana-transaction-status", "solana-version", - "solana-vote", "spl-token-2022", "tokio", "tokio-util 0.7.12", @@ -6038,7 +6037,6 @@ dependencies = [ "solana-sdk", "solana-timings", "solana-type-overrides", - "solana-vote", "solana_rbpf", "thiserror 2.0.3", ] @@ -6812,7 +6810,6 @@ dependencies = [ "solana-system-program", "solana-timings", "solana-type-overrides", - "solana-vote", "thiserror 2.0.3", ] diff --git a/svm/examples/Cargo.toml b/svm/examples/Cargo.toml index 823899d3517660..a5df7288e95576 100644 --- a/svm/examples/Cargo.toml +++ b/svm/examples/Cargo.toml @@ -43,7 +43,6 @@ solana-sdk = { path = "../../sdk/" } solana-svm = { path = "../" } solana-system-program = { path = "../../programs/system" } solana-version = { path = "../../version" } -solana-vote = { path = "../../vote" } solana-test-validator = { path = "../../test-validator" } solana-transaction-status = { path = "../../transaction-status" } spl-associated-token-account = "=6.0.0" diff --git a/svm/examples/json-rpc/server/Cargo.toml b/svm/examples/json-rpc/server/Cargo.toml index d78532222234f6..fd0558a5cf97e5 100644 --- a/svm/examples/json-rpc/server/Cargo.toml +++ b/svm/examples/json-rpc/server/Cargo.toml @@ -30,7 +30,6 @@ solana-svm = { workspace = true } solana-system-program = { workspace = true } solana-transaction-status = { workspace = true } solana-version = { workspace = true } -solana-vote = { workspace = true } spl-token-2022 = { workspace = true, features = ["no-entrypoint"] } tokio = { workspace = true, features = ["full"] } tokio-util = { workspace = true, features = ["codec", "compat"] } diff --git a/svm/examples/json-rpc/server/src/rpc_process.rs b/svm/examples/json-rpc/server/src/rpc_process.rs index fdea14aab20369..280496f0903225 100644 --- a/svm/examples/json-rpc/server/src/rpc_process.rs +++ b/svm/examples/json-rpc/server/src/rpc_process.rs @@ -24,7 +24,7 @@ use { }, solana_sdk::{ account::{from_account, Account, AccountSharedData, ReadableAccount}, - clock::{Epoch, Slot, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY}, + clock::{Slot, MAX_PROCESSING_AGE, MAX_TRANSACTION_FORWARDING_DELAY}, commitment_config::CommitmentConfig, exit::Exit, hash::Hash, @@ -61,7 +61,6 @@ use { map_inner_instructions, parse_ui_inner_instructions, TransactionBinaryEncoding, UiTransactionEncoding, }, - solana_vote::vote_account::VoteAccountsHashMap, spl_token_2022::{ extension::{ interest_bearing_mint::InterestBearingConfig, BaseStateWithExtensions, @@ -435,14 +434,6 @@ impl JsonRpcRequestProcessor { .unwrap_or_default() } - fn epoch_total_stake(&self, _epoch: Epoch) -> Option { - Some(u64::default()) - } - - fn epoch_vote_accounts(&self, _epoch: Epoch) -> Option<&VoteAccountsHashMap> { - None - } - fn get_account(&self, pubkey: &Pubkey) -> Option { let account_map: HashMap = HashMap::from_iter(self.account_map.clone()); @@ -547,8 +538,7 @@ impl JsonRpcRequestProcessor { let processing_environment = TransactionProcessingEnvironment { blockhash, blockhash_lamports_per_signature: lamports_per_signature, - epoch_total_stake: self.epoch_total_stake(Epoch::default()), - epoch_vote_accounts: self.epoch_vote_accounts(Epoch::default()), + epoch_total_stake: 0, feature_set: Arc::clone(&bank.feature_set), fee_lamports_per_signature: lamports_per_signature, rent_collector: None, diff --git a/svm/examples/paytube/src/lib.rs b/svm/examples/paytube/src/lib.rs index 6db007ceb22c93..a219f7e783d314 100644 --- a/svm/examples/paytube/src/lib.rs +++ b/svm/examples/paytube/src/lib.rs @@ -148,8 +148,7 @@ impl PayTubeChannel { let processing_environment = TransactionProcessingEnvironment { blockhash: Hash::default(), blockhash_lamports_per_signature: fee_structure.lamports_per_signature, - epoch_total_stake: None, - epoch_vote_accounts: None, + epoch_total_stake: 0, feature_set: Arc::new(feature_set), fee_lamports_per_signature: fee_structure.lamports_per_signature, rent_collector: Some(&rent_collector), diff --git a/svm/src/message_processor.rs b/svm/src/message_processor.rs index 87ec0cf0e49d97..add06c690b4ba3 100644 --- a/svm/src/message_processor.rs +++ b/svm/src/message_processor.rs @@ -258,8 +258,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); @@ -312,8 +312,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); @@ -356,8 +356,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); @@ -491,8 +491,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); @@ -530,8 +530,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); @@ -566,8 +566,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); @@ -663,8 +663,8 @@ mod tests { let environment_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, Arc::new(FeatureSet::all_enabled()), &sysvar_cache, ); diff --git a/svm/src/transaction_processing_callback.rs b/svm/src/transaction_processing_callback.rs index 34741e9bd7ae3a..a1356fc06e6da2 100644 --- a/svm/src/transaction_processing_callback.rs +++ b/svm/src/transaction_processing_callback.rs @@ -10,6 +10,10 @@ pub trait TransactionProcessingCallback { fn inspect_account(&self, _address: &Pubkey, _account_state: AccountState, _is_writable: bool) { } + + fn get_current_epoch_vote_account_stake(&self, _vote_address: &Pubkey) -> u64 { + 0 + } } /// The state the account is in initially, before transaction processing diff --git a/svm/src/transaction_processor.rs b/svm/src/transaction_processor.rs index 739e703ffc81ab..18125318ef8056 100644 --- a/svm/src/transaction_processor.rs +++ b/svm/src/transaction_processor.rs @@ -63,7 +63,6 @@ use { solana_svm_transaction::{svm_message::SVMMessage, svm_transaction::SVMTransaction}, solana_timings::{ExecuteTimingType, ExecuteTimings}, solana_type_overrides::sync::{atomic::Ordering, Arc, RwLock, RwLockReadGuard}, - solana_vote::vote_account::VoteAccountsHashMap, std::{ collections::{hash_map::Entry, HashMap, HashSet}, fmt::{Debug, Formatter}, @@ -140,9 +139,7 @@ pub struct TransactionProcessingEnvironment<'a> { /// `fee_per_signature` field to adjust transaction fees. pub blockhash_lamports_per_signature: u64, /// The total stake for the current epoch. - pub epoch_total_stake: Option, - /// The vote accounts for the current epoch. - pub epoch_vote_accounts: Option<&'a VoteAccountsHashMap>, + pub epoch_total_stake: u64, /// Runtime feature set to use for the transaction batch. pub feature_set: Arc, /// Transaction fee to charge per signature, in lamports. @@ -156,8 +153,7 @@ impl Default for TransactionProcessingEnvironment<'_> { Self { blockhash: Hash::default(), blockhash_lamports_per_signature: 0, - epoch_total_stake: None, - epoch_vote_accounts: None, + epoch_total_stake: 0, feature_set: Arc::::default(), fee_lamports_per_signature: FeeStructure::default().lamports_per_signature, // <-- Default fee. rent_collector: None, @@ -457,6 +453,7 @@ impl TransactionBatchProcessor { } TransactionLoadResult::Loaded(loaded_transaction) => { let executed_tx = self.execute_loaded_transaction( + callbacks, tx, loaded_transaction, &mut execute_timings, @@ -912,8 +909,9 @@ impl TransactionBatchProcessor { /// Execute a transaction using the provided loaded accounts and update /// the executors cache if the transaction was successful. #[allow(clippy::too_many_arguments)] - fn execute_loaded_transaction( + fn execute_loaded_transaction( &self, + callback: &CB, tx: &impl SVMTransaction, mut loaded_transaction: LoadedTransaction, execute_timings: &mut ExecuteTimings, @@ -978,6 +976,8 @@ impl TransactionBatchProcessor { let mut executed_units = 0u64; let sysvar_cache = &self.sysvar_cache.read().unwrap(); + let epoch_vote_account_stake_callback = + |pubkey| callback.get_current_epoch_vote_account_stake(pubkey); let mut invoke_context = InvokeContext::new( &mut transaction_context, @@ -986,7 +986,7 @@ impl TransactionBatchProcessor { environment.blockhash, environment.blockhash_lamports_per_signature, environment.epoch_total_stake, - environment.epoch_vote_accounts, + &epoch_vote_account_stake_callback, Arc::clone(&environment.feature_set), sysvar_cache, ), @@ -1449,7 +1449,10 @@ mod tests { let mut processing_config = TransactionProcessingConfig::default(); processing_config.recording_config.enable_log_recording = true; + let mock_bank = MockBankCallback::default(); + let executed_tx = batch_processor.execute_loaded_transaction( + &mock_bank, &sanitized_transaction, loaded_transaction.clone(), &mut ExecuteTimings::default(), @@ -1463,6 +1466,7 @@ mod tests { processing_config.log_messages_bytes_limit = Some(2); let executed_tx = batch_processor.execute_loaded_transaction( + &mock_bank, &sanitized_transaction, loaded_transaction.clone(), &mut ExecuteTimings::default(), @@ -1479,6 +1483,7 @@ mod tests { processing_config.log_messages_bytes_limit = None; let executed_tx = batch_processor.execute_loaded_transaction( + &mock_bank, &sanitized_transaction, loaded_transaction, &mut ExecuteTimings::default(), @@ -1541,8 +1546,10 @@ mod tests { ..Default::default() }; let mut error_metrics = TransactionErrorMetrics::new(); + let mock_bank = MockBankCallback::default(); let _ = batch_processor.execute_loaded_transaction( + &mock_bank, &sanitized_transaction, loaded_transaction, &mut ExecuteTimings::default(), diff --git a/svm/tests/conformance.rs b/svm/tests/conformance.rs index fbbcefaedce694..39a2796c2f1a94 100644 --- a/svm/tests/conformance.rs +++ b/svm/tests/conformance.rs @@ -444,8 +444,8 @@ fn execute_fixture_as_instr( let env_config = EnvironmentConfig::new( Hash::default(), 0, - None, - None, + 0, + &|_| 0, mock_bank.feature_set.clone(), sysvar_cache, );