Skip to content

Commit

Permalink
tests passing
Browse files Browse the repository at this point in the history
  • Loading branch information
coachchucksol committed Dec 6, 2024
1 parent 902da71 commit 7168f9d
Show file tree
Hide file tree
Showing 13 changed files with 79 additions and 115 deletions.
16 changes: 8 additions & 8 deletions clients/js/jito_tip_router/accounts/ballotBox.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export type BallotBox = {
reserved: Array<number>;
operatorsVoted: bigint;
uniqueBallots: bigint;
winningBallot: BallotTally;
winningBallotTally: BallotTally;
operatorVotes: Array<OperatorVote>;
ballotTallies: Array<BallotTally>;
};
Expand All @@ -70,7 +70,7 @@ export type BallotBoxArgs = {
reserved: Array<number>;
operatorsVoted: number | bigint;
uniqueBallots: number | bigint;
winningBallot: BallotTallyArgs;
winningBallotTally: BallotTallyArgs;
operatorVotes: Array<OperatorVoteArgs>;
ballotTallies: Array<BallotTallyArgs>;
};
Expand All @@ -86,9 +86,9 @@ export function getBallotBoxEncoder(): Encoder<BallotBoxArgs> {
['reserved', getArrayEncoder(getU8Encoder(), { size: 128 })],
['operatorsVoted', getU64Encoder()],
['uniqueBallots', getU64Encoder()],
['winningBallot', getBallotTallyEncoder()],
['operatorVotes', getArrayEncoder(getOperatorVoteEncoder(), { size: 32 })],
['ballotTallies', getArrayEncoder(getBallotTallyEncoder(), { size: 32 })],
['winningBallotTally', getBallotTallyEncoder()],
['operatorVotes', getArrayEncoder(getOperatorVoteEncoder(), { size: 16 })],
['ballotTallies', getArrayEncoder(getBallotTallyEncoder(), { size: 16 })],
]);
}

Expand All @@ -103,9 +103,9 @@ export function getBallotBoxDecoder(): Decoder<BallotBox> {
['reserved', getArrayDecoder(getU8Decoder(), { size: 128 })],
['operatorsVoted', getU64Decoder()],
['uniqueBallots', getU64Decoder()],
['winningBallot', getBallotTallyDecoder()],
['operatorVotes', getArrayDecoder(getOperatorVoteDecoder(), { size: 32 })],
['ballotTallies', getArrayDecoder(getBallotTallyDecoder(), { size: 32 })],
['winningBallotTally', getBallotTallyDecoder()],
['operatorVotes', getArrayDecoder(getOperatorVoteDecoder(), { size: 16 })],
['ballotTallies', getArrayDecoder(getBallotTallyDecoder(), { size: 16 })],
]);
}

Expand Down
9 changes: 0 additions & 9 deletions clients/js/jito_tip_router/types/ballotTally.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@

import {
combineCodec,
fixDecoderSize,
fixEncoderSize,
getBytesDecoder,
getBytesEncoder,
getStructDecoder,
getStructEncoder,
getU16Decoder,
Expand All @@ -21,7 +17,6 @@ import {
type Codec,
type Decoder,
type Encoder,
type ReadonlyUint8Array,
} from '@solana/web3.js';
import {
getBallotDecoder,
Expand All @@ -39,15 +34,13 @@ export type BallotTally = {
ballot: Ballot;
stakeWeights: StakeWeights;
tally: bigint;
reserved: ReadonlyUint8Array;
};

export type BallotTallyArgs = {
index: number;
ballot: BallotArgs;
stakeWeights: StakeWeightsArgs;
tally: number | bigint;
reserved: ReadonlyUint8Array;
};

export function getBallotTallyEncoder(): Encoder<BallotTallyArgs> {
Expand All @@ -56,7 +49,6 @@ export function getBallotTallyEncoder(): Encoder<BallotTallyArgs> {
['ballot', getBallotEncoder()],
['stakeWeights', getStakeWeightsEncoder()],
['tally', getU64Encoder()],
['reserved', fixEncoderSize(getBytesEncoder(), 64)],
]);
}

Expand All @@ -66,7 +58,6 @@ export function getBallotTallyDecoder(): Decoder<BallotTally> {
['ballot', getBallotDecoder()],
['stakeWeights', getStakeWeightsDecoder()],
['tally', getU64Decoder()],
['reserved', fixDecoderSize(getBytesDecoder(), 64)],
]);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,9 @@ pub struct BallotBox {
pub reserved: [u8; 128],
pub operators_voted: u64,
pub unique_ballots: u64,
pub winning_ballot: BallotTally,
pub operator_votes: [OperatorVote; 32],
pub ballot_tallies: [BallotTally; 32],
pub winning_ballot_tally: BallotTally,
pub operator_votes: [OperatorVote; 16],
pub ballot_tallies: [BallotTally; 16],
}

impl BallotBox {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,4 @@ pub struct BallotTally {
pub ballot: Ballot,
pub stake_weights: StakeWeights,
pub tally: u64,
#[cfg_attr(feature = "serde", serde(with = "serde_with::As::<serde_with::Bytes>"))]
pub reserved: [u8; 64],
}
92 changes: 55 additions & 37 deletions core/src/ballot_box.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ pub struct BallotTally {
ballot: Ballot,
stake_weights: StakeWeights,
tally: PodU64,
reserved: [u8; 64],
// reserved: [u8; 64],
}

impl Default for BallotTally {
Expand All @@ -69,7 +69,7 @@ impl Default for BallotTally {
ballot: Ballot::default(),
stake_weights: StakeWeights::default(),
tally: PodU64::from(0),
reserved: [0; 64],
// reserved: [0; 64],
}
}
}
Expand All @@ -81,7 +81,7 @@ impl BallotTally {
ballot,
stake_weights: *stake_weights,
tally: PodU64::from(1),
reserved: [0; 64],
// reserved: [0; 64],
}
}

Expand All @@ -105,6 +105,10 @@ impl BallotTally {
self.index() == u16::MAX
}

pub fn is_valid(&self) -> bool {
!self.is_empty()
}

pub fn increment_tally(&mut self, stake_weights: &StakeWeights) -> Result<(), TipRouterError> {
self.stake_weights.increment(stake_weights)?;
self.tally = PodU64::from(
Expand Down Expand Up @@ -194,11 +198,11 @@ pub struct BallotBox {
operators_voted: PodU64,
unique_ballots: PodU64,

winning_ballot: BallotTally,
winning_ballot_tally: BallotTally,

//TODO fix 32 -> MAX_OPERATORS
operator_votes: [OperatorVote; 32],
ballot_tallies: [BallotTally; 32],
operator_votes: [OperatorVote; 16],
ballot_tallies: [BallotTally; 16],
}

impl Discriminator for BallotBox {
Expand All @@ -215,10 +219,10 @@ impl BallotBox {
slot_consensus_reached: PodU64::from(DEFAULT_CONSENSUS_REACHED_SLOT),
operators_voted: PodU64::from(0),
unique_ballots: PodU64::from(0),
winning_ballot: BallotTally::default(),
winning_ballot_tally: BallotTally::default(),
//TODO fix 32 -> MAX_OPERATORS
operator_votes: [OperatorVote::default(); 32],
ballot_tallies: [BallotTally::default(); 32],
operator_votes: [OperatorVote::default(); 16],
ballot_tallies: [BallotTally::default(); 16],
reserved: [0; 128],
}
}
Expand Down Expand Up @@ -299,28 +303,38 @@ impl BallotBox {
self.operators_voted.into()
}

pub fn has_ballot(&self, ballot: &Ballot) -> bool {
self.ballot_tallies.iter().any(|t| t.ballot.eq(ballot))
}

pub fn is_consensus_reached(&self) -> bool {
self.slot_consensus_reached() > 0
self.slot_consensus_reached() != DEFAULT_CONSENSUS_REACHED_SLOT
|| self.winning_ballot_tally.is_valid()
}

pub fn get_winning_ballot(&self) -> Result<&BallotTally, TipRouterError> {
if self.winning_ballot.is_empty() {
pub fn tie_breaker_set(&self) -> bool {
self.slot_consensus_reached() == DEFAULT_CONSENSUS_REACHED_SLOT
&& self.winning_ballot_tally.is_valid()
}

pub fn get_winning_ballot_tally(&self) -> Result<&BallotTally, TipRouterError> {
if self.winning_ballot_tally.is_empty() {
Err(TipRouterError::ConsensusNotReached)
} else {
Ok(&self.winning_ballot)
Ok(&self.winning_ballot_tally)
}
}

pub fn has_winning_ballot(&self) -> bool {
!self.winning_ballot.is_empty()
!self.winning_ballot_tally.is_empty()
}

pub const fn operator_votes(&self) -> &[OperatorVote; 32] {
pub const fn operator_votes(&self) -> &[OperatorVote; 16] {
&self.operator_votes
}

pub fn set_winning_ballot(&mut self, ballot: BallotTally) {
self.winning_ballot = ballot;
pub fn set_winning_ballot_tally(&mut self, ballot: BallotTally) {
self.winning_ballot_tally = ballot;
}

fn increment_or_create_ballot_tally(
Expand Down Expand Up @@ -432,10 +446,10 @@ impl BallotBox {
let consensus_reached =
ballot_percentage_of_total.greater_than_or_equal(&target_precise_percentage);

if consensus_reached && self.winning_ballot.is_empty() {
if consensus_reached && self.winning_ballot_tally.is_empty() {
self.slot_consensus_reached = PodU64::from(current_slot);

self.set_winning_ballot(*max_tally);
self.set_winning_ballot_tally(*max_tally);
}

Ok(())
Expand Down Expand Up @@ -480,19 +494,10 @@ impl BallotBox {
// return Err(TipRouterError::TieBreakerNotInPriorVotes);
// }

self.slot_consensus_reached = PodU64::from(0);
self.set_winning_ballot(*finalized_ballot_tally);
self.set_winning_ballot_tally(*finalized_ballot_tally);
Ok(())
}

pub fn has_ballot(&self, ballot: &Ballot) -> bool {
self.ballot_tallies.iter().any(|t| t.ballot.eq(ballot))
}

pub fn tie_breaker_set(&self) -> bool {
self.slot_consensus_reached() == 0
}

/// 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
Expand Down Expand Up @@ -537,7 +542,7 @@ impl BallotBox {

if !meta_merkle_tree::verify::verify(
proof,
self.winning_ballot.ballot.root(),
self.winning_ballot_tally.ballot.root(),
node_hash.to_bytes(),
) {
return Err(TipRouterError::InvalidMerkleProof);
Expand Down Expand Up @@ -635,7 +640,7 @@ mod tests {
);

// Test error on changing vote after consensus
ballot_box.set_winning_ballot(*new_tally);
ballot_box.set_winning_ballot_tally(*new_tally);
ballot_box.slot_consensus_reached = PodU64::from(new_slot);
let result = ballot_box.cast_vote(
operator,
Expand Down Expand Up @@ -704,7 +709,7 @@ mod tests {
assert_eq!(ballot_box.ballot_tallies[1].ballot(), ballot2);

// Test error when ballot tallies are full
for i in 3..=32 {
for i in 3..=16 {
let ballot = Ballot::new([i as u8; 32]);
ballot_box
.increment_or_create_ballot_tally(&ballot, &stake_weights)
Expand Down Expand Up @@ -740,7 +745,7 @@ mod tests {
DEFAULT_CONSENSUS_REACHED_SLOT
);
assert!(matches!(
ballot_box.get_winning_ballot(),
ballot_box.get_winning_ballot_tally(),
Err(TipRouterError::ConsensusNotReached)
));

Expand All @@ -753,7 +758,10 @@ mod tests {
.unwrap();
assert!(ballot_box.is_consensus_reached());
assert_eq!(ballot_box.slot_consensus_reached(), current_slot);
assert_eq!(ballot_box.get_winning_ballot().unwrap().ballot(), ballot);
assert_eq!(
ballot_box.get_winning_ballot_tally().unwrap().ballot(),
ballot
);

// Consensus remains after additional votes
let ballot2 = Ballot::new([2; 32]);
Expand All @@ -765,7 +773,10 @@ mod tests {
.unwrap();
assert!(ballot_box.is_consensus_reached());
assert_eq!(ballot_box.slot_consensus_reached(), current_slot);
assert_eq!(ballot_box.get_winning_ballot().unwrap().ballot(), ballot);
assert_eq!(
ballot_box.get_winning_ballot_tally().unwrap().ballot(),
ballot
);

// Test with multiple competing ballots
let mut ballot_box = BallotBox::new(ncn, epoch, 0, current_slot);
Expand Down Expand Up @@ -796,7 +807,10 @@ mod tests {
.tally_votes(total_stake_weight, current_slot)
.unwrap();
assert!(ballot_box.is_consensus_reached());
assert_eq!(ballot_box.get_winning_ballot().unwrap().ballot(), ballot3);
assert_eq!(
ballot_box.get_winning_ballot_tally().unwrap().ballot(),
ballot3
);
}

#[test]
Expand All @@ -822,6 +836,7 @@ mod tests {
// Test setting tie breaker before voting is stalled
let current_epoch = epoch + 1;
let epochs_before_stall = 3;

assert_eq!(
ballot_box.set_tie_breaker_ballot(ballot1.root(), current_epoch, epochs_before_stall),
Err(TipRouterError::VotingNotFinalized)
Expand All @@ -833,7 +848,10 @@ mod tests {
.set_tie_breaker_ballot(ballot1.root(), current_epoch, epochs_before_stall)
.unwrap();
assert!(ballot_box.is_consensus_reached());
assert_eq!(ballot_box.get_winning_ballot().unwrap().ballot(), ballot1);
assert_eq!(
ballot_box.get_winning_ballot_tally().unwrap().ballot(),
ballot1
);

// Test setting tie breaker with invalid merkle root
let mut ballot_box = BallotBox::new(ncn, epoch, 0, current_slot);
Expand Down
2 changes: 1 addition & 1 deletion core/src/base_reward_router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ impl BaseRewardRouter {
&mut self,
ballot_box: &BallotBox,
) -> Result<(), TipRouterError> {
let winning_ballot = ballot_box.get_winning_ballot()?;
let winning_ballot = ballot_box.get_winning_ballot_tally()?;
let winning_stake_weight = winning_ballot.stake_weights();

for votes in ballot_box.operator_votes().iter() {
Expand Down
Loading

0 comments on commit 7168f9d

Please sign in to comment.