Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
94b9c82
v1
Aug 1, 2022
85547e9
stuff
Aug 1, 2022
d8bbde2
fix
Aug 1, 2022
17462d2
stuff
Aug 2, 2022
67a3c68
maybe?
Aug 2, 2022
7587c7c
whoops
Aug 2, 2022
be542c3
ok
Aug 2, 2022
b39bcf9
blah
Aug 2, 2022
e8f3aa4
more constants
Aug 2, 2022
b910d46
ok
Aug 2, 2022
3c7c270
blah
Aug 2, 2022
7e9b322
imlement
Aug 2, 2022
c57cae0
maybe
Aug 2, 2022
ab38504
ok
Aug 2, 2022
71e97c7
ok
Aug 2, 2022
04891b0
ok
Aug 2, 2022
71c9888
ok
Aug 2, 2022
9c1ca66
ok
Aug 2, 2022
3e94f78
ok
Aug 2, 2022
d578aa6
ok
Aug 2, 2022
36fef92
ok
Aug 2, 2022
1abc3a2
ok
Aug 2, 2022
bd81625
ok
Aug 2, 2022
f5f3d80
ok
Aug 2, 2022
d1f5f16
ok
Aug 2, 2022
44a5302
ok
Aug 2, 2022
3ad90a7
ok
Aug 2, 2022
2529aa7
ok
Aug 2, 2022
5567909
ok
Aug 2, 2022
0f23692
ok
Aug 2, 2022
fb3153b
ok
Aug 2, 2022
acd242a
ok
Aug 2, 2022
b8eb1d7
ok
Aug 2, 2022
97075c6
ok
Aug 2, 2022
15d013f
ok
Aug 2, 2022
2364894
ok
Aug 2, 2022
7d12c0e
ok
Aug 2, 2022
de8dc00
ok
Aug 2, 2022
8f9ffdd
ok
Aug 2, 2022
9058353
ok
Aug 3, 2022
0bd6e79
delete instruction from c
Aug 3, 2022
20a140b
format
Aug 3, 2022
e3b5eb6
add lifetime
Aug 3, 2022
91e6b3e
ok
Aug 3, 2022
c55f917
does this work
Aug 3, 2022
38c180a
reformat
Aug 3, 2022
f50779e
test clippy
Aug 3, 2022
e7173d8
hm
Aug 3, 2022
96d0f10
merge and bugfix
Aug 3, 2022
ee26a5f
cleanup
Aug 3, 2022
47e1d5b
fix defines
Aug 3, 2022
cc869aa
Fix version of bytemuck and clean import
guibescos Aug 3, 2022
b53696f
Merge branch 'migrate_accounts' of github.com:pyth-network/pyth-clien…
guibescos Aug 3, 2022
6374215
Rust oracle
guibescos Aug 3, 2022
27466d3
Fix double borrow
guibescos Aug 3, 2022
fd94e20
Cleanup
guibescos Aug 5, 2022
c8f6b23
Finalize merge
guibescos Aug 5, 2022
d9aa1fd
Merge branch 'main' into add-price-rust
guibescos Aug 5, 2022
ed6c7d8
Refactor derivs
guibescos Aug 5, 2022
460e125
Load checks length
guibescos Aug 5, 2022
81142a1
Refactor load product
guibescos Aug 5, 2022
bacc9f0
Pubkey assign
guibescos Aug 5, 2022
48ccf9d
Comments
guibescos Aug 5, 2022
cc7ea35
Fix pubkey assign
guibescos Aug 5, 2022
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
16 changes: 16 additions & 0 deletions program/rust/src/c_oracle_header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,19 @@ unsafe impl Zeroable for cmd_hdr {
#[cfg(target_endian = "little")]
unsafe impl Pod for cmd_hdr {
}

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

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

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

#[cfg(target_endian = "little")]
unsafe impl Pod for pc_pub_key_t {
}
3 changes: 3 additions & 0 deletions program/rust/src/processor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use crate::c_entrypoint_wrapper;
use crate::c_oracle_header::{
cmd_hdr,
command_t_e_cmd_add_mapping,
command_t_e_cmd_add_price,
command_t_e_cmd_agg_price,
command_t_e_cmd_init_mapping,
command_t_e_cmd_upd_account_version,
Expand All @@ -22,6 +23,7 @@ use crate::error::{
};
use crate::rust_oracle::{
add_mapping,
add_price,
init_mapping,
update_price,
update_version,
Expand Down Expand Up @@ -58,6 +60,7 @@ pub fn process_instruction(
command_t_e_cmd_upd_account_version => {
update_version(program_id, accounts, instruction_data)
}
command_t_e_cmd_add_price => add_price(program_id, accounts, instruction_data),
command_t_e_cmd_init_mapping => init_mapping(program_id, accounts, instruction_data),
command_t_e_cmd_add_mapping => add_mapping(program_id, accounts, instruction_data),
_ => c_entrypoint_wrapper(input),
Expand Down
104 changes: 92 additions & 12 deletions program/rust/src/rust_oracle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ use std::mem::{
};

use bytemuck::{
bytes_of,
try_from_bytes,
try_from_bytes_mut,
Pod,
Expand All @@ -21,12 +22,21 @@ use solana_program::pubkey::Pubkey;
use solana_program::rent::Rent;

use crate::c_oracle_header::{
cmd_add_price_t,
cmd_hdr_t,
pc_acc,
pc_map_table_t,
pc_price_t,
pc_prod_t,
pc_pub_key_t,
PC_ACCTYPE_MAPPING,
PC_ACCTYPE_PRICE,
PC_ACCTYPE_PRODUCT,
PC_MAGIC,
PC_MAP_TABLE_SIZE,
PC_MAX_NUM_DECIMALS,
PC_PROD_ACC_SIZE,
PC_PTYPE_UNKNOWN,
};
use crate::error::OracleResult;

Expand Down Expand Up @@ -110,13 +120,56 @@ pub fn add_mapping(
)?;

initialize_mapping_account(next_mapping, hdr.ver_)?;
unsafe {
cur_mapping
.next_
.k1_
.copy_from_slice(&next_mapping.key.to_bytes());
pubkey_assign(&mut cur_mapping.next_, &next_mapping.key.to_bytes());

Ok(SUCCESS)
}

/// add a price account to a product account
/// accounts[0] funding account [signer writable]
/// accounts[1] product account to add the price account to [signer writable]
/// accounts[2] newly created price account [signer writable]
pub fn add_price(
program_id: &Pubkey,
accounts: &[AccountInfo],
instruction_data: &[u8],
) -> OracleResult {
let cmd_args = load::<cmd_add_price_t>(instruction_data)?;

if cmd_args.expo_ > PC_MAX_NUM_DECIMALS as i32
|| cmd_args.expo_ < -(PC_MAX_NUM_DECIMALS as i32)
|| cmd_args.ptype_ == PC_PTYPE_UNKNOWN
{
return Err(ProgramError::InvalidArgument);
}

let [_funding_account, product_account, price_account] = match accounts {
[x, y, z]
if valid_funding_account(x)
&& valid_signable_account(program_id, y, PC_PROD_ACC_SIZE as usize)
&& valid_signable_account(program_id, z, size_of::<pc_price_t>())
&& valid_fresh_account(z) =>
{
Ok([x, y, z])
}
_ => Err(ProgramError::InvalidArgument),
}?;

let mut product_data = load_product_account_mut(product_account, cmd_args.ver_)?;

clear_account(price_account)?;

let mut price_data = load_account_as_mut::<pc_price_t>(price_account)?;
price_data.magic_ = PC_MAGIC;
price_data.ver_ = cmd_args.ver_;
price_data.type_ = PC_ACCTYPE_PRICE;
price_data.size_ = (size_of::<pc_price_t>() - size_of_val(&price_data.comp_)) as u32;
price_data.expo_ = cmd_args.expo_;
price_data.ptype_ = cmd_args.ptype_;
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());

Ok(SUCCESS)
}

Expand Down Expand Up @@ -154,7 +207,11 @@ pub fn clear_account(account: &AccountInfo) -> Result<(), ProgramError> {

/// Interpret the bytes in `data` as a value of type `T`
fn load<T: Pod>(data: &[u8]) -> Result<&T, ProgramError> {
try_from_bytes(&data[0..size_of::<T>()]).map_err(|_| ProgramError::InvalidArgument)
try_from_bytes(
data.get(0..size_of::<T>())
.ok_or(ProgramError::InvalidArgument)?,
)
.map_err(|_| ProgramError::InvalidArgument)
}

/// Interpret the bytes in `data` as a mutable value of type `T`
Expand Down Expand Up @@ -191,17 +248,16 @@ fn load_mapping_account_mut<'a>(
account: &'a AccountInfo,
expected_version: u32,
) -> Result<RefMut<'a, pc_map_table_t>, ProgramError> {
let mapping_account_ref = load_account_as_mut::<pc_map_table_t>(account)?;
let mapping_account = *mapping_account_ref;
let mapping_data = load_account_as_mut::<pc_map_table_t>(account)?;

pyth_assert(
mapping_account.magic_ == PC_MAGIC
&& mapping_account.ver_ == expected_version
&& mapping_account.type_ == PC_ACCTYPE_MAPPING,
mapping_data.magic_ == PC_MAGIC
&& mapping_data.ver_ == expected_version
&& mapping_data.type_ == PC_ACCTYPE_MAPPING,
ProgramError::InvalidArgument,
)?;

Ok(mapping_account_ref)
Ok(mapping_data)
}

/// Initialize account as a new mapping account. This function will zero out any existing data in
Expand All @@ -218,3 +274,27 @@ fn initialize_mapping_account(account: &AccountInfo, version: u32) -> Result<(),

Ok(())
}

/// Mutably borrow the data in `account` as a product account, validating that the account
/// is properly formatted. Any mutations to the returned value will be reflected in the
/// account data. Use this to read already-initialized accounts.
fn load_product_account_mut<'a>(
account: &'a AccountInfo,
expected_version: u32,
) -> Result<RefMut<'a, pc_prod_t>, ProgramError> {
let product_data = load_account_as_mut::<pc_prod_t>(account)?;

pyth_assert(
product_data.magic_ == PC_MAGIC
&& product_data.ver_ == expected_version
&& product_data.type_ == PC_ACCTYPE_PRODUCT,
ProgramError::InvalidArgument,
)?;

Ok(product_data)
}

// Assign pubkey bytes from source to target, fails if source is not 32 bytes
fn pubkey_assign(target: &mut pc_pub_key_t, source: &[u8]) {
unsafe { target.k1_.copy_from_slice(source) }
}