From 0fd6f268a310088df89ecb0da2eba654a53bed7e Mon Sep 17 00:00:00 2001 From: Evan Batsell Date: Mon, 2 Dec 2024 18:17:08 -0500 Subject: [PATCH] Lints --- core/src/ballot_box.rs | 31 ++++++++++++++++--- meta_merkle_tree/src/error.rs | 2 ++ meta_merkle_tree/src/generated_merkle_tree.rs | 16 +++++----- meta_merkle_tree/src/merkle_tree.rs | 19 ++++++------ meta_merkle_tree/src/meta_merkle_tree.rs | 10 ++++-- meta_merkle_tree/src/tree_node.rs | 4 +-- program/src/set_merkle_root.rs | 2 +- 7 files changed, 56 insertions(+), 28 deletions(-) diff --git a/core/src/ballot_box.rs b/core/src/ballot_box.rs index 871cb1b..cb35014 100644 --- a/core/src/ballot_box.rs +++ b/core/src/ballot_box.rs @@ -299,6 +299,10 @@ impl BallotBox { self.slot_consensus_reached() > 0 || self.winning_ballot.is_valid() } + pub fn tie_breaker_set(&self) -> bool { + self.slot_consensus_reached() == 0 && self.winning_ballot.is_valid() + } + pub fn get_winning_ballot(&self) -> Result { if self.winning_ballot.is_valid() { Ok(self.winning_ballot) @@ -351,7 +355,7 @@ impl BallotBox { current_slot: u64, valid_slots_after_consensus: u64, ) -> Result<(), TipRouterError> { - if !self.is_voting_valid(current_slot, valid_slots_after_consensus) { + if !self.is_voting_valid(current_slot, valid_slots_after_consensus)? { return Err(TipRouterError::VotingNotValid); } @@ -442,7 +446,12 @@ impl BallotBox { } // Check if voting is stalled and setting the tie breaker is eligible - if current_epoch < self.epoch() + epochs_before_stall { + if current_epoch + < self + .epoch() + .checked_add(epochs_before_stall) + .ok_or(TipRouterError::ArithmeticOverflow)? + { return Err(TipRouterError::VotingNotFinalized); } @@ -461,9 +470,21 @@ impl BallotBox { self.ballot_tallies.iter().any(|t| t.ballot.eq(ballot)) } - pub fn is_voting_valid(&self, current_slot: u64, valid_slots_after_consensus: u64) -> bool { - !(self.is_consensus_reached() - && current_slot > self.slot_consensus_reached() + valid_slots_after_consensus) + /// Determines if an operator can still cast their vote. + /// Returns true when: + /// Consensus is not reached OR the voting window is still valid, assuming set_tie_breaker was not invoked + pub fn is_voting_valid( + &self, + current_slot: u64, + valid_slots_after_consensus: u64, + ) -> Result { + let vote_window_valid = current_slot + <= self + .slot_consensus_reached() + .checked_add(valid_slots_after_consensus) + .ok_or(TipRouterError::ArithmeticOverflow)?; + + Ok((!self.is_consensus_reached() || vote_window_valid) && !self.tie_breaker_set()) } pub fn verify_merkle_root( diff --git a/meta_merkle_tree/src/error.rs b/meta_merkle_tree/src/error.rs index 62dc6fb..ca72c24 100644 --- a/meta_merkle_tree/src/error.rs +++ b/meta_merkle_tree/src/error.rs @@ -10,4 +10,6 @@ pub enum MerkleTreeError { IoError(#[from] std::io::Error), #[error("Serde Error: {0}")] SerdeError(#[from] serde_json::Error), + #[error("Arithmetic Overflow/Underflow")] + ArithmeticOverflow, } diff --git a/meta_merkle_tree/src/generated_merkle_tree.rs b/meta_merkle_tree/src/generated_merkle_tree.rs index eaf0f39..c08f3ab 100644 --- a/meta_merkle_tree/src/generated_merkle_tree.rs +++ b/meta_merkle_tree/src/generated_merkle_tree.rs @@ -45,7 +45,7 @@ pub struct GeneratedMerkleTree { impl GeneratedMerkleTreeCollection { pub fn new_from_stake_meta_collection( stake_meta_coll: StakeMetaCollection, - ) -> Result { + ) -> Result { let generated_merkle_trees = stake_meta_coll .stake_metas .into_iter() @@ -90,7 +90,7 @@ impl GeneratedMerkleTreeCollection { }) .collect::, MerkleRootGeneratorError>>()?; - Ok(GeneratedMerkleTreeCollection { + Ok(Self { generated_merkle_trees, bank_hash: stake_meta_coll.bank_hash, epoch: stake_meta_coll.epoch, @@ -127,7 +127,7 @@ pub struct TreeNode { impl TreeNode { fn vec_from_stake_meta( stake_meta: &StakeMeta, - ) -> Result>, MerkleRootGeneratorError> { + ) -> Result>, MerkleRootGeneratorError> { if let Some(tip_distribution_meta) = stake_meta.maybe_tip_distribution_meta.as_ref() { let validator_amount = (tip_distribution_meta.total_tips as u128) .checked_mul(tip_distribution_meta.validator_fee_bps as u128) @@ -142,7 +142,7 @@ impl TreeNode { ], &jito_tip_distribution::ID, ); - let mut tree_nodes = vec![TreeNode { + let mut tree_nodes = vec![Self { claimant: stake_meta.validator_vote_account, claim_status_pubkey, claim_status_bump, @@ -176,7 +176,7 @@ impl TreeNode { ], &jito_tip_distribution::ID, ); - Ok(TreeNode { + Ok(Self { claimant: delegation.stake_account_pubkey, claim_status_pubkey, claim_status_bump, @@ -186,7 +186,7 @@ impl TreeNode { proof: None, }) }) - .collect::, MerkleRootGeneratorError>>()?, + .collect::, MerkleRootGeneratorError>>()?, ); Ok(Some(tree_nodes)) @@ -316,14 +316,14 @@ mod pubkey_string_conversion { use serde::{self, Deserialize, Deserializer, Serializer}; use solana_program::pubkey::Pubkey; - pub(crate) fn serialize(pubkey: &Pubkey, serializer: S) -> Result + pub fn serialize(pubkey: &Pubkey, serializer: S) -> Result where S: Serializer, { serializer.serialize_str(&pubkey.to_string()) } - pub(crate) fn deserialize<'de, D>(deserializer: D) -> Result + pub fn deserialize<'de, D>(deserializer: D) -> Result where D: Deserializer<'de>, { diff --git a/meta_merkle_tree/src/merkle_tree.rs b/meta_merkle_tree/src/merkle_tree.rs index 8e2ec5b..c992475 100644 --- a/meta_merkle_tree/src/merkle_tree.rs +++ b/meta_merkle_tree/src/merkle_tree.rs @@ -1,3 +1,4 @@ +#![allow(clippy::arithmetic_side_effects)] // https://github.com/jito-foundation/jito-solana/blob/v1.16.19-jito/merkle-tree/src/merkle_tree.rs use solana_program::hash::{hashv, Hash}; @@ -38,11 +39,11 @@ impl<'a> ProofEntry<'a> { Self(target, left_sibling, right_sibling) } - pub fn get_left_sibling(&self) -> Option<&'a Hash> { + pub const fn get_left_sibling(&self) -> Option<&'a Hash> { self.1 } - pub fn get_right_sibling(&self) -> Option<&'a Hash> { + pub const fn get_right_sibling(&self) -> Option<&'a Hash> { self.2 } } @@ -76,8 +77,8 @@ impl<'a> Proof<'a> { } impl MerkleTree { - #[inline] - fn next_level_len(level_len: usize) -> usize { + #[allow(clippy::integer_division)] + const fn next_level_len(level_len: usize) -> usize { if level_len == 1 { 0 } else { @@ -109,8 +110,8 @@ impl MerkleTree { } pub fn new>(items: &[T], sorted_hashes: bool) -> Self { - let cap = MerkleTree::calculate_vec_capacity(items.len()); - let mut mt = MerkleTree { + let cap = Self::calculate_vec_capacity(items.len()); + let mut mt = Self { leaf_count: items.len(), nodes: Vec::with_capacity(cap), }; @@ -121,7 +122,7 @@ impl MerkleTree { mt.nodes.push(hash); } - let mut level_len = MerkleTree::next_level_len(items.len()); + let mut level_len = Self::next_level_len(items.len()); let mut level_start = items.len(); let mut prev_level_len = items.len(); let mut prev_level_start = 0; @@ -154,7 +155,7 @@ impl MerkleTree { prev_level_start = level_start; prev_level_len = level_len; level_start += level_len; - level_len = MerkleTree::next_level_len(level_len); + level_len = Self::next_level_len(level_len); } mt @@ -196,7 +197,7 @@ impl MerkleTree { node_index /= 2; level_start += level_len; - level_len = MerkleTree::next_level_len(level_len); + level_len = Self::next_level_len(level_len); } Some(path) } diff --git a/meta_merkle_tree/src/meta_merkle_tree.rs b/meta_merkle_tree/src/meta_merkle_tree.rs index ba8b290..28099c3 100644 --- a/meta_merkle_tree/src/meta_merkle_tree.rs +++ b/meta_merkle_tree/src/meta_merkle_tree.rs @@ -52,7 +52,7 @@ impl MetaMerkleTree { tree_node.proof = Some(get_proof(&tree, i)); } - let tree = MetaMerkleTree { + let tree = Self { merkle_root: tree .get_root() .ok_or(MerkleTreeError::MerkleRootError)? @@ -94,7 +94,7 @@ impl MetaMerkleTree { pub fn new_from_file(path: &PathBuf) -> Result { let file = File::open(path)?; let reader = BufReader::new(file); - let tree: MetaMerkleTree = serde_json::from_reader(reader)?; + let tree: Self = serde_json::from_reader(reader)?; Ok(tree) } @@ -118,7 +118,11 @@ impl MetaMerkleTree { fn validate(&self) -> Result<()> { // The Merkle tree can be at most height 32, implying a max node count of 2^32 - 1 - if self.num_nodes > 2u64.pow(32) - 1 { + let max_nodes = 2u64 + .checked_pow(32) + .and_then(|x| x.checked_sub(1)) + .ok_or(MerkleTreeError::ArithmeticOverflow)?; + if self.num_nodes > max_nodes { return Err(MerkleValidationError(format!( "Max num nodes {} is greater than 2^32 - 1", self.num_nodes diff --git a/meta_merkle_tree/src/tree_node.rs b/meta_merkle_tree/src/tree_node.rs index 8d14697..209fc5b 100644 --- a/meta_merkle_tree/src/tree_node.rs +++ b/meta_merkle_tree/src/tree_node.rs @@ -22,7 +22,7 @@ pub struct TreeNode { } impl TreeNode { - pub fn new( + pub const fn new( tip_distribution_account: Pubkey, validator_merkle_root: [u8; 32], max_total_claim: u64, @@ -50,7 +50,7 @@ impl TreeNode { // TODO replace this with the GeneratedMerkleTree from the Operator module once that's created impl From for TreeNode { fn from(generated_merkle_tree: GeneratedMerkleTree) -> Self { - TreeNode { + Self { tip_distribution_account: generated_merkle_tree.tip_distribution_account, validator_merkle_root: generated_merkle_tree.merkle_root.to_bytes(), max_total_claim: generated_merkle_tree.max_total_claim, diff --git a/program/src/set_merkle_root.rs b/program/src/set_merkle_root.rs index ca34ebb..8e5b717 100644 --- a/program/src/set_merkle_root.rs +++ b/program/src/set_merkle_root.rs @@ -29,7 +29,7 @@ pub fn process_set_merkle_root( BallotBox::load(program_id, ncn.key, epoch, ballot_box, false)?; let (tip_distribution_address, _) = derive_tip_distribution_account_address( - &tip_distribution_program_id.key, + tip_distribution_program_id.key, vote_account.key, epoch, );