Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: No unwraps No. 2 #135

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions clients/js/restaking_client/errors/jitoRestaking.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ import {
} from '@solana/web3.js';
import { JITO_RESTAKING_PROGRAM_ADDRESS } from '../programs';

/** JsmCoreArithmeticOverflow: JsmCoreArithmeticOverflow */
export const JITO_RESTAKING_ERROR__JSM_CORE_ARITHMETIC_OVERFLOW = 0x0; // 0
/** JsmCoreArithmeticUnderflow: JsmCoreArithmeticUnderflow */
export const JITO_RESTAKING_ERROR__JSM_CORE_ARITHMETIC_UNDERFLOW = 0x1; // 1
/** JsmCoreDivisionByZero: JsmCoreDivisionByZero */
export const JITO_RESTAKING_ERROR__JSM_CORE_DIVISION_BY_ZERO = 0x2; // 2
/** NcnOperatorAdminInvalid: NcnOperatorAdminInvalid */
export const JITO_RESTAKING_ERROR__NCN_OPERATOR_ADMIN_INVALID = 0x3e8; // 1000
/** NcnCooldownOperatorFailed: NcnCooldownOperatorFailed */
Expand Down Expand Up @@ -76,6 +82,9 @@ export type JitoRestakingError =
| typeof JITO_RESTAKING_ERROR__ARITHMETIC_UNDERFLOW
| typeof JITO_RESTAKING_ERROR__DIVISION_BY_ZERO
| typeof JITO_RESTAKING_ERROR__INVALID_EPOCH_LENGTH
| typeof JITO_RESTAKING_ERROR__JSM_CORE_ARITHMETIC_OVERFLOW
| typeof JITO_RESTAKING_ERROR__JSM_CORE_ARITHMETIC_UNDERFLOW
| typeof JITO_RESTAKING_ERROR__JSM_CORE_DIVISION_BY_ZERO
| typeof JITO_RESTAKING_ERROR__NCN_ADMIN_INVALID
| typeof JITO_RESTAKING_ERROR__NCN_COOLDOWN_OPERATOR_FAILED
| typeof JITO_RESTAKING_ERROR__NCN_DELEGATE_ADMIN_INVALID
Expand Down Expand Up @@ -108,6 +117,9 @@ if (process.env.NODE_ENV !== 'production') {
[JITO_RESTAKING_ERROR__ARITHMETIC_UNDERFLOW]: `ArithmeticUnderflow`,
[JITO_RESTAKING_ERROR__DIVISION_BY_ZERO]: `DivisionByZero`,
[JITO_RESTAKING_ERROR__INVALID_EPOCH_LENGTH]: `InvalidEpochLength`,
[JITO_RESTAKING_ERROR__JSM_CORE_ARITHMETIC_OVERFLOW]: `JsmCoreArithmeticOverflow`,
[JITO_RESTAKING_ERROR__JSM_CORE_ARITHMETIC_UNDERFLOW]: `JsmCoreArithmeticUnderflow`,
[JITO_RESTAKING_ERROR__JSM_CORE_DIVISION_BY_ZERO]: `JsmCoreDivisionByZero`,
[JITO_RESTAKING_ERROR__NCN_ADMIN_INVALID]: `NcnAdminInvalid`,
[JITO_RESTAKING_ERROR__NCN_COOLDOWN_OPERATOR_FAILED]: `NcnCooldownOperatorFailed`,
[JITO_RESTAKING_ERROR__NCN_DELEGATE_ADMIN_INVALID]: `NcnDelegateAdminInvalid`,
Expand Down
12 changes: 12 additions & 0 deletions clients/js/vault_client/errors/jitoVault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ import {
} from '@solana/web3.js';
import { JITO_VAULT_PROGRAM_ADDRESS } from '../programs';

/** JsmCoreArithmeticOverflow: JsmCoreArithmeticOverflow */
export const JITO_VAULT_ERROR__JSM_CORE_ARITHMETIC_OVERFLOW = 0x0; // 0
/** JsmCoreArithmeticUnderflow: JsmCoreArithmeticUnderflow */
export const JITO_VAULT_ERROR__JSM_CORE_ARITHMETIC_UNDERFLOW = 0x1; // 1
/** JsmCoreDivisionByZero: JsmCoreDivisionByZero */
export const JITO_VAULT_ERROR__JSM_CORE_DIVISION_BY_ZERO = 0x2; // 2
/** VaultSlashUnderflow: VaultSlashUnderflow */
export const JITO_VAULT_ERROR__VAULT_SLASH_UNDERFLOW = 0x3e8; // 1000
/** VaultInsufficientFunds: VaultInsufficientFunds */
Expand Down Expand Up @@ -136,6 +142,9 @@ export type JitoVaultError =
| typeof JITO_VAULT_ERROR__INVALID_DEPOSITOR
| typeof JITO_VAULT_ERROR__INVALID_DEPOSIT_TOKEN_ACCOUNT
| typeof JITO_VAULT_ERROR__INVALID_EPOCH_LENGTH
| typeof JITO_VAULT_ERROR__JSM_CORE_ARITHMETIC_OVERFLOW
| typeof JITO_VAULT_ERROR__JSM_CORE_ARITHMETIC_UNDERFLOW
| typeof JITO_VAULT_ERROR__JSM_CORE_DIVISION_BY_ZERO
| typeof JITO_VAULT_ERROR__NCN_OPERATOR_STATE_UNSLASHABLE
| typeof JITO_VAULT_ERROR__NCN_OVERFLOW
| typeof JITO_VAULT_ERROR__NCN_VAULT_SLASHER_TICKET_UNSLASHABLE
Expand Down Expand Up @@ -197,6 +206,9 @@ if (process.env.NODE_ENV !== 'production') {
[JITO_VAULT_ERROR__INVALID_DEPOSITOR]: `InvalidDepositor`,
[JITO_VAULT_ERROR__INVALID_DEPOSIT_TOKEN_ACCOUNT]: `InvalidDepositTokenAccount`,
[JITO_VAULT_ERROR__INVALID_EPOCH_LENGTH]: `InvalidEpochLength`,
[JITO_VAULT_ERROR__JSM_CORE_ARITHMETIC_OVERFLOW]: `JsmCoreArithmeticOverflow`,
[JITO_VAULT_ERROR__JSM_CORE_ARITHMETIC_UNDERFLOW]: `JsmCoreArithmeticUnderflow`,
[JITO_VAULT_ERROR__JSM_CORE_DIVISION_BY_ZERO]: `JsmCoreDivisionByZero`,
[JITO_VAULT_ERROR__NCN_OPERATOR_STATE_UNSLASHABLE]: `NcnOperatorStateUnslashable`,
[JITO_VAULT_ERROR__NCN_OVERFLOW]: `NcnOverflow`,
[JITO_VAULT_ERROR__NCN_VAULT_SLASHER_TICKET_UNSLASHABLE]: `NcnVaultSlasherTicketUnslashable`,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ use thiserror::Error;

#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
pub enum JitoRestakingError {
/// 0 - JsmCoreArithmeticOverflow
#[error("JsmCoreArithmeticOverflow")]
JsmCoreArithmeticOverflow = 0x0,
/// 1 - JsmCoreArithmeticUnderflow
#[error("JsmCoreArithmeticUnderflow")]
JsmCoreArithmeticUnderflow = 0x1,
/// 2 - JsmCoreDivisionByZero
#[error("JsmCoreDivisionByZero")]
JsmCoreDivisionByZero = 0x2,
/// 1000 - NcnOperatorAdminInvalid
#[error("NcnOperatorAdminInvalid")]
NcnOperatorAdminInvalid = 0x3E8,
Expand Down
9 changes: 9 additions & 0 deletions clients/rust/vault_client/src/generated/errors/jito_vault.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@ use thiserror::Error;

#[derive(Clone, Debug, Eq, Error, FromPrimitive, PartialEq)]
pub enum JitoVaultError {
/// 0 - JsmCoreArithmeticOverflow
#[error("JsmCoreArithmeticOverflow")]
JsmCoreArithmeticOverflow = 0x0,
/// 1 - JsmCoreArithmeticUnderflow
#[error("JsmCoreArithmeticUnderflow")]
JsmCoreArithmeticUnderflow = 0x1,
/// 2 - JsmCoreDivisionByZero
#[error("JsmCoreDivisionByZero")]
JsmCoreDivisionByZero = 0x2,
/// 1000 - VaultSlashUnderflow
#[error("VaultSlashUnderflow")]
VaultSlashUnderflow = 0x3E8,
Expand Down
36 changes: 36 additions & 0 deletions core/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use solana_program::{decode_error::DecodeError, program_error::ProgramError};
use thiserror::Error;

#[derive(Debug, Error, PartialEq, Eq)]
pub enum JsmCoreError {
#[error("JsmCoreArithmeticOverflow")]
JsmCoreArithmeticOverflow,
#[error("JsmCoreArithmeticUnderflow")]
JsmCoreArithmeticUnderflow,
#[error("JsmCoreDivisionByZero")]
JsmCoreDivisionByZero,
}

impl<T> DecodeError<T> for JsmCoreError {
fn type_of() -> &'static str {
"jito::jsm-core"
}
}

impl From<JsmCoreError> for ProgramError {
fn from(e: JsmCoreError) -> Self {
Self::Custom(e as u32)
}
}

impl From<JsmCoreError> for u64 {
fn from(e: JsmCoreError) -> Self {
e as Self
}
}

impl From<JsmCoreError> for u32 {
fn from(e: JsmCoreError) -> Self {
e as Self
}
}
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ use solana_program::{
system_instruction,
};

pub mod error;
pub mod loader;
pub mod slot_toggle;

Expand Down
112 changes: 71 additions & 41 deletions core/src/slot_toggle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ use bytemuck::{Pod, Zeroable};
use jito_bytemuck::types::PodU64;
use shank::ShankType;

use crate::error::JsmCoreError;

/// SlotToggle is a state tracker that allows for activation and deactivation of certain features
/// based on slot time.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Pod, Zeroable, ShankType)]
Expand Down Expand Up @@ -64,19 +66,21 @@ impl SlotToggle {
///
/// # Returns
/// * `bool` - Whether the feature was successfully activated
pub fn activate(&mut self, slot: u64, epoch_length: u64) -> bool {
match self.state(slot, epoch_length) {
pub fn activate(&mut self, slot: u64, epoch_length: u64) -> Result<bool, JsmCoreError> {
match self.state(slot, epoch_length)? {
SlotToggleState::Inactive => {
if self.slot_added() == slot {
// this should only be possible if the feature is being activated for the first time
// and the slot is the same as the slot it was created at
false
Ok(false)
} else {
self.slot_added = PodU64::from(slot);
true
Ok(true)
}
}
_ => false,
SlotToggleState::WarmUp | SlotToggleState::Active | SlotToggleState::Cooldown => {
Ok(false)
}
}
}

Expand All @@ -90,27 +94,36 @@ impl SlotToggle {
///
/// # Returns
/// * `bool` - Whether the feature was successfully deactivated
pub fn deactivate(&mut self, slot: u64, epoch_length: u64) -> bool {
match self.state(slot, epoch_length) {
pub fn deactivate(&mut self, slot: u64, epoch_length: u64) -> Result<bool, JsmCoreError> {
match self.state(slot, epoch_length)? {
SlotToggleState::Active => {
self.slot_removed = PodU64::from(slot);
true
Ok(true)
}
SlotToggleState::Inactive | SlotToggleState::WarmUp | SlotToggleState::Cooldown => {
Ok(false)
}
_ => false,
}
}

/// Check if the feature is active or in cooldown state at the given slot.
pub fn is_active_or_cooldown(&self, slot: u64, epoch_length: u64) -> bool {
matches!(
self.state(slot, epoch_length),
pub fn is_active_or_cooldown(
&self,
slot: u64,
epoch_length: u64,
) -> Result<bool, JsmCoreError> {
Ok(matches!(
self.state(slot, epoch_length)?,
SlotToggleState::Active | SlotToggleState::Cooldown
)
))
}

/// Check if the feature is active at the given slot.
pub fn is_active(&self, slot: u64, epoch_length: u64) -> bool {
matches!(self.state(slot, epoch_length), SlotToggleState::Active)
pub fn is_active(&self, slot: u64, epoch_length: u64) -> Result<bool, JsmCoreError> {
Ok(matches!(
self.state(slot, epoch_length)?,
SlotToggleState::Active
))
}

/// Get the state of the feature at the given slot.
Expand All @@ -122,28 +135,42 @@ impl SlotToggle {
///
/// # Returns
/// * `SlotToggleState` - The state of the feature at the given slot
pub fn state(&self, slot: u64, epoch_length: u64) -> SlotToggleState {
let current_epoch = slot.checked_div(epoch_length).unwrap();
pub fn state(&self, slot: u64, epoch_length: u64) -> Result<SlotToggleState, JsmCoreError> {
let current_epoch = slot
.checked_div(epoch_length)
.ok_or(JsmCoreError::JsmCoreDivisionByZero)?;

let slot_added: u64 = self.slot_added.into();
let slot_removed: u64 = self.slot_removed.into();

match slot_added.cmp(&slot_removed) {
Ordering::Equal => SlotToggleState::Inactive,
Ordering::Equal => Ok(SlotToggleState::Inactive),
Ordering::Less => {
let slot_removed_epoch = slot_removed.checked_div(epoch_length).unwrap();
if current_epoch > slot_removed_epoch.checked_add(1).unwrap() {
SlotToggleState::Inactive
let slot_removed_epoch = slot_removed
.checked_div(epoch_length)
.ok_or(JsmCoreError::JsmCoreDivisionByZero)?;
if current_epoch
> slot_removed_epoch
.checked_add(1)
.ok_or(JsmCoreError::JsmCoreArithmeticOverflow)?
{
Ok(SlotToggleState::Inactive)
} else {
SlotToggleState::Cooldown
Ok(SlotToggleState::Cooldown)
}
}
Ordering::Greater => {
let slot_added_epoch = slot_added.checked_div(epoch_length).unwrap();
if current_epoch > slot_added_epoch.checked_add(1).unwrap() {
SlotToggleState::Active
let slot_added_epoch = slot_added
.checked_div(epoch_length)
.ok_or(JsmCoreError::JsmCoreDivisionByZero)?;
if current_epoch
> slot_added_epoch
.checked_add(1)
.ok_or(JsmCoreError::JsmCoreArithmeticOverflow)?
{
Ok(SlotToggleState::Active)
} else {
SlotToggleState::WarmUp
Ok(SlotToggleState::WarmUp)
}
}
}
Expand All @@ -169,11 +196,14 @@ mod tests {
fn test_slot_zero() {
let epoch_length = 150;
let toggle = SlotToggle::new(0);
assert_eq!(toggle.state(0, epoch_length), SlotToggleState::Inactive);
assert_eq!(toggle.state(10, epoch_length), SlotToggleState::Inactive);
assert_eq!(toggle.state(0, epoch_length), Ok(SlotToggleState::Inactive));
assert_eq!(
toggle.state(10, epoch_length),
Ok(SlotToggleState::Inactive)
);
assert_eq!(
toggle.state(epoch_length + 1, epoch_length),
SlotToggleState::Inactive
Ok(SlotToggleState::Inactive)
);
}

Expand All @@ -185,7 +215,7 @@ mod tests {
let toggle = SlotToggle::new(creation_slot);
assert_eq!(toggle.slot_added(), creation_slot);
assert_eq!(toggle.slot_removed(), creation_slot);
assert!(toggle.state(creation_slot, epoch_length) == SlotToggleState::Inactive);
assert!(toggle.state(creation_slot, epoch_length) == Ok(SlotToggleState::Inactive));
}

#[test]
Expand All @@ -196,8 +226,8 @@ mod tests {
let mut toggle = SlotToggle::new(creation_slot);

// can't transition to activate the same slot it was created at
assert!(!toggle.activate(creation_slot, epoch_length));
assert!(!toggle.deactivate(creation_slot, epoch_length));
assert!(!toggle.activate(creation_slot, epoch_length).unwrap());
assert!(!toggle.deactivate(creation_slot, epoch_length).unwrap());
}

#[test]
Expand All @@ -211,48 +241,48 @@ mod tests {
// Assert inactive
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::Inactive
Ok(SlotToggleState::Inactive)
);

// Transition to warming up
current_slot += 1;
assert!(toggle.activate(current_slot, epoch_length));
assert!(toggle.activate(current_slot, epoch_length).unwrap());
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::WarmUp
Ok(SlotToggleState::WarmUp)
);

// Assert warming up
current_slot += epoch_length;
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::WarmUp
Ok(SlotToggleState::WarmUp)
);

// Assert active
current_slot += epoch_length;
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::Active
Ok(SlotToggleState::Active)
);

// Assert Deactivate
assert!(toggle.deactivate(current_slot, epoch_length));
assert!(toggle.deactivate(current_slot, epoch_length).unwrap());
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::Cooldown
Ok(SlotToggleState::Cooldown)
);

current_slot += epoch_length;
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::Cooldown
Ok(SlotToggleState::Cooldown)
);

current_slot += epoch_length;
assert_eq!(
toggle.state(current_slot, epoch_length),
SlotToggleState::Inactive
Ok(SlotToggleState::Inactive)
);
}
}
15 changes: 15 additions & 0 deletions idl/jito_restaking.json
Original file line number Diff line number Diff line change
Expand Up @@ -1349,6 +1349,21 @@
}
],
"errors": [
{
"code": 0,
"name": "JsmCoreArithmeticOverflow",
"msg": "JsmCoreArithmeticOverflow"
},
{
"code": 1,
"name": "JsmCoreArithmeticUnderflow",
"msg": "JsmCoreArithmeticUnderflow"
},
{
"code": 2,
"name": "JsmCoreDivisionByZero",
"msg": "JsmCoreDivisionByZero"
},
{
"code": 1000,
"name": "NcnOperatorAdminInvalid",
Expand Down
Loading