Skip to content
Merged
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
208 changes: 135 additions & 73 deletions program/rust/src/c_oracle_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,94 +34,156 @@ pub trait PythAccount: Pod {
}
}

impl PythAccount for pc_map_table_t {
impl PythAccount for MappingAccount {
const ACCOUNT_TYPE: u32 = PC_ACCTYPE_MAPPING;
/// Equal to the offset of `prod_` in `MappingAccount`, see the trait comment for more detail
const INITIAL_SIZE: u32 = PC_MAP_TABLE_T_PROD_OFFSET as u32;
}

impl PythAccount for pc_prod_t {
impl PythAccount for ProductAccount {
const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRODUCT;
const INITIAL_SIZE: u32 = size_of::<pc_prod_t>() as u32;
const INITIAL_SIZE: u32 = size_of::<ProductAccount>() as u32;
fn minimum_size() -> usize {
PC_PROD_ACC_SIZE as usize
}
}

impl PythAccount for pc_price_t {
impl PythAccount for PriceAccount {
const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE;
/// Equal to the offset of `comp_` in `PriceAccount`, see the trait comment for more detail
const INITIAL_SIZE: u32 = PC_PRICE_T_COMP_OFFSET as u32;
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_acc {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_acc {
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_map_table {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_map_table {
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_prod {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_prod {
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_price {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_price {
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_price_info {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_price_info {
}

#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_ema {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_ema {
}


#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_pub_key_t {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_pub_key_t {
}


#[cfg(target_endian = "little")]
unsafe impl Zeroable for pc_price_comp_t {
}

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_price_comp_t {
}

impl pc_pub_key_t {
pub fn new_unique() -> pc_pub_key_t {
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct PriceAccount {
pub magic_: u32,
pub ver_: u32,
pub type_: u32,
pub size_: u32,
/// Type of the price account
pub ptype_: u32,
/// Exponent for the published prices
pub expo_: i32,
/// Current number of authorized publishers
pub num_: u32,
/// Number of valid quotes for the last aggregation
pub num_qt_: u32,
/// Last slot with a succesful aggregation (status : TRADING)
pub last_slot_: u64,
/// Second to last slot where aggregation was attempted
pub valid_slot_: u64,
/// Ema for price
pub twap_: PriceEma,
/// Ema for confidence
pub twac_: PriceEma,
/// Last time aggregation was attempted
pub timestamp_: i64,
/// Minimum valid publisher quotes for a succesful aggregation
pub min_pub_: u8,
pub unused_1_: i8,
pub unused_2_: i16,
pub unused_3_: i32,
/// Corresponding product account
pub prod_: CPubkey,
/// Next price account in the list
pub next_: CPubkey,
/// Second to last slot where aggregation was succesful (i.e. status : TRADING)
pub prev_slot_: u64,
/// Aggregate price at prev_slot_
pub prev_price_: i64,
/// Confidence interval at prev_slot_
pub prev_conf_: u64,
/// Timestamp of prev_slot_
pub prev_timestamp_: i64,
/// Last attempted aggregate results
pub agg_: PriceInfo,
/// Publishers' price components
pub comp_: [PriceComponent; PC_COMP_SIZE as usize],
}

#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct PriceComponent {
pub pub_: CPubkey,
pub agg_: PriceInfo,
pub latest_: PriceInfo,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
pub struct PriceInfo {
pub price_: i64,
pub conf_: u64,
pub status_: u32,
pub corp_act_status_: u32,
pub pub_slot_: u64,
}

#[repr(C)]
#[derive(Debug, Copy, Clone, Pod, Zeroable)]
pub struct PriceEma {
pub val_: i64,
pub numer_: i64,
pub denom_: i64,
}

#[repr(C)]
#[derive(Copy, Clone, Zeroable, Pod)]
pub struct AccountHeader {
pub magic_: u32,
pub ver_: u32,
pub type_: u32,
pub size_: u32,
}

#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct ProductAccount {
pub magic_: u32,
pub ver_: u32,
pub type_: u32,
pub size_: u32,
pub px_acc_: CPubkey,
}

#[repr(C)]
#[derive(Copy, Clone)]
pub struct MappingAccount {
pub magic_: u32,
pub ver_: u32,
pub type_: u32,
pub size_: u32,
pub num_: u32,
pub unused_: u32,
pub next_: CPubkey,
pub prod_: [CPubkey; PC_MAP_TABLE_SIZE as usize],
}

// Unsafe impl because CPubkey is a union
unsafe impl Pod for CPubkey {
}
unsafe impl Zeroable for CPubkey {
}


// Unsafe impl because product_list is of size 640 and there's no derived trait for this size
unsafe impl Pod for MappingAccount {
}
unsafe impl Zeroable for MappingAccount {
}

#[repr(C)]
#[derive(Copy, Clone)]
pub union CPubkey {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Both fields are currently used in the code. I feel like we can get to a safe derivation if we :

  • Replace CPubkey by the solana sdk Pubkey
  • Update functions to only use k1_ or k8_.
    Let's do it in a future PR.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree with the first suggestion, we should use the solana Pubkey type directly in a future PR. The second suggestion would just keep us using the ad-hoc unsafe functions we should scrap.

pub k1_: [u8; 32usize],
pub k8_: [u64; 4usize],
}

impl CPubkey {
pub fn new_unique() -> CPubkey {
let solana_unique = Pubkey::new_unique();
pc_pub_key_t {
CPubkey {
k1_: solana_unique.to_bytes(),
}
}
Expand Down
6 changes: 3 additions & 3 deletions program/rust/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use bytemuck::{
};

use crate::c_oracle_header::{
pc_acc,
AccountHeader,
PythAccount,
PC_MAGIC,
};
Expand Down Expand Up @@ -71,7 +71,7 @@ pub fn load_checked<'a, T: PythAccount>(
version: u32,
) -> Result<RefMut<'a, T>, ProgramError> {
{
let account_header = load_account_as::<pc_acc>(account)?;
let account_header = load_account_as::<AccountHeader>(account)?;
pyth_assert(
account_header.magic_ == PC_MAGIC
&& account_header.ver_ == version
Expand All @@ -90,7 +90,7 @@ pub fn initialize_pyth_account_checked<'a, T: PythAccount>(
clear_account(account)?;

{
let mut account_header = load_account_as_mut::<pc_acc>(account)?;
let mut account_header = load_account_as_mut::<AccountHeader>(account)?;
account_header.magic_ = PC_MAGIC;
account_header.ver_ = version;
account_header.type_ = T::ACCOUNT_TYPE;
Expand Down
4 changes: 2 additions & 2 deletions program/rust/src/instruction.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::c_oracle_header::{
pc_pub_key_t,
CPubkey,
PC_VERSION,
};
use crate::deserialize::load;
Expand Down Expand Up @@ -122,7 +122,7 @@ pub type InitPriceArgs = AddPriceArgs;
#[derive(Zeroable, Pod, Copy, Clone)]
pub struct AddPublisherArgs {
pub header: CommandHeader,
pub publisher: pc_pub_key_t,
pub publisher: CPubkey,
}

pub type DelPublisherArgs = AddPublisherArgs;
Expand Down
Loading