Browse Source

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
Pankaj Garg 1 year ago
parent
commit
af0ed22174

+ 0 - 3
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",

+ 0 - 1
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 }
 

+ 13 - 12
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<u64>,
-    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<FeatureSet>,
     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<u64>,
-        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<FeatureSet>,
         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<u64> {
+    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,
         );

+ 0 - 1
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]

+ 14 - 23
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::<Pubkey>(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::<FeatureSet>::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::<FeatureSet>::default(),
             &sysvar_cache,
         );

+ 0 - 2
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",
 ]
 

+ 9 - 2
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")]

+ 2 - 2
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,
                 ),

+ 0 - 1
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]

+ 3 - 2
svm/doc/spec.md

@@ -133,6 +133,8 @@ pub trait TransactionProcessingCallback {
     fn get_account_shared_data(&self, pubkey: &Pubkey) -> Option<AccountSharedData>;
 
     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.

+ 0 - 3
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",
 ]
 

+ 0 - 1
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"

+ 0 - 1
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"] }

+ 2 - 12
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<u64> {
-        Some(u64::default())
-    }
-
-    fn epoch_vote_accounts(&self, _epoch: Epoch) -> Option<&VoteAccountsHashMap> {
-        None
-    }
-
     fn get_account(&self, pubkey: &Pubkey) -> Option<AccountSharedData> {
         let account_map: HashMap<Pubkey, AccountSharedData> =
             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,

+ 1 - 2
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),

+ 14 - 14
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,
         );

+ 4 - 0
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

+ 15 - 8
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<u64>,
-    /// 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<FeatureSet>,
     /// 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::<FeatureSet>::default(),
             fee_lamports_per_signature: FeeStructure::default().lamports_per_signature, // <-- Default fee.
             rent_collector: None,
@@ -457,6 +453,7 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
                 }
                 TransactionLoadResult::Loaded(loaded_transaction) => {
                     let executed_tx = self.execute_loaded_transaction(
+                        callbacks,
                         tx,
                         loaded_transaction,
                         &mut execute_timings,
@@ -912,8 +909,9 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
     /// 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<CB: TransactionProcessingCallback>(
         &self,
+        callback: &CB,
         tx: &impl SVMTransaction,
         mut loaded_transaction: LoadedTransaction,
         execute_timings: &mut ExecuteTimings,
@@ -978,6 +976,8 @@ impl<FG: ForkGraph> TransactionBatchProcessor<FG> {
 
         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<FG: ForkGraph> TransactionBatchProcessor<FG> {
                 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(),

+ 2 - 2
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,
     );