Skip to content

Commit

Permalink
weight table complete
Browse files Browse the repository at this point in the history
  • Loading branch information
coachchucksol committed Oct 11, 2024
1 parent db8f6e8 commit 545278c
Show file tree
Hide file tree
Showing 12 changed files with 328 additions and 20 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
/target

.developer
4 changes: 4 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions weight_table_core/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ pub enum WeightTableError {

#[error("Incorrect weight table admin")]
IncorrectWeightTableAdmin = 0x2200,
#[error("Cannnot create future weight tables")]
CannotCreateFutureWeightTables = 0x2201,
}

impl<T> DecodeError<T> for WeightTableError {
Expand Down
81 changes: 67 additions & 14 deletions weight_table_core/src/weight_table.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use bytemuck::{Pod, Zeroable};
use jito_bytemuck::{types::PodU64, AccountDeserialize, Discriminator};
use shank::{ShankAccount, ShankType};
use solana_program::pubkey::Pubkey;
use solana_program::{account_info::AccountInfo, msg, program_error::ProgramError, pubkey::Pubkey};

use crate::{discriminators::WEIGHT_TABLE_DISCRIMINATOR, error::WeightTableError, weight::Weight};

Expand All @@ -16,8 +16,11 @@ pub struct WeightTable {
/// The NCN epoch for which the weight table is valid
pub ncn_epoch: PodU64,

/// Anything non-zero means the table is finalized and cannot be updated.
finalized: u8,
/// Slot weight table was created
slot_created: PodU64,

/// Slot weight table was finalized
slot_finalized: PodU64,

/// Bump seed for the PDA
pub bump: u8,
Expand All @@ -35,14 +38,14 @@ impl Discriminator for WeightTable {

impl WeightTable {
pub const MAX_TABLE_ENTRIES: usize = 32;
pub const NOT_FINALIZED: u8 = 0;
pub const FINALIZED: u8 = 0xFF;
pub const NOT_FINALIZED: u64 = u64::MAX;

pub fn new(ncn: Pubkey, ncn_epoch: u64, bump: u8) -> Self {
pub fn new(ncn: Pubkey, ncn_epoch: u64, slot_created: u64, bump: u8) -> Self {
Self {
ncn,
ncn_epoch: PodU64::from(ncn_epoch),
finalized: Self::NOT_FINALIZED,
slot_created: PodU64::from(slot_created),
slot_finalized: PodU64::from(Self::NOT_FINALIZED),
bump,
reserved: [0; 128],
table: [WeightEntry::default(); Self::MAX_TABLE_ENTRIES],
Expand Down Expand Up @@ -103,12 +106,51 @@ impl WeightTable {
Ok(())
}

pub fn slot_created(&self) -> u64 {
self.slot_created.into()
}

pub fn slot_finalized(&self) -> u64 {
self.slot_finalized.into()
}

pub fn finalized(&self) -> bool {
self.finalized != Self::NOT_FINALIZED
self.slot_finalized != PodU64::from(Self::NOT_FINALIZED)
}

pub fn finalize(&mut self) {
self.finalized = Self::FINALIZED;
pub fn finalize(&mut self, current_slot: u64) {
self.slot_finalized = PodU64::from(current_slot);
}

pub fn load(
program_id: &Pubkey,
weight_table: &AccountInfo,
ncn: &AccountInfo,
ncn_epoch: u64,
expect_writable: bool,
) -> Result<(), ProgramError> {
if weight_table.owner.ne(program_id) {
msg!("Weight table account is not owned by the program");
return Err(ProgramError::InvalidAccountOwner);
}
if weight_table.data_is_empty() {
msg!("Weight table is empty");
return Err(ProgramError::InvalidAccountData);
}
if expect_writable && !weight_table.is_writable {
msg!("Weight table account is not writable");
return Err(ProgramError::InvalidAccountData);
}
if weight_table.data.borrow()[0].ne(&Self::DISCRIMINATOR) {
msg!("Weight table account has an incorrect discriminator");
return Err(ProgramError::InvalidAccountData);
}
let expected_pubkey = Self::find_program_address(program_id, ncn.key, ncn_epoch).0;
if weight_table.key.ne(&expected_pubkey) {
msg!("Weight table incorrect PDA");
return Err(ProgramError::InvalidAccountData);
}
Ok(())
}
}

Expand Down Expand Up @@ -138,15 +180,15 @@ mod tests {
#[test]
fn test_weight_table_new() {
let ncn = Pubkey::new_unique();
let table = WeightTable::new(ncn, 0, 0);
let table = WeightTable::new(ncn, 0, 0, 0);
assert_eq!(table.entry_count(), 0);
}

#[test]
fn test_weight_table_entry_count() {
let ncn = Pubkey::new_unique();

let mut table = WeightTable::new(ncn, 0, 0);
let mut table = WeightTable::new(ncn, 0, 0, 0);
let mint1 = Pubkey::new_unique();
let mint2 = Pubkey::new_unique();

Expand All @@ -165,7 +207,7 @@ mod tests {
fn test_weight_table_find_weight() {
let ncn = Pubkey::new_unique();

let mut table = WeightTable::new(ncn, 0, 0);
let mut table = WeightTable::new(ncn, 0, 0, 0);
let mint1 = Pubkey::new_unique();
let mint2 = Pubkey::new_unique();

Expand All @@ -185,7 +227,7 @@ mod tests {
fn test_weight_table_set_weight() {
let ncn = Pubkey::new_unique();

let mut table = WeightTable::new(ncn, 0, 0);
let mut table = WeightTable::new(ncn, 0, 0, 0);
let mint = Pubkey::new_unique();

// Set initial weight
Expand Down Expand Up @@ -225,4 +267,15 @@ mod tests {
let non_empty_entry = WeightEntry::new(mint, weight);
assert!(!non_empty_entry.is_empty());
}

#[test]
fn test_weight_table_finalize() {
let mut weight_table = WeightTable::new(Pubkey::new_unique(), 0, 0, 0);

assert!(!weight_table.finalized());
assert_eq!(weight_table.slot_finalized(), WeightTable::NOT_FINALIZED);

weight_table.finalize(0);
assert!(weight_table.finalized());
}
}
15 changes: 15 additions & 0 deletions weight_table_program/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,22 @@ license = { workspace = true }
edition = { workspace = true }
readme = { workspace = true }

[features]
no-entrypoint = []
no-idl = []
no-log-ix-name = []
cpi = ["no-entrypoint"]
default = []
mainnet-beta = []
testnet = []
devnet = []
localhost = []

[dependencies]
borsh = { workspace = true }
bytemuck = { workspace = true }
cfg-if = { workspace = true }
const_str_to_pubkey = { workspace = true }
jito-reward-core = { workspace = true }
jito-bytemuck = { workspace = true }
jito-jsm-core = { workspace = true }
Expand All @@ -21,11 +34,13 @@ jito-restaking-sdk = { workspace = true }
jito-restaking-core= { workspace = true }
jito-restaking-program = { workspace = true }
jito-weight-table-core = { workspace = true }
jito-weight-table-sdk = { workspace = true }
shank = { workspace = true }
solana-program = { workspace = true }
spl-associated-token-account = { workspace = true }
spl-token = { workspace = true }
thiserror = { workspace = true }
solana-security-txt = { workspace = true }

[dev-dependencies]
assert_matches = { workspace = true }
1 change: 0 additions & 1 deletion weight_table_program/src/copy_weight_table.rs

This file was deleted.

49 changes: 48 additions & 1 deletion weight_table_program/src/finalize_weight_table.rs
Original file line number Diff line number Diff line change
@@ -1 +1,48 @@
// Permissioned update table
use jito_bytemuck::AccountDeserialize;
use jito_jsm_core::loader::load_signer;
use jito_restaking_core::ncn::Ncn;
use jito_weight_table_core::{error::WeightTableError, weight_table::WeightTable};
use solana_program::{
account_info::AccountInfo, clock::Clock, entrypoint::ProgramResult, msg,
program_error::ProgramError, pubkey::Pubkey, sysvar::Sysvar,
};

/// Initializes a Weight Table
pub fn process_finalize_weight_table(
program_id: &Pubkey,
accounts: &[AccountInfo],
ncn_epoch: u64,
) -> ProgramResult {
let [ncn, weight_table, weight_table_admin, restaking_program_id] = accounts else {
return Err(ProgramError::NotEnoughAccountKeys);
};

Ncn::load(restaking_program_id.key, ncn, false)?;
let ncn_weight_table_admin = {
//TODO switch to weight table admin when that is merged
let ncn_data = ncn.data.borrow();
let ncn = Ncn::try_from_slice_unchecked(&ncn_data)?;
ncn.admin
};

load_signer(weight_table_admin, true)?;
WeightTable::load(program_id, weight_table, ncn, ncn_epoch, true)?;

if restaking_program_id.key.ne(&jito_restaking_program::id()) {
msg!("Incorrect restaking program ID");
return Err(ProgramError::InvalidAccountData);
}

if ncn_weight_table_admin.ne(&weight_table_admin.key) {
msg!("Vault update delegations ticket is not at the correct PDA");
return Err(WeightTableError::IncorrectWeightTableAdmin.into());
}

let mut weight_table_data = weight_table.try_borrow_mut_data()?;
let weight_table_account = WeightTable::try_from_slice_unchecked_mut(&mut weight_table_data)?;

let current_slot = Clock::get()?.slot;
weight_table_account.finalize(current_slot);

Ok(())
}
17 changes: 15 additions & 2 deletions weight_table_program/src/initialize_weight_table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,11 @@ use solana_program::{
};

/// Initializes a Weight Table
/// Can be backfilled for previous epochs
pub fn process_initialize_weight_table(
program_id: &Pubkey,
accounts: &[AccountInfo],
first_slot_of_ncn_epoch: Option<u64>,
) -> ProgramResult {
let [restaking_config, ncn, weight_table, weight_table_admin, restaking_program_id, system_program] =
accounts
Expand Down Expand Up @@ -50,10 +52,20 @@ pub fn process_initialize_weight_table(
}

let current_slot = Clock::get()?.slot;
let ncn_epoch = current_slot
let current_ncn_epoch = current_slot
.checked_div(ncn_epoch_length)
.ok_or(WeightTableError::DenominatorIsZero)?;

let ncn_epoch_slot = first_slot_of_ncn_epoch.unwrap_or(current_slot);
let ncn_epoch = ncn_epoch_slot
.checked_div(ncn_epoch_length)
.ok_or(WeightTableError::DenominatorIsZero)?;

if ncn_epoch > current_ncn_epoch {
msg!("Weight tables can only be initialized for current or past epochs");
return Err(WeightTableError::CannotCreateFutureWeightTables.into());
}

let (weight_table_pubkey, weight_table_bump, mut weight_table_seeds) =
WeightTable::find_program_address(program_id, ncn.key, ncn_epoch);
weight_table_seeds.push(vec![weight_table_bump]);
Expand Down Expand Up @@ -82,7 +94,8 @@ pub fn process_initialize_weight_table(
let mut weight_table_data = weight_table.try_borrow_mut_data()?;
weight_table_data[0] = WeightTable::DISCRIMINATOR;
let weight_table_account = WeightTable::try_from_slice_unchecked_mut(&mut weight_table_data)?;
*weight_table_account = WeightTable::new(*ncn.key, ncn_epoch, weight_table_bump);

*weight_table_account = WeightTable::new(*ncn.key, ncn_epoch, current_slot, weight_table_bump);

Ok(())
}
Loading

0 comments on commit 545278c

Please sign in to comment.