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
75 changes: 33 additions & 42 deletions program/rust/src/c_oracle_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,49 +57,46 @@ impl PythAccount for PriceAccount {
#[repr(C)]
#[derive(Copy, Clone, Pod, Zeroable)]
pub struct PriceAccount {
pub magic_: u32,
pub ver_: u32,
pub type_: u32,
pub size_: u32,
pub header: AccountHeader,
/// Type of the price account
pub ptype_: u32,
pub price_type: u32,
/// Exponent for the published prices
pub expo_: i32,
pub exponent: i32,
/// Current number of authorized publishers
pub num_: u32,
pub num_: u32,
/// Number of valid quotes for the last aggregation
pub num_qt_: u32,
pub num_qt_: u32,
/// Last slot with a succesful aggregation (status : TRADING)
pub last_slot_: u64,
pub last_slot_: u64,
/// Second to last slot where aggregation was attempted
pub valid_slot_: u64,
pub valid_slot_: u64,
/// Ema for price
pub twap_: PriceEma,
pub twap_: PriceEma,
/// Ema for confidence
pub twac_: PriceEma,
pub twac_: PriceEma,
/// Last time aggregation was attempted
pub timestamp_: i64,
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,
pub min_pub_: u8,
pub unused_1_: i8,
pub unused_2_: i16,
pub unused_3_: i32,
/// Corresponding product account
pub prod_: CPubkey,
pub product_account: CPubkey,
/// Next price account in the list
pub next_: CPubkey,
pub next_price_account: CPubkey,
/// Second to last slot where aggregation was succesful (i.e. status : TRADING)
pub prev_slot_: u64,
pub prev_slot_: u64,
/// Aggregate price at prev_slot_
pub prev_price_: i64,
pub prev_price_: i64,
/// Confidence interval at prev_slot_
pub prev_conf_: u64,
pub prev_conf_: u64,
/// Timestamp of prev_slot_
pub prev_timestamp_: i64,
pub prev_timestamp_: i64,
/// Last attempted aggregate results
pub agg_: PriceInfo,
pub agg_: PriceInfo,
/// Publishers' price components
pub comp_: [PriceComponent; PC_COMP_SIZE as usize],
pub comp_: [PriceComponent; PC_COMP_SIZE as usize],
}

#[repr(C)]
Expand Down Expand Up @@ -131,33 +128,27 @@ pub struct PriceEma {
#[repr(C)]
#[derive(Copy, Clone, Zeroable, Pod)]
pub struct AccountHeader {
pub magic_: u32,
pub ver_: u32,
pub type_: u32,
pub size_: u32,
pub magic_number: u32,
pub version: u32,
pub account_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,
pub header: AccountHeader,
pub first_price_account: 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],
pub header: AccountHeader,
pub number_of_products: u32,
pub unused_: u32,
pub next_mapping_account: CPubkey,
pub products_list: [CPubkey; PC_MAP_TABLE_SIZE as usize],
}

// Unsafe impl because CPubkey is a union
Expand Down
14 changes: 7 additions & 7 deletions program/rust/src/deserialize.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,9 @@ pub fn load_checked<'a, T: PythAccount>(
{
let account_header = load_account_as::<AccountHeader>(account)?;
pyth_assert(
account_header.magic_ == PC_MAGIC
&& account_header.ver_ == version
&& account_header.type_ == T::ACCOUNT_TYPE,
account_header.magic_number == PC_MAGIC
&& account_header.version == version
&& account_header.account_type == T::ACCOUNT_TYPE,
ProgramError::InvalidArgument,
)?;
}
Expand All @@ -91,10 +91,10 @@ pub fn initialize_pyth_account_checked<'a, T: PythAccount>(

{
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;
account_header.size_ = T::INITIAL_SIZE;
account_header.magic_number = PC_MAGIC;
account_header.version = version;
account_header.account_type = T::ACCOUNT_TYPE;
account_header.size = T::INITIAL_SIZE;
}

load_account_as_mut::<T>(account)
Expand Down
90 changes: 57 additions & 33 deletions program/rust/src/rust_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,12 +208,16 @@ pub fn add_mapping(
let hdr = load::<CommandHeader>(instruction_data)?;
let mut cur_mapping = load_checked::<MappingAccount>(cur_mapping, hdr.version)?;
pyth_assert(
cur_mapping.num_ == PC_MAP_TABLE_SIZE && pubkey_is_zero(&cur_mapping.next_),
cur_mapping.number_of_products == PC_MAP_TABLE_SIZE
&& pubkey_is_zero(&cur_mapping.next_mapping_account),
ProgramError::InvalidArgument,
)?;

initialize_pyth_account_checked::<MappingAccount>(next_mapping, hdr.version)?;
pubkey_assign(&mut cur_mapping.next_, &next_mapping.key.to_bytes());
pubkey_assign(
&mut cur_mapping.next_mapping_account,
&next_mapping.key.to_bytes(),
);

Ok(())
}
Expand Down Expand Up @@ -363,11 +367,20 @@ pub fn add_price(

let mut price_data =
initialize_pyth_account_checked::<PriceAccount>(price_account, cmd_args.header.version)?;
price_data.expo_ = cmd_args.exponent;
price_data.ptype_ = cmd_args.price_type;
pubkey_assign(&mut price_data.prod_, &product_account.key.to_bytes());
pubkey_assign(&mut price_data.next_, bytes_of(&product_data.px_acc_));
pubkey_assign(&mut product_data.px_acc_, &price_account.key.to_bytes());
price_data.exponent = cmd_args.exponent;
price_data.price_type = cmd_args.price_type;
pubkey_assign(
&mut price_data.product_account,
&product_account.key.to_bytes(),
);
pubkey_assign(
&mut price_data.next_price_account,
bytes_of(&product_data.first_price_account),
);
pubkey_assign(
&mut product_data.first_price_account,
&price_account.key.to_bytes(),
);

Ok(())
}
Expand Down Expand Up @@ -398,16 +411,22 @@ pub fn del_price(
let mut product_data = load_checked::<ProductAccount>(product_account, cmd_args.version)?;
let price_data = load_checked::<PriceAccount>(price_account, cmd_args.version)?;
pyth_assert(
pubkey_equal(&product_data.px_acc_, &price_account.key.to_bytes()),
pubkey_equal(
&product_data.first_price_account,
&price_account.key.to_bytes(),
),
ProgramError::InvalidArgument,
)?;

pyth_assert(
pubkey_equal(&price_data.prod_, &product_account.key.to_bytes()),
pubkey_equal(&price_data.product_account, &product_account.key.to_bytes()),
ProgramError::InvalidArgument,
)?;

pubkey_assign(&mut product_data.px_acc_, bytes_of(&price_data.next_));
pubkey_assign(
&mut product_data.first_price_account,
bytes_of(&price_data.next_price_account),
);
}

// Zero out the balance of the price account to delete it.
Expand Down Expand Up @@ -439,11 +458,11 @@ pub fn init_price(

let mut price_data = load_checked::<PriceAccount>(price_account, cmd_args.header.version)?;
pyth_assert(
price_data.ptype_ == cmd_args.price_type,
price_data.price_type == cmd_args.price_type,
ProgramError::InvalidArgument,
)?;

price_data.expo_ = cmd_args.exponent;
price_data.exponent = cmd_args.exponent;

price_data.last_slot_ = 0;
price_data.valid_slot_ = 0;
Expand Down Expand Up @@ -530,7 +549,7 @@ pub fn add_publisher(
bytes_of(&cmd_args.publisher),
);
price_data.num_ += 1;
price_data.size_ =
price_data.header.size =
try_convert::<_, u32>(size_of::<PriceAccount>() - size_of_val(&price_data.comp_))?
+ price_data.num_ * try_convert::<_, u32>(size_of::<PriceComponent>())?;
Ok(())
Expand Down Expand Up @@ -574,7 +593,7 @@ pub fn del_publisher(
0,
size_of::<PriceComponent>(),
);
price_data.size_ =
price_data.header.size =
try_convert::<_, u32>(size_of::<PriceAccount>() - size_of_val(&price_data.comp_))?
+ price_data.num_ * try_convert::<_, u32>(size_of::<PriceComponent>())?;
return Ok(());
Expand Down Expand Up @@ -606,21 +625,22 @@ pub fn add_product(
let mut mapping_data = load_checked::<MappingAccount>(tail_mapping_account, hdr.version)?;
// The mapping account must have free space to add the product account
pyth_assert(
mapping_data.num_ < PC_MAP_TABLE_SIZE,
mapping_data.number_of_products < PC_MAP_TABLE_SIZE,
ProgramError::InvalidArgument,
)?;

initialize_pyth_account_checked::<ProductAccount>(new_product_account, hdr.version)?;

let current_index: usize = try_convert(mapping_data.num_)?;
let current_index: usize = try_convert(mapping_data.number_of_products)?;
pubkey_assign(
&mut mapping_data.prod_[current_index],
&mut mapping_data.products_list[current_index],
bytes_of(&new_product_account.key.to_bytes()),
);
mapping_data.num_ += 1;
mapping_data.size_ =
try_convert::<_, u32>(size_of::<MappingAccount>() - size_of_val(&mapping_data.prod_))?
+ mapping_data.num_ * try_convert::<_, u32>(size_of::<CPubkey>())?;
mapping_data.number_of_products += 1;
mapping_data.header.size = try_convert::<_, u32>(
size_of::<MappingAccount>() - size_of_val(&mapping_data.products_list),
)? + mapping_data.number_of_products
* try_convert::<_, u32>(size_of::<CPubkey>())?;

Ok(())
}
Expand Down Expand Up @@ -680,7 +700,7 @@ pub fn upd_product(
}

let mut product_data = load_checked::<ProductAccount>(product_account, hdr.version)?;
product_data.size_ = try_convert(size_of::<ProductAccount>() + new_data.len())?;
product_data.header.size = try_convert(size_of::<ProductAccount>() + new_data.len())?;

Ok(())
}
Expand Down Expand Up @@ -738,36 +758,40 @@ pub fn del_product(
let product_data = load_checked::<ProductAccount>(product_account, cmd_args.version)?;

// This assertion is just to make the subtractions below simpler
pyth_assert(mapping_data.num_ >= 1, ProgramError::InvalidArgument)?;
pyth_assert(
pubkey_is_zero(&product_data.px_acc_),
mapping_data.number_of_products >= 1,
ProgramError::InvalidArgument,
)?;
pyth_assert(
pubkey_is_zero(&product_data.first_price_account),
ProgramError::InvalidArgument,
)?;

let product_key = product_account.key.to_bytes();
let product_index = mapping_data
.prod_
.products_list
.iter()
.position(|x| pubkey_equal(x, &product_key))
.ok_or(ProgramError::InvalidArgument)?;

let num_after_removal: usize = try_convert(
mapping_data
.num_
.number_of_products
.checked_sub(1)
.ok_or(ProgramError::InvalidArgument)?,
)?;

let last_key_bytes = mapping_data.prod_[num_after_removal];
let last_key_bytes = mapping_data.products_list[num_after_removal];
pubkey_assign(
&mut mapping_data.prod_[product_index],
&mut mapping_data.products_list[product_index],
bytes_of(&last_key_bytes),
);
pubkey_clear(&mut mapping_data.prod_[num_after_removal]);
mapping_data.num_ = try_convert::<_, u32>(num_after_removal)?;
mapping_data.size_ =
try_convert::<_, u32>(size_of::<MappingAccount>() - size_of_val(&mapping_data.prod_))?
+ mapping_data.num_ * try_convert::<_, u32>(size_of::<CPubkey>())?;
pubkey_clear(&mut mapping_data.products_list[num_after_removal]);
mapping_data.number_of_products = try_convert::<_, u32>(num_after_removal)?;
mapping_data.header.size = try_convert::<_, u32>(
size_of::<MappingAccount>() - size_of_val(&mapping_data.products_list),
)? + mapping_data.number_of_products
* try_convert::<_, u32>(size_of::<CPubkey>())?;
}

// Zero out the balance of the price account to delete it.
Expand Down
21 changes: 12 additions & 9 deletions program/rust/src/tests/test_add_mapping.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ fn test_add_mapping() {
{
let mut cur_mapping_data =
load_checked::<MappingAccount>(&cur_mapping, PC_VERSION).unwrap();
cur_mapping_data.num_ = PC_MAP_TABLE_SIZE;
cur_mapping_data.number_of_products = PC_MAP_TABLE_SIZE;
}

assert!(process_instruction(
Expand All @@ -65,12 +65,15 @@ fn test_add_mapping() {
load_checked::<MappingAccount>(&cur_mapping, PC_VERSION).unwrap();

assert!(pubkey_equal(
&cur_mapping_data.next_,
&cur_mapping_data.next_mapping_account,
&next_mapping.key.to_bytes()
));
assert!(pubkey_is_zero(&next_mapping_data.next_));
pubkey_assign(&mut cur_mapping_data.next_, &Pubkey::default().to_bytes());
cur_mapping_data.num_ = 0;
assert!(pubkey_is_zero(&next_mapping_data.next_mapping_account));
pubkey_assign(
&mut cur_mapping_data.next_mapping_account,
&Pubkey::default().to_bytes(),
);
cur_mapping_data.number_of_products = 0;
}

clear_account(&next_mapping).unwrap();
Expand All @@ -91,9 +94,9 @@ fn test_add_mapping() {
{
let mut cur_mapping_data =
load_checked::<MappingAccount>(&cur_mapping, PC_VERSION).unwrap();
assert!(pubkey_is_zero(&cur_mapping_data.next_));
cur_mapping_data.num_ = PC_MAP_TABLE_SIZE;
cur_mapping_data.magic_ = 0;
assert!(pubkey_is_zero(&cur_mapping_data.next_mapping_account));
cur_mapping_data.number_of_products = PC_MAP_TABLE_SIZE;
cur_mapping_data.header.magic_number = 0;
}

assert_eq!(
Expand All @@ -111,7 +114,7 @@ fn test_add_mapping() {

{
let mut cur_mapping_data = load_account_as_mut::<MappingAccount>(&cur_mapping).unwrap();
cur_mapping_data.magic_ = PC_MAGIC;
cur_mapping_data.header.magic_number = PC_MAGIC;
}

assert!(process_instruction(
Expand Down
Loading