vote_simulator.rs 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  1. #![cfg(feature = "dev-context-only-utils")]
  2. use {
  3. crate::{
  4. cluster_info_vote_listener::VoteTracker,
  5. cluster_slots_service::cluster_slots::ClusterSlots,
  6. consensus::{
  7. fork_choice::{select_vote_and_reset_forks, SelectVoteAndResetForkResult},
  8. heaviest_subtree_fork_choice::HeaviestSubtreeForkChoice,
  9. latest_validator_votes_for_frozen_banks::LatestValidatorVotesForFrozenBanks,
  10. progress_map::{ForkProgress, ProgressMap},
  11. tower_vote_state::TowerVoteState,
  12. Tower,
  13. },
  14. repair::cluster_slot_state_verifier::{
  15. DuplicateConfirmedSlots, DuplicateSlotsTracker, EpochSlotsFrozenSlots,
  16. },
  17. replay_stage::{HeaviestForkFailures, ReplayStage, TowerBFTStructures},
  18. unfrozen_gossip_verified_vote_hashes::UnfrozenGossipVerifiedVoteHashes,
  19. },
  20. crossbeam_channel::unbounded,
  21. solana_clock::Slot,
  22. solana_hash::Hash,
  23. solana_pubkey::Pubkey,
  24. solana_runtime::{
  25. bank::Bank,
  26. bank_forks::BankForks,
  27. genesis_utils::{
  28. create_genesis_config_with_vote_accounts, GenesisConfigInfo, ValidatorVoteKeypairs,
  29. },
  30. },
  31. solana_signer::Signer,
  32. solana_vote::vote_transaction,
  33. solana_vote_program::vote_state::{Lockout, TowerSync},
  34. std::{
  35. collections::{HashMap, HashSet, VecDeque},
  36. sync::{Arc, RwLock},
  37. },
  38. trees::{tr, Tree, TreeWalk},
  39. };
  40. pub struct VoteSimulator {
  41. pub validator_keypairs: HashMap<Pubkey, ValidatorVoteKeypairs>,
  42. pub node_pubkeys: Vec<Pubkey>,
  43. pub vote_pubkeys: Vec<Pubkey>,
  44. pub bank_forks: Arc<RwLock<BankForks>>,
  45. pub progress: ProgressMap,
  46. pub latest_validator_votes_for_frozen_banks: LatestValidatorVotesForFrozenBanks,
  47. pub tbft_structs: TowerBFTStructures,
  48. }
  49. impl VoteSimulator {
  50. pub fn new(num_keypairs: usize) -> Self {
  51. let (
  52. validator_keypairs,
  53. node_pubkeys,
  54. vote_pubkeys,
  55. bank_forks,
  56. progress,
  57. heaviest_subtree_fork_choice,
  58. ) = Self::init_state(num_keypairs);
  59. Self {
  60. validator_keypairs,
  61. node_pubkeys,
  62. vote_pubkeys,
  63. bank_forks,
  64. progress,
  65. latest_validator_votes_for_frozen_banks: LatestValidatorVotesForFrozenBanks::default(),
  66. tbft_structs: TowerBFTStructures {
  67. heaviest_subtree_fork_choice,
  68. duplicate_slots_tracker: DuplicateSlotsTracker::default(),
  69. duplicate_confirmed_slots: DuplicateConfirmedSlots::default(),
  70. unfrozen_gossip_verified_vote_hashes: UnfrozenGossipVerifiedVoteHashes::default(),
  71. epoch_slots_frozen_slots: EpochSlotsFrozenSlots::default(),
  72. },
  73. }
  74. }
  75. pub fn fill_bank_forks(
  76. &mut self,
  77. forks: Tree<u64>,
  78. cluster_votes: &HashMap<Pubkey, Vec<u64>>,
  79. is_frozen: bool,
  80. ) {
  81. let root = *forks.root().data();
  82. assert!(self.bank_forks.read().unwrap().get(root).is_some());
  83. let mut walk = TreeWalk::from(forks);
  84. while let Some(visit) = walk.get() {
  85. let slot = *visit.node().data();
  86. if self.bank_forks.read().unwrap().get(slot).is_some() {
  87. walk.forward();
  88. continue;
  89. }
  90. let parent = *walk.get_parent().unwrap().data();
  91. let parent_bank = self.bank_forks.read().unwrap().get(parent).unwrap();
  92. let new_bank = Bank::new_from_parent(parent_bank.clone(), &Pubkey::default(), slot);
  93. let new_bank = self
  94. .bank_forks
  95. .write()
  96. .unwrap()
  97. .insert(new_bank)
  98. .clone_without_scheduler();
  99. self.progress
  100. .entry(slot)
  101. .or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0));
  102. for (pubkey, vote) in cluster_votes.iter() {
  103. if vote.contains(&parent) {
  104. let keypairs = self.validator_keypairs.get(pubkey).unwrap();
  105. let latest_blockhash = parent_bank.last_blockhash();
  106. let tower_sync = if let Some(vote_account) =
  107. parent_bank.get_vote_account(&keypairs.vote_keypair.pubkey())
  108. {
  109. let mut vote_state = TowerVoteState::from(
  110. vote_account.vote_state_view().expect("must be TowerBFT"),
  111. );
  112. vote_state.process_next_vote_slot(parent);
  113. TowerSync::new(
  114. vote_state.votes,
  115. vote_state.root_slot,
  116. parent_bank.hash(),
  117. Hash::default(),
  118. )
  119. } else {
  120. TowerSync::new(
  121. VecDeque::from([Lockout::new(parent)]),
  122. Some(root),
  123. parent_bank.hash(),
  124. Hash::default(),
  125. )
  126. };
  127. let vote_tx = vote_transaction::new_tower_sync_transaction(
  128. tower_sync,
  129. latest_blockhash,
  130. &keypairs.node_keypair,
  131. &keypairs.vote_keypair,
  132. &keypairs.vote_keypair,
  133. None,
  134. );
  135. info!("voting {} {}", parent_bank.slot(), parent_bank.hash());
  136. new_bank.process_transaction(&vote_tx).unwrap();
  137. // Check the vote landed
  138. let vote_account = new_bank
  139. .get_vote_account(&keypairs.vote_keypair.pubkey())
  140. .unwrap();
  141. let vote_state_view = vote_account.vote_state_view().unwrap();
  142. assert!(vote_state_view
  143. .votes_iter()
  144. .any(|lockout| lockout.slot() == parent));
  145. }
  146. }
  147. new_bank.fill_bank_with_ticks_for_tests();
  148. if !visit.node().has_no_child() || is_frozen {
  149. new_bank.set_block_id(Some(Hash::new_unique()));
  150. new_bank.freeze();
  151. self.progress
  152. .get_fork_stats_mut(new_bank.slot())
  153. .expect("All frozen banks must exist in the Progress map")
  154. .bank_hash = Some(new_bank.hash());
  155. self.tbft_structs
  156. .heaviest_subtree_fork_choice
  157. .add_new_leaf_slot(
  158. (new_bank.slot(), new_bank.hash()),
  159. Some((new_bank.parent_slot(), new_bank.parent_hash())),
  160. );
  161. }
  162. walk.forward();
  163. }
  164. }
  165. pub fn simulate_vote(
  166. &mut self,
  167. vote_slot: Slot,
  168. my_pubkey: &Pubkey,
  169. tower: &mut Tower,
  170. ) -> Vec<HeaviestForkFailures> {
  171. // Try to simulate the vote
  172. let ancestors = self.bank_forks.read().unwrap().ancestors();
  173. let mut frozen_banks: Vec<_> = self
  174. .bank_forks
  175. .read()
  176. .unwrap()
  177. .frozen_banks()
  178. .map(|(_slot, bank)| bank)
  179. .collect();
  180. let _ = ReplayStage::compute_bank_stats(
  181. my_pubkey,
  182. &ancestors,
  183. &mut frozen_banks,
  184. tower,
  185. &mut self.progress,
  186. &VoteTracker::default(),
  187. &ClusterSlots::default(),
  188. &self.bank_forks,
  189. &mut self.tbft_structs.heaviest_subtree_fork_choice,
  190. &mut self.latest_validator_votes_for_frozen_banks,
  191. );
  192. let vote_bank = self
  193. .bank_forks
  194. .read()
  195. .unwrap()
  196. .get(vote_slot)
  197. .expect("Bank must have been created before vote simulation");
  198. // Try to vote on the given slot
  199. let descendants = self.bank_forks.read().unwrap().descendants();
  200. let SelectVoteAndResetForkResult {
  201. heaviest_fork_failures,
  202. ..
  203. } = select_vote_and_reset_forks(
  204. &vote_bank,
  205. None,
  206. &ancestors,
  207. &descendants,
  208. &self.progress,
  209. tower,
  210. &self.latest_validator_votes_for_frozen_banks,
  211. &self.tbft_structs.heaviest_subtree_fork_choice,
  212. );
  213. // Make sure this slot isn't locked out or failing threshold
  214. info!("Checking vote: {}", vote_bank.slot());
  215. if !heaviest_fork_failures.is_empty() {
  216. return heaviest_fork_failures;
  217. }
  218. let new_root = tower.record_bank_vote(&vote_bank);
  219. if let Some(new_root) = new_root {
  220. self.set_root(new_root);
  221. }
  222. vec![]
  223. }
  224. pub fn set_root(&mut self, new_root: Slot) {
  225. let (drop_bank_sender, _drop_bank_receiver) = unbounded();
  226. ReplayStage::handle_new_root(
  227. new_root,
  228. &self.bank_forks,
  229. &mut self.progress,
  230. None, // snapshot_controller
  231. None,
  232. &mut true,
  233. &drop_bank_sender,
  234. &mut self.tbft_structs,
  235. )
  236. .unwrap();
  237. }
  238. pub fn create_and_vote_new_branch(
  239. &mut self,
  240. start_slot: Slot,
  241. end_slot: Slot,
  242. cluster_votes: &HashMap<Pubkey, Vec<u64>>,
  243. votes_to_simulate: &HashSet<Slot>,
  244. my_pubkey: &Pubkey,
  245. tower: &mut Tower,
  246. ) -> HashMap<Slot, Vec<HeaviestForkFailures>> {
  247. (start_slot + 1..=end_slot)
  248. .filter_map(|slot| {
  249. let mut fork_tip_parent = tr(slot - 1);
  250. fork_tip_parent.push_front(tr(slot));
  251. self.fill_bank_forks(fork_tip_parent, cluster_votes, true);
  252. if votes_to_simulate.contains(&slot) {
  253. Some((slot, self.simulate_vote(slot, my_pubkey, tower)))
  254. } else {
  255. None
  256. }
  257. })
  258. .collect()
  259. }
  260. pub fn simulate_lockout_interval(
  261. &mut self,
  262. slot: Slot,
  263. lockout_interval: (u64, u64),
  264. vote_account_pubkey: &Pubkey,
  265. ) {
  266. self.progress
  267. .entry(slot)
  268. .or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0))
  269. .fork_stats
  270. .lockout_intervals
  271. .entry(lockout_interval.1)
  272. .or_default()
  273. .push((lockout_interval.0, *vote_account_pubkey));
  274. }
  275. pub fn clear_lockout_intervals(&mut self, slot: Slot) {
  276. self.progress
  277. .entry(slot)
  278. .or_insert_with(|| ForkProgress::new(Hash::default(), None, None, 0, 0))
  279. .fork_stats
  280. .lockout_intervals
  281. .clear()
  282. }
  283. pub fn can_progress_on_fork(
  284. &mut self,
  285. my_pubkey: &Pubkey,
  286. tower: &mut Tower,
  287. start_slot: u64,
  288. num_slots: u64,
  289. cluster_votes: &mut HashMap<Pubkey, Vec<u64>>,
  290. ) -> bool {
  291. // Check that within some reasonable time, validator can make a new
  292. // root on this fork
  293. let old_root = tower.root();
  294. for i in 1..num_slots {
  295. // The parent of the tip of the fork
  296. let mut fork_tip_parent = tr(start_slot + i - 1);
  297. // The tip of the fork
  298. fork_tip_parent.push_front(tr(start_slot + i));
  299. self.fill_bank_forks(fork_tip_parent, cluster_votes, true);
  300. if self
  301. .simulate_vote(i + start_slot, my_pubkey, tower)
  302. .is_empty()
  303. {
  304. cluster_votes
  305. .entry(*my_pubkey)
  306. .or_default()
  307. .push(start_slot + i);
  308. }
  309. if old_root != tower.root() {
  310. return true;
  311. }
  312. }
  313. false
  314. }
  315. #[allow(clippy::type_complexity)]
  316. fn init_state(
  317. num_keypairs: usize,
  318. ) -> (
  319. HashMap<Pubkey, ValidatorVoteKeypairs>,
  320. Vec<Pubkey>,
  321. Vec<Pubkey>,
  322. Arc<RwLock<BankForks>>,
  323. ProgressMap,
  324. HeaviestSubtreeForkChoice,
  325. ) {
  326. let keypairs: HashMap<_, _> = std::iter::repeat_with(|| {
  327. let vote_keypairs = ValidatorVoteKeypairs::new_rand();
  328. (vote_keypairs.node_keypair.pubkey(), vote_keypairs)
  329. })
  330. .take(num_keypairs)
  331. .collect();
  332. let node_pubkeys: Vec<_> = keypairs
  333. .values()
  334. .map(|keys| keys.node_keypair.pubkey())
  335. .collect();
  336. let vote_pubkeys: Vec<_> = keypairs
  337. .values()
  338. .map(|keys| keys.vote_keypair.pubkey())
  339. .collect();
  340. let (bank_forks, progress, heaviest_subtree_fork_choice) =
  341. initialize_state(&keypairs, 10_000);
  342. (
  343. keypairs,
  344. node_pubkeys,
  345. vote_pubkeys,
  346. bank_forks,
  347. progress,
  348. heaviest_subtree_fork_choice,
  349. )
  350. }
  351. }
  352. // Setup BankForks with bank 0 and all the validator accounts
  353. pub fn initialize_state(
  354. validator_keypairs_map: &HashMap<Pubkey, ValidatorVoteKeypairs>,
  355. stake: u64,
  356. ) -> (
  357. Arc<RwLock<BankForks>>,
  358. ProgressMap,
  359. HeaviestSubtreeForkChoice,
  360. ) {
  361. let validator_keypairs: Vec<_> = validator_keypairs_map.values().collect();
  362. let GenesisConfigInfo {
  363. mut genesis_config,
  364. mint_keypair,
  365. ..
  366. } = create_genesis_config_with_vote_accounts(
  367. 1_000_000_000,
  368. &validator_keypairs,
  369. vec![stake; validator_keypairs.len()],
  370. );
  371. genesis_config.poh_config.hashes_per_tick = Some(2);
  372. let (bank0, bank_forks) = Bank::new_with_bank_forks_for_tests(&genesis_config);
  373. bank0.set_block_id(Some(Hash::new_unique()));
  374. for pubkey in validator_keypairs_map.keys() {
  375. bank0.transfer(10_000, &mint_keypair, pubkey).unwrap();
  376. }
  377. bank0.fill_bank_with_ticks_for_tests();
  378. bank0.freeze();
  379. let mut progress = ProgressMap::default();
  380. progress.insert(
  381. 0,
  382. ForkProgress::new_from_bank(&bank0, bank0.collector_id(), &Pubkey::default(), None, 0, 0),
  383. );
  384. let heaviest_subtree_fork_choice =
  385. HeaviestSubtreeForkChoice::new_from_bank_forks(bank_forks.clone());
  386. (bank_forks, progress, heaviest_subtree_fork_choice)
  387. }