From f6466df0805d825f32d923e7f6aaedf05bf79d1b Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Fri, 5 Aug 2022 22:36:31 +0000 Subject: [PATCH 01/58] added resize feature --- docker/Dockerfile | 5 ++++- program/rust/Cargo.toml | 3 +++ program/rust/src/rust_oracle.rs | 15 +++++++++++++-- scripts/build-bpf.sh | 12 +++++++++--- 4 files changed, 29 insertions(+), 6 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index fb7394d90..2acf861f8 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -66,8 +66,11 @@ RUN cp -a /usr/bin/sdk solana RUN ./pyth-client/scripts/patch-solana.sh # Build and test the oracle program. -RUN cd pyth-client && ./scripts/build-bpf.sh . +RUN cd pyth-client && ./scripts/build-bpf.sh . "test" RUN /bin/bash -l -c "pytest-3 --pyargs pyth" +# Build for releases +RUN cd pyth-client && ./scripts/build-bpf.sh + ENTRYPOINT [] CMD [] diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index babf453bd..c63c7de82 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -5,6 +5,9 @@ edition = "2021" license = "Apache 2.0" publish = false +[features] +resize-account = [] + [build-dependencies] bindgen = "0.60.1" diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index ed4427ecb..70e3a369a 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -57,13 +57,24 @@ pub fn update_price( /// has version number/ account type dependant logic to make sure the given account is compatible /// with the current version /// updates the version number for all accounts, and resizes price accounts +#[cfg(feature = "resize-account")] pub fn update_version( _program_id: &Pubkey, _accounts: &[AccountInfo], _instruction_data: &[u8], ) -> OracleResult { - panic!("Need to merge fix to pythd in order to implement this"); - // Ok(SUCCESS) + //actual implementation to follow + Ok(SUCCESS) +} + +/// place holder untill we are ready to resize accounts +#[cfg(not(feature = "resize-account"))] +pub fn update_version( + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], +) -> OracleResult { + panic!("Can not update version yet!"); } diff --git a/scripts/build-bpf.sh b/scripts/build-bpf.sh index 2ed8be054..ac7a0453f 100755 --- a/scripts/build-bpf.sh +++ b/scripts/build-bpf.sh @@ -28,7 +28,7 @@ set -x cd "${C_DIR}" export V="${V:-1}" make clean -make "${@:2}" +make make cpyth rm ./target/*-keypair.json @@ -38,8 +38,14 @@ cd "${PYTH_DIR}" cargo clean cargo test cargo clean -cargo build-bpf - +if [[ $# -ge 2 ]] && [[ $2 == "test" ]] +then + echo "testing" + cargo build-bpf --features resize-account +else + echo "production" + cargo build-bpf +fi sha256sum ./target/**/*.so From 734828f65d674f484f5add766d9c654a08f80077 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Fri, 5 Aug 2022 22:43:26 +0000 Subject: [PATCH 02/58] added update account to log --- program/rust/src/log.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/program/rust/src/log.rs b/program/rust/src/log.rs index e91dad706..32c4dce6e 100644 --- a/program/rust/src/log.rs +++ b/program/rust/src/log.rs @@ -86,6 +86,11 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu command_t_e_cmd_upd_product => { msg!("UpdateProduct"); } + + command_t_e_cmd_upd_account_version => { + //accounts[1] is the updated account + msg!("UpdateAccount: {}", accounts[1].key); + } _ => { msg!("UnrecognizedInstruction"); return Err(OracleError::UnrecognizedInstruction.into()); From b2af9e219e14634b5f1d9ac309660d95c362ed57 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 17:54:31 +0000 Subject: [PATCH 03/58] implemented upgrade instruction --- program/rust/src/error.rs | 4 + program/rust/src/rust_oracle.rs | 96 +++++++++++++++++++++--- program/rust/src/time_machine_types.rs | 100 ++++++++++++++++++++++++- 3 files changed, 188 insertions(+), 12 deletions(-) diff --git a/program/rust/src/error.rs b/program/rust/src/error.rs index 1d1ca61ab..9990b336a 100644 --- a/program/rust/src/error.rs +++ b/program/rust/src/error.rs @@ -20,6 +20,10 @@ pub enum OracleError { UnknownCError = 602, #[error("UnrecognizedInstruction")] UnrecognizedInstruction = 603, + #[error("InvalidFundingAccount")] + InvalidFundingAccount = 604, + #[error("InvalidSignableAccount")] + InvalidSignableAccount = 605, } impl From for ProgramError { diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 70e3a369a..25c079930 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -20,6 +20,14 @@ use solana_program::program_memory::sol_memset; use solana_program::pubkey::Pubkey; use solana_program::rent::Rent; +#[cfg(feature = "resize-account")] +use crate::error::OracleError; +#[cfg(feature = "resize-account")] +use solana_program::program::invoke; +#[cfg(feature = "resize-account")] +use solana_program::system_instruction::transfer; + + use crate::c_oracle_header::{ cmd_add_price_t, cmd_hdr_t, @@ -54,17 +62,84 @@ pub fn update_price( // of the program c_entrypoint_wrapper(input) } + +///resize price account and initialize the TimeMachineStructure +#[cfg(feature = "resize-account")] +pub fn upgrade_price_account( + funding_account_info: &AccountInfo, + price_account_info: &AccountInfo, + program_id: &Pubkey, +) -> ProgramResult { + pyth_assert( + valid_funding_account(&funding_account_info), + OracleError::InvalidFundingAccount, + )?; + + pyth_assert( + valid_signable_account(program_id, &upgraded_account, size_of::()), + OracleError::InvalidSignableAccount, + )?; + + let account_len = price_account_info.try_data_len()?; + match account_len { + size_of::() => { + //compute the number of lamports needed in the price account to update it + let rent: Rent = Default::default(); + let lamports_needed: u64 = rent + .minimum_balance(new_account_len) + .saturating_sub(price_account_info.lamports()); + //transfer lamports if necessary + if lamports_needed > 0 { + let transfer_instruction = transfer( + funding_account_info.key, + price_account_info.key, + lamports_needed, + ); + invoke( + &transfer_instruction, + &[finding_account, price_account_info], + )?; + } + //resize + price_account_info.realloc(new_account_len, false)?; + //update twap_tracker + let mut price_account = load_account_as_mut::(price_account_info)?; + price_account.time_machine.add_first_price( + price_account.price_data.current_time, + price_account.price_data.current_price, + price_account.price_data.current_conf, + ); + } + PRICE_ACCOUNT_SIZE => Ok(()), + _ => Err(ProgramError::InvalidArgument), + } +} + /// has version number/ account type dependant logic to make sure the given account is compatible /// with the current version /// updates the version number for all accounts, and resizes price accounts #[cfg(feature = "resize-account")] pub fn update_version( - _program_id: &Pubkey, - _accounts: &[AccountInfo], - _instruction_data: &[u8], + program_id: &Pubkey, + accounts: &[AccountInfo], + instruction_data: &[u8], ) -> OracleResult { - //actual implementation to follow - Ok(SUCCESS) + let mut funding_account_info = accounts[0]; + let mut upgraded_account = accounts[1]; + + //read account info + let pyth_acc_info = + load::(&funding_account_info.try_borrow_data()?[..size_of::()])?; + + //Note: currently we do not seem to need to do anything with the version number, + // but such logic can be added here, or in the per account type upgrades below + + match pyth_acc_info.type_ { + PC_ACCTYPE_PRICE => { + upgrade_price_account(&funding_account_info, &upgraded_account, &program_id) + } + _ => Ok(()), + } } /// place holder untill we are ready to resize accounts @@ -153,7 +228,7 @@ pub fn add_price( return Err(ProgramError::InvalidArgument); } - let [_funding_account, product_account, price_account] = match accounts { + let [_funding_account, product_account, price_account_info] = match accounts { [x, y, z] if valid_funding_account(x) && valid_signable_account(program_id, y, PC_PROD_ACC_SIZE as usize) @@ -167,9 +242,9 @@ pub fn add_price( let mut product_data = load_product_account_mut(product_account, cmd_args.ver_)?; - clear_account(price_account)?; + clear_account(price_account_info)?; - let mut price_data = load_account_as_mut::(price_account)?; + let mut price_data = load_account_as_mut::(price_account_info)?; price_data.magic_ = PC_MAGIC; price_data.ver_ = cmd_args.ver_; price_data.type_ = PC_ACCTYPE_PRICE; @@ -178,7 +253,10 @@ pub fn add_price( 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()); + pubkey_assign( + &mut product_data.px_acc_, + &price_account_info.key.to_bytes(), + ); Ok(SUCCESS) } diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 8298f6baa..132c2cd79 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -1,4 +1,36 @@ -#[derive(Debug, Clone)] +use crate::c_oracle_header::{ + pc_price_t, + EXTRA_PUBLISHER_SPACE, +}; +use crate::error::OracleError; +use bytemuck::{ + Pod, + Zeroable, +}; +use solana_program::msg; + +pub trait Tracker { + /// add the first price to a zero initialized tracker + fn add_first_price( + &mut self, + current_time: u64, + current_price: u64, + current_conf: u64, + ) -> Result<(), OracleError>; + + ///add a new price to a tracker + fn add_price( + &mut self, + current_time: u64, + prev_time: u64, + current_price: u64, + prev_price: u64, + current_conf: u64, + prev_conf: u64, + ) -> Result<(), OracleError>; +} + +#[derive(Debug, Clone, Copy)] #[repr(C)] /// this wraps multiple SMA and tick trackers, and includes all the state /// used by the time machine @@ -7,10 +39,61 @@ pub struct TimeMachineWrapper { place_holder: [u8; 1864], } +impl Tracker for TimeMachineWrapper { + fn add_first_price( + &mut self, + _current_time: u64, + _current_price: u64, + _current_conf: u64, + ) -> Result<(), OracleError> { + msg!("implement me"); + Ok(()) + } + fn add_price( + &mut self, + _current_time: u64, + _prev_time: u64, + _current_price: u64, + _prev_price: u64, + _current_conf: u64, + _prev_conf: u64, + ) -> Result<(), OracleError> { + msg!("implement me"); + Ok(()) + } +} + +#[derive(Copy, Clone)] +#[repr(C)] +/// wraps everything stored in a price account +pub struct PriceAccountWrapper { + //an instance of the c price_t type + price_data: pc_price_t, + //space for more publishers + extra_publisher_space: [u8; EXTRA_PUBLISHER_SPACE as usize], + //TimeMachine + time_machine: TimeMachineWrapper, +} + +#[cfg(target_endian = "little")] +unsafe impl Zeroable for PriceAccountWrapper { +} + +#[cfg(target_endian = "little")] +unsafe impl Pod for PriceAccountWrapper { +} + + #[cfg(test)] pub mod tests { - use crate::c_oracle_header::TIME_MACHINE_STRUCT_SIZE; - use crate::time_machine_types::TimeMachineWrapper; + use crate::c_oracle_header::{ + PRICE_ACCOUNT_SIZE, + TIME_MACHINE_STRUCT_SIZE, + }; + use crate::time_machine_types::{ + PriceAccountWrapper, + TimeMachineWrapper, + }; use std::mem::size_of; #[test] ///test that the size defined in C matches that @@ -24,4 +107,15 @@ pub mod tests { size_of::() ); } + #[test] + ///test that priceAccountWrapper has a correct size + fn c_price_account_size_is_correct() { + assert_eq!( + size_of::(), + PRICE_ACCOUNT_SIZE.try_into().unwrap(), + "expected PRICE_ACCOUNT_SIZE ({}) in oracle.h to the same as the size of PriceAccountWrapper ({})", + PRICE_ACCOUNT_SIZE, + size_of::() + ); + } } From 58012e5748148f9ea6fe4520995a875f077f5fbc Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 20:50:10 +0000 Subject: [PATCH 04/58] fixed build errors --- program/rust/src/error.rs | 2 + program/rust/src/rust_oracle.rs | 80 +++++++++++++++++--------- program/rust/src/time_machine_types.rs | 31 +++++++--- 3 files changed, 77 insertions(+), 36 deletions(-) diff --git a/program/rust/src/error.rs b/program/rust/src/error.rs index 9990b336a..8ed7b5f2a 100644 --- a/program/rust/src/error.rs +++ b/program/rust/src/error.rs @@ -24,6 +24,8 @@ pub enum OracleError { InvalidFundingAccount = 604, #[error("InvalidSignableAccount")] InvalidSignableAccount = 605, + #[error("InvalidSystemAccount")] + InvalidSystemAccount = 606, } impl From for ProgramError { diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 25c079930..3ef2e67ae 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -23,9 +23,13 @@ use solana_program::rent::Rent; #[cfg(feature = "resize-account")] use crate::error::OracleError; #[cfg(feature = "resize-account")] +use crate::time_machine_types::PriceAccountWrapper; +#[cfg(feature = "resize-account")] use solana_program::program::invoke; #[cfg(feature = "resize-account")] use solana_program::system_instruction::transfer; +#[cfg(feature = "resize-account")] +use solana_program::system_program::check_id; use crate::c_oracle_header::{ @@ -51,6 +55,12 @@ use crate::utils::pyth_assert; use super::c_entrypoint_wrapper; +#[cfg(feature = "resize-account")] +const PRICE_T_SIZE: usize = size_of::(); +#[cfg(feature = "resize-account")] +const PRICE_ACCOUNT_SIZE: usize = size_of::(); + + ///Calls the c oracle update_price, and updates the Time Machine if needed pub fn update_price( _program_id: &Pubkey, @@ -65,28 +75,30 @@ pub fn update_price( ///resize price account and initialize the TimeMachineStructure #[cfg(feature = "resize-account")] -pub fn upgrade_price_account( - funding_account_info: &AccountInfo, - price_account_info: &AccountInfo, +pub fn upgrade_price_account<'a>( + funding_account_info: &AccountInfo<'a>, + price_account_info: &AccountInfo<'a>, + system_program: &AccountInfo<'a>, program_id: &Pubkey, -) -> ProgramResult { +) -> OracleResult { pyth_assert( valid_funding_account(&funding_account_info), - OracleError::InvalidFundingAccount, + OracleError::InvalidFundingAccount.into(), )?; pyth_assert( - valid_signable_account(program_id, &upgraded_account, size_of::()), - OracleError::InvalidSignableAccount, + valid_signable_account(program_id, &price_account_info, size_of::()), + OracleError::InvalidSignableAccount.into(), )?; let account_len = price_account_info.try_data_len()?; + //const PRICE_T_SIZE: usize = size_of::(); match account_len { - size_of::() => { + PRICE_T_SIZE => { //compute the number of lamports needed in the price account to update it let rent: Rent = Default::default(); let lamports_needed: u64 = rent - .minimum_balance(new_account_len) + .minimum_balance(size_of::()) .saturating_sub(price_account_info.lamports()); //transfer lamports if necessary if lamports_needed > 0 { @@ -97,51 +109,65 @@ pub fn upgrade_price_account( ); invoke( &transfer_instruction, - &[finding_account, price_account_info], + &[ + funding_account_info.clone(), + price_account_info.clone(), + system_program.clone(), + ], )?; } //resize - price_account_info.realloc(new_account_len, false)?; + //we do not need to zero initialize since this is the first time this memory + //is allocated + price_account_info.realloc(size_of::(), false)?; //update twap_tracker let mut price_account = load_account_as_mut::(price_account_info)?; - price_account.time_machine.add_first_price( - price_account.price_data.current_time, - price_account.price_data.current_price, - price_account.price_data.current_conf, - ); + price_account.add_first_price()?; + Ok(SUCCESS) } - PRICE_ACCOUNT_SIZE => Ok(()), + PRICE_ACCOUNT_SIZE => Ok(SUCCESS), _ => Err(ProgramError::InvalidArgument), } } - /// has version number/ account type dependant logic to make sure the given account is compatible /// with the current version /// updates the version number for all accounts, and resizes price accounts +/// accounts[0] funding account [signer writable] +/// accounts[1] upgradded acount [signer writable] +/// accounts [2] system program #[cfg(feature = "resize-account")] pub fn update_version( program_id: &Pubkey, accounts: &[AccountInfo], - instruction_data: &[u8], + _instruction_data: &[u8], ) -> OracleResult { - let mut funding_account_info = accounts[0]; - let mut upgraded_account = accounts[1]; + let funding_account_info = &accounts[0]; + let upgraded_account = &accounts[1]; + let system_program = &accounts[2]; + + pyth_assert( + check_id(system_program.key), + OracleError::InvalidSystemAccount.into(), + )?; //read account info - let pyth_acc_info = - load::(&funding_account_info.try_borrow_data()?[..size_of::()])?; + let pyth_acc_info = load_account_as::(&funding_account_info)?; //Note: currently we do not seem to need to do anything with the version number, // but such logic can be added here, or in the per account type upgrades below match pyth_acc_info.type_ { - PC_ACCTYPE_PRICE => { - upgrade_price_account(&funding_account_info, &upgraded_account, &program_id) - } - _ => Ok(()), + PC_ACCTYPE_PRICE => upgrade_price_account( + &funding_account_info, + &upgraded_account, + &system_program, + &program_id, + ), + _ => Ok(SUCCESS), } } + /// place holder untill we are ready to resize accounts #[cfg(not(feature = "resize-account"))] pub fn update_version( diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 132c2cd79..03d1e7f68 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -14,7 +14,7 @@ pub trait Tracker { fn add_first_price( &mut self, current_time: u64, - current_price: u64, + current_price: i64, current_conf: u64, ) -> Result<(), OracleError>; @@ -23,8 +23,8 @@ pub trait Tracker { &mut self, current_time: u64, prev_time: u64, - current_price: u64, - prev_price: u64, + current_price: i64, + prev_price: i64, current_conf: u64, prev_conf: u64, ) -> Result<(), OracleError>; @@ -43,7 +43,7 @@ impl Tracker for TimeMachineWrapper { fn add_first_price( &mut self, _current_time: u64, - _current_price: u64, + _current_price: i64, _current_conf: u64, ) -> Result<(), OracleError> { msg!("implement me"); @@ -53,8 +53,8 @@ impl Tracker for TimeMachineWrapper { &mut self, _current_time: u64, _prev_time: u64, - _current_price: u64, - _prev_price: u64, + _current_price: i64, + _prev_price: i64, _current_conf: u64, _prev_conf: u64, ) -> Result<(), OracleError> { @@ -68,11 +68,24 @@ impl Tracker for TimeMachineWrapper { /// wraps everything stored in a price account pub struct PriceAccountWrapper { //an instance of the c price_t type - price_data: pc_price_t, + pub price_data: pc_price_t, //space for more publishers - extra_publisher_space: [u8; EXTRA_PUBLISHER_SPACE as usize], + pub extra_publisher_space: [u8; EXTRA_PUBLISHER_SPACE as usize], //TimeMachine - time_machine: TimeMachineWrapper, + pub time_machine: TimeMachineWrapper, +} +impl PriceAccountWrapper { + #[cfg(feature = "resize-account")] + pub fn add_first_price(&mut self) -> Result<(), OracleError> { + self.time_machine.add_first_price( + self.price_data + .timestamp_ + .try_into() + .map_err(|_| OracleError::IntegerCastingError)?, + self.price_data.agg_.price_, + self.price_data.agg_.conf_, + ) + } } #[cfg(target_endian = "little")] From a054e855b6f4648483a8335b1ea54f9d84318253 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 20:50:32 +0000 Subject: [PATCH 05/58] added test for resizing --- docker/Dockerfile | 6 ++- pyth/tests/test_publish.py | 99 +++++++++++++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 3 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 2acf861f8..959730b4c 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -27,7 +27,8 @@ RUN apt-get install -qq \ qt5-qmake \ qtbase5-dev-tools \ libqt5websockets5-dev\ - libclang-dev + libclang-dev\ + python3-pip # Install jcon-cpp library RUN git clone https://github.com/joncol/jcon-cpp.git /jcon-cpp && cd /jcon-cpp && git checkout 2235654e39c7af505d7158bf996e47e37a23d6e3 && mkdir build && cd build && cmake .. && make -j4 && make install @@ -56,6 +57,9 @@ export PYTHONPATH=\"\${PYTHONPATH:+\$PYTHONPATH:}\${HOME}/pyth-client\"\n\ COPY --chown=pyth:pyth . pyth-client/ +# Install python packages needed for testing +RUN pip3 install solana + # Build off-chain binaries. RUN cd pyth-client && ./scripts/build.sh diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index f9e8bde6c..75d4951a1 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -1,10 +1,20 @@ +from typing import Dict +from construct import Bytes, Int32sl, Int32ul, Struct +from solana.publickey import PublicKey +from solana.transaction import AccountMeta, TransactionInstruction, Transaction +from solana.keypair import Keypair +from solana.rpc.api import Client +import base64 + +import asyncio + import json import time from subprocess import check_call, check_output def test_publish(solana_test_validator, pyth_dir, - pyth_init_product, pyth_init_price): + pyth_init_product, pyth_init_price, solana_keygen, solana_program_deploy): def get_price_acct(): cmd = [ @@ -19,6 +29,52 @@ def get_price_acct(): output = output.decode('ascii') output = json.loads(output) return output['price_accounts'][0] + + def resize_account(price_acc_address): + """ + given a string with the pubkey of a price accountm it calls the resize instruction of the Oracle on it + """ + #constants from oracle.h + PROGRAM_VERSION = 2 #TODO: update this + COMMAND_UPD_ACCOUNT = 14 + SYSTEM_PROGRAM = "11111111111111111111111111111111" + + #update version of price accounts to make sure they resize + layout = Struct("version" / Int32ul, "command" / Int32sl) + data = layout.build(dict(version=PROGRAM_VERSION, command=COMMAND_UPD_ACCOUNT)) + funding_key = PublicKey(solana_keygen[0]) + price_key = PublicKey(price_acc_address) + system_key = PublicKey(SYSTEM_PROGRAM) + print("program id is", solana_program_deploy) + resize_instruction = TransactionInstruction( + data=data, + keys=[ + AccountMeta(pubkey=funding_key, is_signer=True, is_writable=True), + AccountMeta(pubkey=price_key, is_signer=False, is_writable=True), + AccountMeta(pubkey=system_key, is_signer=False, is_writable=False), + ], + program_id = PublicKey(solana_program_deploy), + ) + txn = Transaction().add(resize_instruction) + solana_client = Client("http://localhost:8899") + key_file = open(solana_keygen[1]) + key_data = json.load(key_file) + key_file.close() + + sender = Keypair.from_secret_key(key_data) + txn.sign(sender) + solana_client.send_transaction(txn, sender) + + def get_account_size(acc_address): + """ + given a string with the pubkey of an account, resize it + """ + PublicKey(acc_address) + solana_client = Client("http://localhost:8899") + data = solana_client.get_account_info(PublicKey(acc_address), encoding = 'base64')['result']['value']['data'][0] + data = base64.b64decode(data) + return len(data) + before = get_price_acct() assert before['publisher_accounts'][0]['price'] == 0 @@ -49,8 +105,47 @@ def get_price_acct(): check_call(cmd) time.sleep(20) - after = get_price_acct() assert after['publisher_accounts'][0]['price'] == 150 assert after['publisher_accounts'][0]['conf'] == 7 assert after['publisher_accounts'][0]['status'] == 'trading' + + resize_account(pyth_init_price['LTC']) + time.sleep(20) + #defined in oracle.h + new_account_size = 6176 + assert get_account_size(pyth_init_price['LTC']) == new_account_size + time.sleep(20) + + + + #try adding a new price to the resized accounts + cmd = [ + 'pyth', 'upd_price_val', + pyth_init_price['LTC'], + '100', '1', 'trading', + '-r', 'localhost', + '-k', pyth_dir, + '-c', 'finalized', + '-x', + ] + check_call(cmd) + + time.sleep(20) + + cmd = [ + 'pyth', 'upd_price', + pyth_init_price['LTC'], + '-r', 'localhost', + '-k', pyth_dir, + '-c', 'finalized', + '-x', + ] + check_call(cmd) + + time.sleep(20) + + after = get_price_acct() + assert after['publisher_accounts'][0]['price'] == 100 + assert after['publisher_accounts'][0]['conf'] == 1 + assert after['publisher_accounts'][0]['status'] == 'trading' \ No newline at end of file From 811824d7751e4714e16faea434954f88bd42cf1e Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 21:07:50 +0000 Subject: [PATCH 06/58] implemented price updates --- program/rust/src/rust_oracle.rs | 27 +++++++++++++++++++------- program/rust/src/time_machine_types.rs | 17 ++++++++++++++++ 2 files changed, 37 insertions(+), 7 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 3ef2e67ae..02757d422 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -15,14 +15,15 @@ use bytemuck::bytes_of; use solana_program::account_info::AccountInfo; use solana_program::entrypoint::SUCCESS; +use solana_program::msg; use solana_program::program_error::ProgramError; use solana_program::program_memory::sol_memset; use solana_program::pubkey::Pubkey; use solana_program::rent::Rent; + #[cfg(feature = "resize-account")] use crate::error::OracleError; -#[cfg(feature = "resize-account")] use crate::time_machine_types::PriceAccountWrapper; #[cfg(feature = "resize-account")] use solana_program::program::invoke; @@ -48,6 +49,7 @@ use crate::c_oracle_header::{ PC_MAX_NUM_DECIMALS, PC_PROD_ACC_SIZE, PC_PTYPE_UNKNOWN, + SUCCESSFULLY_UPDATED_AGGREGATE, }; use crate::error::OracleResult; @@ -55,22 +57,33 @@ use crate::utils::pyth_assert; use super::c_entrypoint_wrapper; -#[cfg(feature = "resize-account")] const PRICE_T_SIZE: usize = size_of::(); -#[cfg(feature = "resize-account")] const PRICE_ACCOUNT_SIZE: usize = size_of::(); ///Calls the c oracle update_price, and updates the Time Machine if needed pub fn update_price( _program_id: &Pubkey, - _accounts: &[AccountInfo], + accounts: &[AccountInfo], _instruction_data: &[u8], input: *mut u8, ) -> OracleResult { - //For now, we did not change the behavior of this. this is just to show the proposed structure - // of the program - c_entrypoint_wrapper(input) + let price_account_info = &accounts[1]; + let account_len = price_account_info.try_data_len()?; + if account_len < PRICE_ACCOUNT_SIZE { + if account_len != PRICE_T_SIZE { + return Err(ProgramError::InvalidArgument); + } + msg!("Please resize the account to allow for SMA tracking!"); + return c_entrypoint_wrapper(input); + } + let c_ret_value = c_entrypoint_wrapper(input)?; + if c_ret_value == SUCCESSFULLY_UPDATED_AGGREGATE { + let mut price_account = load_account_as_mut::(&price_account_info)?; + price_account.add_price()?; + msg!("updated tracker!"); + } + Ok(c_ret_value) } ///resize price account and initialize the TimeMachineStructure diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 03d1e7f68..975525554 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -86,6 +86,23 @@ impl PriceAccountWrapper { self.price_data.agg_.conf_, ) } + + pub fn add_price(&mut self) -> Result<(), OracleError> { + self.time_machine.add_price( + self.price_data + .timestamp_ + .try_into() + .map_err(|_| OracleError::IntegerCastingError)?, + self.price_data + .prev_timestamp_ + .try_into() + .map_err(|_| OracleError::IntegerCastingError)?, + self.price_data.agg_.price_, + self.price_data.prev_price_, + self.price_data.agg_.conf_, + self.price_data.prev_conf_, + ) + } } #[cfg(target_endian = "little")] From 61ee6b10f229e742e1112a35016a09b247569bf3 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 21:24:55 +0000 Subject: [PATCH 07/58] fixed merge errors --- program/rust/src/rust_oracle.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 977377b81..d5e5cd446 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -280,9 +280,9 @@ pub fn add_price( let mut product_data = load_product_account_mut(product_account, cmd_args.ver_)?; - clear_account(price_account_info)?; + clear_account(price_account)?; - let mut price_data = load_account_as_mut::(price_account_info)?; + let mut price_data = load_account_as_mut::(price_account)?; price_data.magic_ = PC_MAGIC; price_data.ver_ = cmd_args.ver_; price_data.type_ = PC_ACCTYPE_PRICE; @@ -291,10 +291,7 @@ pub fn add_price( 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_info.key.to_bytes(), - ); + pubkey_assign(&mut product_data.px_acc_, &price_account.key.to_bytes()); Ok(SUCCESS) } From 1db05a87baa1c9627dc4fce4e5ece3d2c3b8ea74 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 21:32:41 +0000 Subject: [PATCH 08/58] fixed CI fmt error --- program/rust/src/rust_oracle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index d5e5cd446..b026afa1d 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -80,7 +80,7 @@ pub fn update_price( } let c_ret_value = c_entrypoint_wrapper(input)?; if c_ret_value == SUCCESSFULLY_UPDATED_AGGREGATE { - let mut price_account = load_account_as_mut::(&price_account_info)?; + let mut price_account = load_account_as_mut::(price_account_info)?; price_account.add_price()?; msg!("updated tracker!"); } From 6f5add866673eaafbdd3cede395438871fa91d0f Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 21:44:26 +0000 Subject: [PATCH 09/58] removed duplicate import --- program/rust/src/rust_oracle.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index b026afa1d..739c5bc52 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -22,8 +22,6 @@ use solana_program::pubkey::Pubkey; use solana_program::rent::Rent; -#[cfg(feature = "resize-account")] -use crate::error::OracleError; use crate::time_machine_types::PriceAccountWrapper; #[cfg(feature = "resize-account")] use solana_program::program::invoke; From c389080f8040eb89d7a5271a8e53138bc8492917 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Mon, 8 Aug 2022 22:16:45 +0000 Subject: [PATCH 10/58] fixed typo --- program/rust/src/rust_oracle.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 739c5bc52..a12f3e437 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -154,7 +154,7 @@ pub fn update_version( _instruction_data: &[u8], ) -> OracleResult { let funding_account_info = &accounts[0]; - let upgraded_account = &accounts[1]; + let upgraded_account_info = &accounts[1]; let system_program = &accounts[2]; pyth_assert( @@ -163,7 +163,7 @@ pub fn update_version( )?; //read account info - let pyth_acc_info = load_account_as::(&funding_account_info)?; + let pyth_acc_info = load_account_as::(&upgraded_account_info)?; //Note: currently we do not seem to need to do anything with the version number, // but such logic can be added here, or in the per account type upgrades below @@ -171,7 +171,7 @@ pub fn update_version( match pyth_acc_info.type_ { PC_ACCTYPE_PRICE => upgrade_price_account( &funding_account_info, - &upgraded_account, + &upgraded_account_info, &system_program, &program_id, ), From e0b8d4c333905a33e193f75848d943c7361c6451 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Tue, 9 Aug 2022 00:42:00 +0000 Subject: [PATCH 11/58] made account upgrade permissionless --- program/rust/src/error.rs | 2 ++ program/rust/src/rust_oracle.rs | 11 +++++++---- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/program/rust/src/error.rs b/program/rust/src/error.rs index 8ed7b5f2a..e4e13e104 100644 --- a/program/rust/src/error.rs +++ b/program/rust/src/error.rs @@ -26,6 +26,8 @@ pub enum OracleError { InvalidSignableAccount = 605, #[error("InvalidSystemAccount")] InvalidSystemAccount = 606, + #[error("InvalidWritableAccount")] + InvalidWritableAccount = 607, } impl From for ProgramError { diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index a12f3e437..8e178ed46 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -99,8 +99,8 @@ pub fn upgrade_price_account<'a>( )?; pyth_assert( - valid_signable_account(program_id, &price_account_info, size_of::()), - OracleError::InvalidSignableAccount.into(), + valid_writable_account(program_id, &price_account_info, size_of::()), + OracleError::InvalidWritableAccount.into(), )?; let account_len = price_account_info.try_data_len()?; @@ -349,8 +349,11 @@ fn check_valid_funding_account(account: &AccountInfo) -> Result<(), ProgramError } fn valid_signable_account(program_id: &Pubkey, account: &AccountInfo, minimum_size: usize) -> bool { - account.is_signer - && account.is_writable + account.is_signer && valid_writable_account(program_id, account, minimum_size) +} + +fn valid_writable_account(program_id: &Pubkey, account: &AccountInfo, minimum_size: usize) -> bool { + account.is_writable && account.owner == program_id && account.data_len() >= minimum_size && Rent::default().is_exempt(account.lamports(), account.data_len()) From 4e71ed22e1e2719b0091a3b0833458126cde6889 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Tue, 9 Aug 2022 17:41:31 +0000 Subject: [PATCH 12/58] fixed borrow bug --- program/rust/src/rust_oracle.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 8e178ed46..377005601 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -102,9 +102,7 @@ pub fn upgrade_price_account<'a>( valid_writable_account(program_id, &price_account_info, size_of::()), OracleError::InvalidWritableAccount.into(), )?; - let account_len = price_account_info.try_data_len()?; - //const PRICE_T_SIZE: usize = size_of::(); match account_len { PRICE_T_SIZE => { //compute the number of lamports needed in the price account to update it @@ -141,6 +139,13 @@ pub fn upgrade_price_account<'a>( _ => Err(ProgramError::InvalidArgument), } } + +#[cfg(feature = "resize-account")] +fn get_account_type(account: &AccountInfo) -> Result{ + let account_type = load_account_as::(&account)?.type_; + Ok(account_type) +} + /// has version number/ account type dependant logic to make sure the given account is compatible /// with the current version /// updates the version number for all accounts, and resizes price accounts @@ -163,12 +168,12 @@ pub fn update_version( )?; //read account info - let pyth_acc_info = load_account_as::(&upgraded_account_info)?; + let pyth_acc_type = get_account_type(&upgraded_account_info)?; //Note: currently we do not seem to need to do anything with the version number, // but such logic can be added here, or in the per account type upgrades below - match pyth_acc_info.type_ { + match pyth_acc_type { PC_ACCTYPE_PRICE => upgrade_price_account( &funding_account_info, &upgraded_account_info, From ac28c5c7994a3c7f567e7afae756623f1fd13f26 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Tue, 9 Aug 2022 17:47:34 +0000 Subject: [PATCH 13/58] removed feature logic --- docker/Dockerfile | 13 +++---------- program/rust/Cargo.toml | 5 +---- program/rust/src/rust_oracle.rs | 16 +--------------- program/rust/src/time_machine_types.rs | 1 - scripts/build-bpf.sh | 13 +++---------- 5 files changed, 8 insertions(+), 40 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 959730b4c..3a5bc541a 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -27,8 +27,7 @@ RUN apt-get install -qq \ qt5-qmake \ qtbase5-dev-tools \ libqt5websockets5-dev\ - libclang-dev\ - python3-pip + libclang-dev # Install jcon-cpp library RUN git clone https://github.com/joncol/jcon-cpp.git /jcon-cpp && cd /jcon-cpp && git checkout 2235654e39c7af505d7158bf996e47e37a23d6e3 && mkdir build && cd build && cmake .. && make -j4 && make install @@ -57,9 +56,6 @@ export PYTHONPATH=\"\${PYTHONPATH:+\$PYTHONPATH:}\${HOME}/pyth-client\"\n\ COPY --chown=pyth:pyth . pyth-client/ -# Install python packages needed for testing -RUN pip3 install solana - # Build off-chain binaries. RUN cd pyth-client && ./scripts/build.sh @@ -70,11 +66,8 @@ RUN cp -a /usr/bin/sdk solana RUN ./pyth-client/scripts/patch-solana.sh # Build and test the oracle program. -RUN cd pyth-client && ./scripts/build-bpf.sh . "test" +RUN cd pyth-client && ./scripts/build-bpf.sh . RUN /bin/bash -l -c "pytest-3 --pyargs pyth" -# Build for releases -RUN cd pyth-client && ./scripts/build-bpf.sh - ENTRYPOINT [] -CMD [] +CMD [] \ No newline at end of file diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index c63c7de82..e1062a57b 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -5,9 +5,6 @@ edition = "2021" license = "Apache 2.0" publish = false -[features] -resize-account = [] - [build-dependencies] bindgen = "0.60.1" @@ -17,4 +14,4 @@ bytemuck = "1.11.0" thiserror = "1.0" [lib] -crate-type = ["cdylib", "lib"] +crate-type = ["cdylib", "lib"] \ No newline at end of file diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 377005601..166422f50 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -23,11 +23,8 @@ use solana_program::rent::Rent; use crate::time_machine_types::PriceAccountWrapper; -#[cfg(feature = "resize-account")] use solana_program::program::invoke; -#[cfg(feature = "resize-account")] use solana_program::system_instruction::transfer; -#[cfg(feature = "resize-account")] use solana_program::system_program::check_id; @@ -86,7 +83,6 @@ pub fn update_price( } ///resize price account and initialize the TimeMachineStructure -#[cfg(feature = "resize-account")] pub fn upgrade_price_account<'a>( funding_account_info: &AccountInfo<'a>, price_account_info: &AccountInfo<'a>, @@ -140,7 +136,6 @@ pub fn upgrade_price_account<'a>( } } -#[cfg(feature = "resize-account")] fn get_account_type(account: &AccountInfo) -> Result{ let account_type = load_account_as::(&account)?.type_; Ok(account_type) @@ -152,7 +147,6 @@ fn get_account_type(account: &AccountInfo) -> Result{ /// accounts[0] funding account [signer writable] /// accounts[1] upgradded acount [signer writable] /// accounts [2] system program -#[cfg(feature = "resize-account")] pub fn update_version( program_id: &Pubkey, accounts: &[AccountInfo], @@ -185,15 +179,7 @@ pub fn update_version( } -/// place holder untill we are ready to resize accounts -#[cfg(not(feature = "resize-account"))] -pub fn update_version( - _program_id: &Pubkey, - _accounts: &[AccountInfo], - _instruction_data: &[u8], -) -> OracleResult { - panic!("Can not update version yet!"); -} + /// initialize the first mapping account in a new linked-list of mapping accounts /// accounts[0] funding account [signer writable] diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 975525554..b2ae7565f 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -75,7 +75,6 @@ pub struct PriceAccountWrapper { pub time_machine: TimeMachineWrapper, } impl PriceAccountWrapper { - #[cfg(feature = "resize-account")] pub fn add_first_price(&mut self) -> Result<(), OracleError> { self.time_machine.add_first_price( self.price_data diff --git a/scripts/build-bpf.sh b/scripts/build-bpf.sh index ac7a0453f..15aaf503f 100755 --- a/scripts/build-bpf.sh +++ b/scripts/build-bpf.sh @@ -28,7 +28,7 @@ set -x cd "${C_DIR}" export V="${V:-1}" make clean -make +make "${@:2}" make cpyth rm ./target/*-keypair.json @@ -38,16 +38,9 @@ cd "${PYTH_DIR}" cargo clean cargo test cargo clean -if [[ $# -ge 2 ]] && [[ $2 == "test" ]] -then - echo "testing" - cargo build-bpf --features resize-account -else - echo "production" - cargo build-bpf -fi -sha256sum ./target/**/*.so +cargo build-bpf +sha256sum ./target/**/*.so From fc3c0c13f7ea8e9336432b53381bdeebb4a47a89 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Tue, 9 Aug 2022 17:47:53 +0000 Subject: [PATCH 14/58] cargo fmt --- program/rust/src/rust_oracle.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 166422f50..5927de971 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -136,8 +136,8 @@ pub fn upgrade_price_account<'a>( } } -fn get_account_type(account: &AccountInfo) -> Result{ - let account_type = load_account_as::(&account)?.type_; +fn get_account_type(account: &AccountInfo) -> Result { + let account_type = load_account_as::(&account)?.type_; Ok(account_type) } @@ -179,8 +179,6 @@ pub fn update_version( } - - /// initialize the first mapping account in a new linked-list of mapping accounts /// accounts[0] funding account [signer writable] /// accounts[1] new mapping account [signer writable] From 9b1d17073fa9d1ea750097b21db68ca83391d0f9 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Tue, 9 Aug 2022 17:54:58 +0000 Subject: [PATCH 15/58] made resize permissioned --- program/rust/src/rust_oracle.rs | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 5927de971..b1f1e80ec 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -89,15 +89,8 @@ pub fn upgrade_price_account<'a>( system_program: &AccountInfo<'a>, program_id: &Pubkey, ) -> OracleResult { - pyth_assert( - valid_funding_account(&funding_account_info), - OracleError::InvalidFundingAccount.into(), - )?; - - pyth_assert( - valid_writable_account(program_id, &price_account_info, size_of::()), - OracleError::InvalidWritableAccount.into(), - )?; + check_valid_funding_account(&funding_account_info)?; + check_valid_signable_account(program_id, &price_account_info, size_of::())?; let account_len = price_account_info.try_data_len()?; match account_len { PRICE_T_SIZE => { @@ -333,16 +326,13 @@ fn valid_funding_account(account: &AccountInfo) -> bool { fn check_valid_funding_account(account: &AccountInfo) -> Result<(), ProgramError> { pyth_assert( valid_funding_account(account), - ProgramError::InvalidArgument, + OracleError::InvalidFundingAccount.into(), ) } fn valid_signable_account(program_id: &Pubkey, account: &AccountInfo, minimum_size: usize) -> bool { - account.is_signer && valid_writable_account(program_id, account, minimum_size) -} - -fn valid_writable_account(program_id: &Pubkey, account: &AccountInfo, minimum_size: usize) -> bool { - account.is_writable + account.is_signer + && account.is_writable && account.owner == program_id && account.data_len() >= minimum_size && Rent::default().is_exempt(account.lamports(), account.data_len()) @@ -355,7 +345,7 @@ fn check_valid_signable_account( ) -> Result<(), ProgramError> { pyth_assert( valid_signable_account(program_id, account, minimum_size), - ProgramError::InvalidArgument, + OracleError::InvalidSignableAccount.into(), ) } From be21613fdf275a93de4fbedd406609ba08436c95 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Tue, 9 Aug 2022 18:13:44 +0000 Subject: [PATCH 16/58] fixed tests that broke because of specific errors --- program/rust/src/tests/test_init_mapping.rs | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/program/rust/src/tests/test_init_mapping.rs b/program/rust/src/tests/test_init_mapping.rs index 6e0e40be5..93e7920d3 100644 --- a/program/rust/src/tests/test_init_mapping.rs +++ b/program/rust/src/tests/test_init_mapping.rs @@ -7,6 +7,7 @@ use crate::c_oracle_header::{ PC_VERSION, }; use crate::deserialize::load_account_as; +use crate::error::OracleError; use crate::rust_oracle::{ clear_account, init_mapping, @@ -103,7 +104,7 @@ fn test_init_mapping() { &[funding_account.clone(), mapping_account.clone()], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidFundingAccount.into()) ); funding_account.is_signer = true; @@ -115,7 +116,7 @@ fn test_init_mapping() { &[funding_account.clone(), mapping_account.clone()], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); mapping_account.is_signer = true; @@ -127,7 +128,7 @@ fn test_init_mapping() { &[funding_account.clone(), mapping_account.clone()], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidFundingAccount.into()) ); funding_account.is_writable = true; @@ -139,7 +140,7 @@ fn test_init_mapping() { &[funding_account.clone(), mapping_account.clone()], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); mapping_account.is_writable = true; @@ -151,7 +152,7 @@ fn test_init_mapping() { &[funding_account.clone(), mapping_account.clone()], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); mapping_account.owner = &program_id; @@ -164,7 +165,7 @@ fn test_init_mapping() { &[funding_account.clone(), mapping_account.clone()], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); mapping_account.data = prev_data; From 3e50c3390f7880ae840a58abf7c9c4c0f43860f2 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 03:30:15 +0000 Subject: [PATCH 17/58] tested permissioned resize --- pyth/tests/test_publish.py | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index 75d4951a1..48c13d983 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -5,7 +5,7 @@ from solana.keypair import Keypair from solana.rpc.api import Client import base64 - +import os import asyncio import json @@ -30,6 +30,18 @@ def get_price_acct(): output = json.loads(output) return output['price_accounts'][0] + def get_key_pair(path_to_file): + key_file = open(path_to_file) + key_data = json.load(key_file) + key_file.close() + + return Keypair.from_secret_key(key_data) + + def get_path_to_pythdir_pair(account_addr): + return os.path.join(pyth_dir, "account_" + account_addr + ".json") + + + def resize_account(price_acc_address): """ given a string with the pubkey of a price accountm it calls the resize instruction of the Oracle on it @@ -50,20 +62,18 @@ def resize_account(price_acc_address): data=data, keys=[ AccountMeta(pubkey=funding_key, is_signer=True, is_writable=True), - AccountMeta(pubkey=price_key, is_signer=False, is_writable=True), + AccountMeta(pubkey=price_key, is_signer=True, is_writable=True), AccountMeta(pubkey=system_key, is_signer=False, is_writable=False), ], program_id = PublicKey(solana_program_deploy), ) txn = Transaction().add(resize_instruction) solana_client = Client("http://localhost:8899") - key_file = open(solana_keygen[1]) - key_data = json.load(key_file) - key_file.close() - sender = Keypair.from_secret_key(key_data) - txn.sign(sender) - solana_client.send_transaction(txn, sender) + sender = get_key_pair(solana_keygen[1]) + path_to_price = get_path_to_pythdir_pair(price_key) + price_key_pair = get_key_pair(path_to_price) + solana_client.send_transaction(txn, sender, price_key_pair) def get_account_size(acc_address): """ From 5941c4e576036f221903eaa2def90951c3a65087 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 03:33:57 +0000 Subject: [PATCH 18/58] added reguired package --- docker/Dockerfile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 3a5bc541a..1cd2bd548 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -27,8 +27,9 @@ RUN apt-get install -qq \ qt5-qmake \ qtbase5-dev-tools \ libqt5websockets5-dev\ - libclang-dev - + libclang-dev\ + python3-pip + # Install jcon-cpp library RUN git clone https://github.com/joncol/jcon-cpp.git /jcon-cpp && cd /jcon-cpp && git checkout 2235654e39c7af505d7158bf996e47e37a23d6e3 && mkdir build && cd build && cmake .. && make -j4 && make install @@ -56,6 +57,8 @@ export PYTHONPATH=\"\${PYTHONPATH:+\$PYTHONPATH:}\${HOME}/pyth-client\"\n\ COPY --chown=pyth:pyth . pyth-client/ +RUN pip3 install solana + # Build off-chain binaries. RUN cd pyth-client && ./scripts/build.sh From 3288adc7a966baf21b3bb90190884af3f56ccc04 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 15:35:16 +0000 Subject: [PATCH 19/58] fixed error in pytest --- pyth/tests/test_publish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index 48c13d983..ad3e23028 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -38,7 +38,7 @@ def get_key_pair(path_to_file): return Keypair.from_secret_key(key_data) def get_path_to_pythdir_pair(account_addr): - return os.path.join(pyth_dir, "account_" + account_addr + ".json") + return os.path.join(pyth_dir, "account_" + str(account_addr) + ".json") From 812015831bbb61c8c1d1d86d4c080ee90490e17f Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 15:41:25 +0000 Subject: [PATCH 20/58] added new line --- program/rust/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index e1062a57b..babf453bd 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -14,4 +14,4 @@ bytemuck = "1.11.0" thiserror = "1.0" [lib] -crate-type = ["cdylib", "lib"] \ No newline at end of file +crate-type = ["cdylib", "lib"] From 7987d89f7111d2bdca01f5aa0863e4b0a965587f Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 15:49:46 +0000 Subject: [PATCH 21/58] removed uneeded borrowing --- program/rust/src/rust_oracle.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index b1f1e80ec..c5c978e5e 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -89,8 +89,8 @@ pub fn upgrade_price_account<'a>( system_program: &AccountInfo<'a>, program_id: &Pubkey, ) -> OracleResult { - check_valid_funding_account(&funding_account_info)?; - check_valid_signable_account(program_id, &price_account_info, size_of::())?; + check_valid_funding_account(funding_account_info)?; + check_valid_signable_account(program_id, price_account_info, size_of::())?; let account_len = price_account_info.try_data_len()?; match account_len { PRICE_T_SIZE => { @@ -130,7 +130,7 @@ pub fn upgrade_price_account<'a>( } fn get_account_type(account: &AccountInfo) -> Result { - let account_type = load_account_as::(&account)?.type_; + let account_type = load_account_as::(account)?.type_; Ok(account_type) } @@ -155,17 +155,17 @@ pub fn update_version( )?; //read account info - let pyth_acc_type = get_account_type(&upgraded_account_info)?; + let pyth_acc_type = get_account_type(upgraded_account_info)?; //Note: currently we do not seem to need to do anything with the version number, // but such logic can be added here, or in the per account type upgrades below match pyth_acc_type { PC_ACCTYPE_PRICE => upgrade_price_account( - &funding_account_info, - &upgraded_account_info, - &system_program, - &program_id, + funding_account_info, + upgraded_account_info, + system_program, + program_id, ), _ => Ok(SUCCESS), } From dea076f2af00b62bfa6403285bcf2911cb40630b Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:08:56 +0000 Subject: [PATCH 22/58] removed extra sleep in test --- pyth/tests/test_publish.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index ad3e23028..21f9fc90d 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -125,7 +125,6 @@ def get_account_size(acc_address): #defined in oracle.h new_account_size = 6176 assert get_account_size(pyth_init_price['LTC']) == new_account_size - time.sleep(20) @@ -158,4 +157,4 @@ def get_account_size(acc_address): after = get_price_acct() assert after['publisher_accounts'][0]['price'] == 100 assert after['publisher_accounts'][0]['conf'] == 1 - assert after['publisher_accounts'][0]['status'] == 'trading' \ No newline at end of file + assert after['publisher_accounts'][0]['status'] == 'trading' From d6e8335d3ddb40688508b26fb48aa1b1be5095dd Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:18:51 +0000 Subject: [PATCH 23/58] refactored lamport transfer into a function --- program/rust/src/rust_oracle.rs | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index c5c978e5e..45c7b8d4d 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -81,6 +81,19 @@ pub fn update_price( } Ok(c_ret_value) } +fn send_lamports<'a>( + from: &AccountInfo<'a>, + to: &AccountInfo<'a>, + system_program: &AccountInfo<'a>, + ammount: u64, +) -> Result<(), ProgramError> { + let transfer_instruction = transfer(from.key, to.key, ammount); + invoke( + &transfer_instruction, + &[from.clone(), to.clone(), system_program.clone()], + )?; + Ok(()) +} ///resize price account and initialize the TimeMachineStructure pub fn upgrade_price_account<'a>( @@ -101,18 +114,11 @@ pub fn upgrade_price_account<'a>( .saturating_sub(price_account_info.lamports()); //transfer lamports if necessary if lamports_needed > 0 { - let transfer_instruction = transfer( - funding_account_info.key, - price_account_info.key, + send_lamports( + funding_account_info, + price_account_info, + system_program, lamports_needed, - ); - invoke( - &transfer_instruction, - &[ - funding_account_info.clone(), - price_account_info.clone(), - system_program.clone(), - ], )?; } //resize From 2ee49dcc9d1be0bffd2ac55abadd0649b82c39f4 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:21:57 +0000 Subject: [PATCH 24/58] changed comment --- program/rust/src/rust_oracle.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 45c7b8d4d..faa289757 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -107,12 +107,11 @@ pub fn upgrade_price_account<'a>( let account_len = price_account_info.try_data_len()?; match account_len { PRICE_T_SIZE => { - //compute the number of lamports needed in the price account to update it + //ensure account is still rent exempt after resizing let rent: Rent = Default::default(); let lamports_needed: u64 = rent .minimum_balance(size_of::()) .saturating_sub(price_account_info.lamports()); - //transfer lamports if necessary if lamports_needed > 0 { send_lamports( funding_account_info, From bb7cdc936a16154c059f4d08209d0f1b0c5c018c Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:23:37 +0000 Subject: [PATCH 25/58] fixed doc string --- pyth/tests/test_publish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index 21f9fc90d..e4dec40de 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -77,7 +77,7 @@ def resize_account(price_acc_address): def get_account_size(acc_address): """ - given a string with the pubkey of an account, resize it + given a string with the pubkey of an account, return its size """ PublicKey(acc_address) solana_client = Client("http://localhost:8899") From af615503e12a30e12f340e37b1976576964832b5 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:24:51 +0000 Subject: [PATCH 26/58] fixed typo --- pyth/tests/test_publish.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index e4dec40de..29c876bc3 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -42,7 +42,7 @@ def get_path_to_pythdir_pair(account_addr): - def resize_account(price_acc_address): + def resize_account(price_account_address): """ given a string with the pubkey of a price accountm it calls the resize instruction of the Oracle on it """ @@ -55,7 +55,7 @@ def resize_account(price_acc_address): layout = Struct("version" / Int32ul, "command" / Int32sl) data = layout.build(dict(version=PROGRAM_VERSION, command=COMMAND_UPD_ACCOUNT)) funding_key = PublicKey(solana_keygen[0]) - price_key = PublicKey(price_acc_address) + price_key = PublicKey(price_account_address) system_key = PublicKey(SYSTEM_PROGRAM) print("program id is", solana_program_deploy) resize_instruction = TransactionInstruction( From 60b02dc5d81b776d60886969098886e009562680 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:36:47 +0000 Subject: [PATCH 27/58] renamed upgrade instruction --- program/rust/src/processor.rs | 4 ++-- program/rust/src/rust_oracle.rs | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/program/rust/src/processor.rs b/program/rust/src/processor.rs index 53c97d1e5..08bde53ae 100644 --- a/program/rust/src/processor.rs +++ b/program/rust/src/processor.rs @@ -27,7 +27,7 @@ use crate::rust_oracle::{ add_product, init_mapping, update_price, - update_version, + upgrade_account, }; use crate::deserialize::load; @@ -60,7 +60,7 @@ pub fn process_instruction( | command_t_e_cmd_upd_price_no_fail_on_error | command_t_e_cmd_agg_price => update_price(program_id, accounts, instruction_data, input), command_t_e_cmd_upd_account_version => { - update_version(program_id, accounts, instruction_data) + upgrade_account(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), diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index faa289757..450d7d92b 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -139,13 +139,13 @@ fn get_account_type(account: &AccountInfo) -> Result { Ok(account_type) } -/// has version number/ account type dependant logic to make sure the given account is compatible -/// with the current version +/// We should call this instruction on any account that needs to be +/// upgraded after an Oracle update /// updates the version number for all accounts, and resizes price accounts /// accounts[0] funding account [signer writable] /// accounts[1] upgradded acount [signer writable] /// accounts [2] system program -pub fn update_version( +pub fn upgrade_account( program_id: &Pubkey, accounts: &[AccountInfo], _instruction_data: &[u8], From 5850ca37e01adc033147846d29571b773da2540d Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 16:52:36 +0000 Subject: [PATCH 28/58] moved try_convert to utils --- program/rust/src/rust_oracle.rs | 11 ++++------- program/rust/src/utils.rs | 7 +++++++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 450d7d92b..e3c30df79 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -49,7 +49,10 @@ use crate::c_oracle_header::{ use crate::error::OracleResult; use crate::OracleError; -use crate::utils::pyth_assert; +use crate::utils::{ + pyth_assert, + try_convert, +}; use super::c_entrypoint_wrapper; @@ -450,9 +453,3 @@ pub fn load_product_account_mut<'a>( pub fn pubkey_assign(target: &mut pc_pub_key_t, source: &[u8]) { unsafe { target.k1_.copy_from_slice(source) } } - -/// Convert `x: T` into a `U`, returning the appropriate `OracleError` if the conversion fails. -fn try_convert>(x: T) -> Result { - // Note: the error here assumes we're only applying this function to integers right now. - U::try_from(x).map_err(|_| OracleError::IntegerCastingError) -} diff --git a/program/rust/src/utils.rs b/program/rust/src/utils.rs index 3df2a1b8c..ce14b6095 100644 --- a/program/rust/src/utils.rs +++ b/program/rust/src/utils.rs @@ -1,3 +1,4 @@ +use crate::error::OracleError; use solana_program::program_error::ProgramError; pub fn pyth_assert(condition: bool, error_code: ProgramError) -> Result<(), ProgramError> { @@ -7,3 +8,9 @@ pub fn pyth_assert(condition: bool, error_code: ProgramError) -> Result<(), Prog Result::Ok(()) } } + +/// Convert `x: T` into a `U`, returning the appropriate `OracleError` if the conversion fails. +pub fn try_convert>(x: T) -> Result { + // Note: the error here assumes we're only applying this function to integers right now. + U::try_from(x).map_err(|_| OracleError::IntegerCastingError) +} From 5f02836d1d0c59a617c0c919da1c9423f363a8d8 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 18:34:36 +0000 Subject: [PATCH 29/58] try_convert for ergonomicity --- program/rust/src/time_machine_types.rs | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index b2ae7565f..8281406c7 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -3,6 +3,7 @@ use crate::c_oracle_header::{ EXTRA_PUBLISHER_SPACE, }; use crate::error::OracleError; +use crate::utils::try_convert; use bytemuck::{ Pod, Zeroable, @@ -77,10 +78,7 @@ pub struct PriceAccountWrapper { impl PriceAccountWrapper { pub fn add_first_price(&mut self) -> Result<(), OracleError> { self.time_machine.add_first_price( - self.price_data - .timestamp_ - .try_into() - .map_err(|_| OracleError::IntegerCastingError)?, + try_convert(self.price_data.timestamp_)?, self.price_data.agg_.price_, self.price_data.agg_.conf_, ) @@ -88,14 +86,8 @@ impl PriceAccountWrapper { pub fn add_price(&mut self) -> Result<(), OracleError> { self.time_machine.add_price( - self.price_data - .timestamp_ - .try_into() - .map_err(|_| OracleError::IntegerCastingError)?, - self.price_data - .prev_timestamp_ - .try_into() - .map_err(|_| OracleError::IntegerCastingError)?, + try_convert(self.price_data.timestamp_)?, + try_convert(self.price_data.prev_timestamp_)?, self.price_data.agg_.price_, self.price_data.prev_price_, self.price_data.agg_.conf_, From cdac025674ae0dede13837df7c5ab25af56e4cd3 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 18:43:08 +0000 Subject: [PATCH 30/58] reordered add_price params --- program/rust/src/time_machine_types.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 8281406c7..19634b6c3 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -22,12 +22,12 @@ pub trait Tracker { ///add a new price to a tracker fn add_price( &mut self, - current_time: u64, prev_time: u64, - current_price: i64, prev_price: i64, - current_conf: u64, prev_conf: u64, + current_time: u64, + current_price: i64, + current_conf: u64, ) -> Result<(), OracleError>; } @@ -52,12 +52,12 @@ impl Tracker for TimeMachineWrapper { } fn add_price( &mut self, - _current_time: u64, _prev_time: u64, - _current_price: i64, _prev_price: i64, - _current_conf: u64, _prev_conf: u64, + _current_time: u64, + _current_price: i64, + _current_conf: u64, ) -> Result<(), OracleError> { msg!("implement me"); Ok(()) @@ -86,12 +86,12 @@ impl PriceAccountWrapper { pub fn add_price(&mut self) -> Result<(), OracleError> { self.time_machine.add_price( - try_convert(self.price_data.timestamp_)?, try_convert(self.price_data.prev_timestamp_)?, - self.price_data.agg_.price_, self.price_data.prev_price_, - self.price_data.agg_.conf_, self.price_data.prev_conf_, + try_convert(self.price_data.timestamp_)?, + self.price_data.agg_.price_, + self.price_data.agg_.conf_, ) } } From 5f20d65bc19499f347231e7c48b26e82803c74ba Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 19:30:14 +0000 Subject: [PATCH 31/58] better interface for time machine --- program/rust/src/rust_oracle.rs | 4 +- program/rust/src/time_machine_types.rs | 53 ++++++++++++++++---------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index e3c30df79..6bb676f39 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -79,7 +79,7 @@ pub fn update_price( let c_ret_value = c_entrypoint_wrapper(input)?; if c_ret_value == SUCCESSFULLY_UPDATED_AGGREGATE { let mut price_account = load_account_as_mut::(price_account_info)?; - price_account.add_price()?; + price_account.add_price_to_time_machine()?; msg!("updated tracker!"); } Ok(c_ret_value) @@ -129,7 +129,7 @@ pub fn upgrade_price_account<'a>( price_account_info.realloc(size_of::(), false)?; //update twap_tracker let mut price_account = load_account_as_mut::(price_account_info)?; - price_account.add_first_price()?; + price_account.initialize_time_machine()?; Ok(SUCCESS) } PRICE_ACCOUNT_SIZE => Ok(SUCCESS), diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 19634b6c3..e2d0d4945 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -1,6 +1,7 @@ use crate::c_oracle_header::{ pc_price_t, EXTRA_PUBLISHER_SPACE, + PC_STATUS_TRADING, }; use crate::error::OracleError; use crate::utils::try_convert; @@ -11,13 +12,11 @@ use bytemuck::{ use solana_program::msg; pub trait Tracker { - /// add the first price to a zero initialized tracker - fn add_first_price( - &mut self, - current_time: u64, - current_price: i64, - current_conf: u64, - ) -> Result<(), OracleError>; + /// sets a tracker to stract tracking + /// from the given price time + /// Assumes that all entries in it + /// are currently invalid + fn initialize(&mut self, last_valid_price_time: u64) -> Result<(), OracleError>; ///add a new price to a tracker fn add_price( @@ -41,12 +40,12 @@ pub struct TimeMachineWrapper { } impl Tracker for TimeMachineWrapper { - fn add_first_price( - &mut self, - _current_time: u64, - _current_price: i64, - _current_conf: u64, - ) -> Result<(), OracleError> { + /// sets a tracker to stract tracking + /// from the given price time + /// Assumes that all entries in it + /// are currently invalid + /// Can be called multiple times as long as these conditions are valid + fn initialize(&mut self, _last_valid_price_time: u64) -> Result<(), OracleError> { msg!("implement me"); Ok(()) } @@ -76,15 +75,29 @@ pub struct PriceAccountWrapper { pub time_machine: TimeMachineWrapper, } impl PriceAccountWrapper { - pub fn add_first_price(&mut self) -> Result<(), OracleError> { - self.time_machine.add_first_price( - try_convert(self.price_data.timestamp_)?, - self.price_data.agg_.price_, - self.price_data.agg_.conf_, - ) + ///Set the time_machine to start tracking from the time of the most recent trade + pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { + let last_valid_price_time = if self.price_data.agg_.status_ == PC_STATUS_TRADING { + self.price_data.timestamp_ + } else { + self.price_data.prev_timestamp_ + }; + self.time_machine + .initialize(try_convert(last_valid_price_time)?) } - pub fn add_price(&mut self) -> Result<(), OracleError> { + pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { + //If the current price is not certain, ignore it + if self.price_data.agg_.status_ != PC_STATUS_TRADING { + return Ok(()); + } + //If this is the first price, initialize again instead + if self.price_data.prev_timestamp_ == 0 { + return self.initialize_time_machine(); + } + // Otherwise, we know that both current and previous price are valid + //and that the time_machine must have been initialized either while adding + //the previous price or while resizing, so we can go ahead and start tracking self.time_machine.add_price( try_convert(self.price_data.prev_timestamp_)?, self.price_data.prev_price_, From 0f7cc35a986f72b1cba3331c15bc41a58a375aed Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 19:43:52 +0000 Subject: [PATCH 32/58] renamed functions --- program/rust/src/rust_oracle.rs | 2 +- program/rust/src/time_machine_types.rs | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 14 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 6bb676f39..55a96b6ed 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -129,7 +129,7 @@ pub fn upgrade_price_account<'a>( price_account_info.realloc(size_of::(), false)?; //update twap_tracker let mut price_account = load_account_as_mut::(price_account_info)?; - price_account.initialize_time_machine()?; + price_account.invalidate_current_time_machine_entries()?; Ok(SUCCESS) } PRICE_ACCOUNT_SIZE => Ok(SUCCESS), diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index e2d0d4945..0990a0360 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -12,11 +12,10 @@ use bytemuck::{ use solana_program::msg; pub trait Tracker { - /// sets a tracker to stract tracking - /// from the given price time - /// Assumes that all entries in it - /// are currently invalid - fn initialize(&mut self, last_valid_price_time: u64) -> Result<(), OracleError>; + /// Makes the tracker invalidate the entry it's currentrly at + /// Must be used when we start tracking so that we do not give a "valid" + /// entry that is not completely covered by our prices + fn invalidate_current_entry(&mut self, last_valid_price_time: u64) -> Result<(), OracleError>; ///add a new price to a tracker fn add_price( @@ -45,7 +44,7 @@ impl Tracker for TimeMachineWrapper { /// Assumes that all entries in it /// are currently invalid /// Can be called multiple times as long as these conditions are valid - fn initialize(&mut self, _last_valid_price_time: u64) -> Result<(), OracleError> { + fn invalidate_current_entry(&mut self, _last_valid_price_time: u64) -> Result<(), OracleError> { msg!("implement me"); Ok(()) } @@ -75,15 +74,14 @@ pub struct PriceAccountWrapper { pub time_machine: TimeMachineWrapper, } impl PriceAccountWrapper { - ///Set the time_machine to start tracking from the time of the most recent trade - pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { + pub fn invalidate_current_time_machine_entries(&mut self) -> Result<(), OracleError> { let last_valid_price_time = if self.price_data.agg_.status_ == PC_STATUS_TRADING { self.price_data.timestamp_ } else { self.price_data.prev_timestamp_ }; self.time_machine - .initialize(try_convert(last_valid_price_time)?) + .invalidate_current_entry(try_convert(last_valid_price_time)?) } pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { @@ -91,13 +89,14 @@ impl PriceAccountWrapper { if self.price_data.agg_.status_ != PC_STATUS_TRADING { return Ok(()); } - //If this is the first price, initialize again instead + //If this is the first price, make sure to invalidate the current entry + //(as we will start tracking with the next price) if self.price_data.prev_timestamp_ == 0 { - return self.initialize_time_machine(); + return self.invalidate_current_time_machine_entries(); } // Otherwise, we know that both current and previous price are valid - //and that the time_machine must have been initialized either while adding - //the previous price or while resizing, so we can go ahead and start tracking + //and that we have invalidated the current entrym either while resizing + //or while adding the previous price. self.time_machine.add_price( try_convert(self.price_data.prev_timestamp_)?, self.price_data.prev_price_, From 705cf9bf4addda38efefc0924ce983247dcc752d Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 19:49:34 +0000 Subject: [PATCH 33/58] fixed merging errors --- program/rust/src/rust_oracle.rs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index e85de741a..ee171bc8d 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -40,6 +40,7 @@ use crate::c_oracle_header::{ pc_prod_t, pc_pub_key_t, PythAccount, + PC_ACCTYPE_PRICE, PC_COMP_SIZE, PC_MAGIC, PC_MAP_TABLE_SIZE, @@ -564,4 +565,17 @@ pub fn pubkey_is_zero(key: &pc_pub_key_t) -> bool { pub fn pubkey_equal(target: &pc_pub_key_t, source: &[u8]) -> bool { unsafe { target.k1_ == *source } } - +/// Read a `pc_str_t` from the beginning of `source`. Returns a slice of `source` containing +/// the bytes of the `pc_str_t`. +pub fn read_pc_str_t(source: &[u8]) -> Result<&[u8], ProgramError> { + if source.is_empty() { + Err(ProgramError::InvalidArgument) + } else { + let tag_len: usize = try_convert(source[0])?; + if tag_len + 1 > source.len() { + Err(ProgramError::InvalidArgument) + } else { + Ok(&source[..(1 + tag_len)]) + } + } +} From dce35e70b20e6295251680bd9bc4d5b00649de8f Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Wed, 10 Aug 2022 19:59:28 +0000 Subject: [PATCH 34/58] more merge errors --- program/rust/src/tests/test_add_price.rs | 3 ++- program/rust/src/tests/test_add_product.rs | 3 ++- program/rust/src/tests/test_add_publisher.rs | 3 ++- program/rust/src/tests/test_upd_product.rs | 2 +- 4 files changed, 7 insertions(+), 4 deletions(-) diff --git a/program/rust/src/tests/test_add_price.rs b/program/rust/src/tests/test_add_price.rs index dbb8e39fb..098680aa3 100644 --- a/program/rust/src/tests/test_add_price.rs +++ b/program/rust/src/tests/test_add_price.rs @@ -1,3 +1,4 @@ +use crate::error::OracleError; use crate::tests::test_utils::AccountSetup; use bytemuck::bytes_of; use solana_program::program_error::ProgramError; @@ -195,7 +196,7 @@ fn test_add_price() { ], instruction_data_add_price ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); // Fresh product account diff --git a/program/rust/src/tests/test_add_product.rs b/program/rust/src/tests/test_add_product.rs index 2aa629691..7a2241552 100644 --- a/program/rust/src/tests/test_add_product.rs +++ b/program/rust/src/tests/test_add_product.rs @@ -1,5 +1,6 @@ use std::mem::size_of; +use crate::error::OracleError; use crate::tests::test_utils::AccountSetup; use bytemuck::bytes_of; use solana_program::account_info::AccountInfo; @@ -123,7 +124,7 @@ fn test_add_product() { ], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); // test fill up of mapping table diff --git a/program/rust/src/tests/test_add_publisher.rs b/program/rust/src/tests/test_add_publisher.rs index 9d0591f34..b8d573c76 100644 --- a/program/rust/src/tests/test_add_publisher.rs +++ b/program/rust/src/tests/test_add_publisher.rs @@ -23,6 +23,7 @@ use crate::rust_oracle::{ load_checked, pubkey_equal, }; +use crate::OracleError; #[test] fn test_add_publisher() { @@ -53,7 +54,7 @@ fn test_add_publisher() { &[funding_account.clone(), price_account.clone(),], instruction_data ), - Err(ProgramError::InvalidArgument) + Err(OracleError::InvalidSignableAccount.into()) ); // Now give the price account enough lamports to be rent exempt diff --git a/program/rust/src/tests/test_upd_product.rs b/program/rust/src/tests/test_upd_product.rs index 1fda8445f..21ec8e288 100644 --- a/program/rust/src/tests/test_upd_product.rs +++ b/program/rust/src/tests/test_upd_product.rs @@ -1,6 +1,7 @@ use std::mem::size_of; use crate::tests::test_utils::AccountSetup; +use crate::utils::try_convert; use solana_program::account_info::AccountInfo; use solana_program::program_error::ProgramError; use solana_program::pubkey::Pubkey; @@ -19,7 +20,6 @@ use crate::rust_oracle::{ initialize_checked, load_checked, read_pc_str_t, - try_convert, upd_product, }; From e50f644d654a925270153aeda8f950635150f844 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 15:04:47 +0000 Subject: [PATCH 35/58] removed implmentation details for a later PR --- program/rust/src/rust_oracle.rs | 9 +-- program/rust/src/time_machine_types.rs | 77 ++------------------------ program/rust/src/utils.rs | 2 +- 3 files changed, 9 insertions(+), 79 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index ee171bc8d..49f12d6e7 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -57,13 +57,10 @@ use crate::deserialize::{ use crate::error::OracleResult; use crate::OracleError; -use crate::utils::{ - pyth_assert, - try_convert, -}; +use crate::utils::pyth_assert; use super::c_entrypoint_wrapper; - +use crate::utils::try_convert; const PRICE_T_SIZE: usize = size_of::(); const PRICE_ACCOUNT_SIZE: usize = size_of::(); @@ -137,7 +134,7 @@ pub fn upgrade_price_account<'a>( price_account_info.realloc(size_of::(), false)?; //update twap_tracker let mut price_account = load_account_as_mut::(price_account_info)?; - price_account.invalidate_current_time_machine_entries()?; + price_account.initialize_time_machine()?; Ok(SUCCESS) } PRICE_ACCOUNT_SIZE => Ok(SUCCESS), diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 0990a0360..90efc1625 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -1,34 +1,14 @@ use crate::c_oracle_header::{ pc_price_t, EXTRA_PUBLISHER_SPACE, - PC_STATUS_TRADING, }; use crate::error::OracleError; -use crate::utils::try_convert; use bytemuck::{ Pod, Zeroable, }; use solana_program::msg; -pub trait Tracker { - /// Makes the tracker invalidate the entry it's currentrly at - /// Must be used when we start tracking so that we do not give a "valid" - /// entry that is not completely covered by our prices - fn invalidate_current_entry(&mut self, last_valid_price_time: u64) -> Result<(), OracleError>; - - ///add a new price to a tracker - fn add_price( - &mut self, - prev_time: u64, - prev_price: i64, - prev_conf: u64, - current_time: u64, - current_price: i64, - current_conf: u64, - ) -> Result<(), OracleError>; -} - #[derive(Debug, Clone, Copy)] #[repr(C)] /// this wraps multiple SMA and tick trackers, and includes all the state @@ -38,30 +18,6 @@ pub struct TimeMachineWrapper { place_holder: [u8; 1864], } -impl Tracker for TimeMachineWrapper { - /// sets a tracker to stract tracking - /// from the given price time - /// Assumes that all entries in it - /// are currently invalid - /// Can be called multiple times as long as these conditions are valid - fn invalidate_current_entry(&mut self, _last_valid_price_time: u64) -> Result<(), OracleError> { - msg!("implement me"); - Ok(()) - } - fn add_price( - &mut self, - _prev_time: u64, - _prev_price: i64, - _prev_conf: u64, - _current_time: u64, - _current_price: i64, - _current_conf: u64, - ) -> Result<(), OracleError> { - msg!("implement me"); - Ok(()) - } -} - #[derive(Copy, Clone)] #[repr(C)] /// wraps everything stored in a price account @@ -74,37 +30,14 @@ pub struct PriceAccountWrapper { pub time_machine: TimeMachineWrapper, } impl PriceAccountWrapper { - pub fn invalidate_current_time_machine_entries(&mut self) -> Result<(), OracleError> { - let last_valid_price_time = if self.price_data.agg_.status_ == PC_STATUS_TRADING { - self.price_data.timestamp_ - } else { - self.price_data.prev_timestamp_ - }; - self.time_machine - .invalidate_current_entry(try_convert(last_valid_price_time)?) + pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { + msg!("implement me"); + Ok(()) } pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { - //If the current price is not certain, ignore it - if self.price_data.agg_.status_ != PC_STATUS_TRADING { - return Ok(()); - } - //If this is the first price, make sure to invalidate the current entry - //(as we will start tracking with the next price) - if self.price_data.prev_timestamp_ == 0 { - return self.invalidate_current_time_machine_entries(); - } - // Otherwise, we know that both current and previous price are valid - //and that we have invalidated the current entrym either while resizing - //or while adding the previous price. - self.time_machine.add_price( - try_convert(self.price_data.prev_timestamp_)?, - self.price_data.prev_price_, - self.price_data.prev_conf_, - try_convert(self.price_data.timestamp_)?, - self.price_data.agg_.price_, - self.price_data.agg_.conf_, - ) + msg!("implement me"); + Ok(()) } } diff --git a/program/rust/src/utils.rs b/program/rust/src/utils.rs index ce14b6095..5c6be2990 100644 --- a/program/rust/src/utils.rs +++ b/program/rust/src/utils.rs @@ -1,4 +1,4 @@ -use crate::error::OracleError; +use crate::OracleError; use solana_program::program_error::ProgramError; pub fn pyth_assert(condition: bool, error_code: ProgramError) -> Result<(), ProgramError> { From cd4442c445794d1b6826cdb9a9cb64d46ce58060 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 15:21:10 +0000 Subject: [PATCH 36/58] moved try_convert back to rust orale to minimize differences from main --- program/rust/src/rust_oracle.rs | 8 +++++++- program/rust/src/tests/test_upd_product.rs | 1 - program/rust/src/utils.rs | 7 ------- 3 files changed, 7 insertions(+), 9 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 049187d5c..d8e0c9885 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -60,7 +60,6 @@ use crate::OracleError; use crate::utils::pyth_assert; use super::c_entrypoint_wrapper; -use crate::utils::try_convert; const PRICE_T_SIZE: usize = size_of::(); const PRICE_ACCOUNT_SIZE: usize = size_of::(); @@ -565,6 +564,13 @@ pub fn pubkey_is_zero(key: &pc_pub_key_t) -> bool { pub fn pubkey_equal(target: &pc_pub_key_t, source: &[u8]) -> bool { unsafe { target.k1_ == *source } } + +/// Convert `x: T` into a `U`, returning the appropriate `OracleError` if the conversion fails. +pub fn try_convert>(x: T) -> Result { + // Note: the error here assumes we're only applying this function to integers right now. + U::try_from(x).map_err(|_| OracleError::IntegerCastingError) +} + /// Read a `pc_str_t` from the beginning of `source`. Returns a slice of `source` containing /// the bytes of the `pc_str_t`. pub fn read_pc_str_t(source: &[u8]) -> Result<&[u8], ProgramError> { diff --git a/program/rust/src/tests/test_upd_product.rs b/program/rust/src/tests/test_upd_product.rs index c09d0da93..edde586e3 100644 --- a/program/rust/src/tests/test_upd_product.rs +++ b/program/rust/src/tests/test_upd_product.rs @@ -2,7 +2,6 @@ use std::mem::size_of; use crate::rust_oracle::try_convert; use crate::tests::test_utils::AccountSetup; -use crate::utils::try_convert; use solana_program::account_info::AccountInfo; use solana_program::program_error::ProgramError; use solana_program::pubkey::Pubkey; diff --git a/program/rust/src/utils.rs b/program/rust/src/utils.rs index 5c6be2990..3df2a1b8c 100644 --- a/program/rust/src/utils.rs +++ b/program/rust/src/utils.rs @@ -1,4 +1,3 @@ -use crate::OracleError; use solana_program::program_error::ProgramError; pub fn pyth_assert(condition: bool, error_code: ProgramError) -> Result<(), ProgramError> { @@ -8,9 +7,3 @@ pub fn pyth_assert(condition: bool, error_code: ProgramError) -> Result<(), Prog Result::Ok(()) } } - -/// Convert `x: T` into a `U`, returning the appropriate `OracleError` if the conversion fails. -pub fn try_convert>(x: T) -> Result { - // Note: the error here assumes we're only applying this function to integers right now. - U::try_from(x).map_err(|_| OracleError::IntegerCastingError) -} From fff865342eb542e6a618fd699e3d8b87c46a3910 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:02:38 +0000 Subject: [PATCH 37/58] changed upgrade instruction to resize --- program/c/src/oracle/oracle.h | 6 +-- program/rust/src/log.rs | 4 +- program/rust/src/processor.rs | 8 +-- program/rust/src/rust_oracle.rs | 71 ++++++++------------------ program/rust/src/time_machine_types.rs | 8 +++ 5 files changed, 38 insertions(+), 59 deletions(-) diff --git a/program/c/src/oracle/oracle.h b/program/c/src/oracle/oracle.h index a85e0632c..db19384aa 100644 --- a/program/c/src/oracle/oracle.h +++ b/program/c/src/oracle/oracle.h @@ -270,11 +270,11 @@ typedef enum { // key[2] sysvar_clock account [readable] e_cmd_upd_price_no_fail_on_error, - // performs migation logic on the upgraded account. (resizes price accounts) + // resizes a price accpunt so that it fits the Time Machine // key[0] funding account [signer writable] - // key[1] upgraded account [writable] + // key[1] price account [Signer writable] // key[2] system program [readable] - e_cmd_upd_account_version, + e_cmd_resize_price_account, } command_t; typedef struct cmd_hdr diff --git a/program/rust/src/log.rs b/program/rust/src/log.rs index d04133db0..3128419f8 100644 --- a/program/rust/src/log.rs +++ b/program/rust/src/log.rs @@ -86,9 +86,9 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu msg!("UpdateProduct"); } - command_t_e_cmd_upd_account_version => { + command_t_e_cmd_resize_price_account => { //accounts[1] is the updated account - msg!("UpdateAccount: {}", accounts[1].key); + msg!("ResizePriceAccount: {}", accounts[1].key); } _ => { msg!("UnrecognizedInstruction"); diff --git a/program/rust/src/processor.rs b/program/rust/src/processor.rs index b84d4e68b..11f7370f7 100644 --- a/program/rust/src/processor.rs +++ b/program/rust/src/processor.rs @@ -11,8 +11,8 @@ use crate::c_oracle_header::{ command_t_e_cmd_add_publisher, command_t_e_cmd_agg_price, command_t_e_cmd_init_mapping, + command_t_e_cmd_resize_price_account, command_t_e_cmd_set_min_pub, - command_t_e_cmd_upd_account_version, command_t_e_cmd_upd_price, command_t_e_cmd_upd_price_no_fail_on_error, command_t_e_cmd_upd_product, @@ -29,10 +29,10 @@ use crate::rust_oracle::{ add_product, add_publisher, init_mapping, + resize_price_account, set_min_pub, upd_product, update_price, - upgrade_account, }; ///dispatch to the right instruction in the oracle @@ -59,8 +59,8 @@ pub fn process_instruction( command_t_e_cmd_upd_price | command_t_e_cmd_upd_price_no_fail_on_error | command_t_e_cmd_agg_price => update_price(program_id, accounts, instruction_data, input), - command_t_e_cmd_upd_account_version => { - upgrade_account(program_id, accounts, instruction_data) + command_t_e_cmd_resize_price_account => { + resize_price_account(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), diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index d8e0c9885..f26e03b02 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -40,13 +40,13 @@ use crate::c_oracle_header::{ pc_prod_t, pc_pub_key_t, PythAccount, - PC_ACCTYPE_PRICE, PC_COMP_SIZE, PC_MAGIC, PC_MAP_TABLE_SIZE, PC_MAX_NUM_DECIMALS, PC_PROD_ACC_SIZE, PC_PTYPE_UNKNOWN, + PC_VERSION, SUCCESSFULLY_UPDATED_AGGREGATE, }; use crate::deserialize::{ @@ -102,15 +102,25 @@ fn send_lamports<'a>( Ok(()) } -///resize price account and initialize the TimeMachineStructure -pub fn upgrade_price_account<'a>( - funding_account_info: &AccountInfo<'a>, - price_account_info: &AccountInfo<'a>, - system_program: &AccountInfo<'a>, +/// resizes a price accpunt so that it fits the Time Machine +/// key[0] funding account [signer writable] +/// key[1] price account [Signer writable] +/// key[2] system program [readable] +pub fn resize_price_account( program_id: &Pubkey, + accounts: &[AccountInfo], + _instruction_data: &[u8], ) -> OracleResult { + let funding_account_info = &accounts[0]; + let price_account_info = &accounts[1]; + let system_program = &accounts[2]; + check_valid_funding_account(funding_account_info)?; check_valid_signable_account(program_id, price_account_info, size_of::())?; + pyth_assert( + check_id(system_program.key), + OracleError::InvalidSystemAccount.into(), + )?; let account_len = price_account_info.try_data_len()?; match account_len { PRICE_T_SIZE => { @@ -131,8 +141,11 @@ pub fn upgrade_price_account<'a>( //we do not need to zero initialize since this is the first time this memory //is allocated price_account_info.realloc(size_of::(), false)?; - //update twap_tracker - let mut price_account = load_account_as_mut::(price_account_info)?; + //The load below would fail if the account was not a price account, reverting the whole + // transaction + let mut price_account = + load_checked::(price_account_info, PC_VERSION)?; + //Initialize Time Machine price_account.initialize_time_machine()?; Ok(SUCCESS) } @@ -141,48 +154,6 @@ pub fn upgrade_price_account<'a>( } } -fn get_account_type(account: &AccountInfo) -> Result { - let account_type = load_account_as::(account)?.type_; - Ok(account_type) -} - -/// We should call this instruction on any account that needs to be -/// upgraded after an Oracle update -/// updates the version number for all accounts, and resizes price accounts -/// accounts[0] funding account [signer writable] -/// accounts[1] upgradded acount [signer writable] -/// accounts [2] system program -pub fn upgrade_account( - program_id: &Pubkey, - accounts: &[AccountInfo], - _instruction_data: &[u8], -) -> OracleResult { - let funding_account_info = &accounts[0]; - let upgraded_account_info = &accounts[1]; - let system_program = &accounts[2]; - - pyth_assert( - check_id(system_program.key), - OracleError::InvalidSystemAccount.into(), - )?; - - //read account info - let pyth_acc_type = get_account_type(upgraded_account_info)?; - - //Note: currently we do not seem to need to do anything with the version number, - // but such logic can be added here, or in the per account type upgrades below - - match pyth_acc_type { - PC_ACCTYPE_PRICE => upgrade_price_account( - funding_account_info, - upgraded_account_info, - system_program, - program_id, - ), - _ => Ok(SUCCESS), - } -} - /// initialize the first mapping account in a new linked-list of mapping accounts /// accounts[0] funding account [signer writable] diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 90efc1625..6ff8e67d2 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -1,6 +1,8 @@ use crate::c_oracle_header::{ pc_price_t, + PythAccount, EXTRA_PUBLISHER_SPACE, + PC_ACCTYPE_PRICE, }; use crate::error::OracleError; use bytemuck::{ @@ -8,6 +10,8 @@ use bytemuck::{ Zeroable, }; use solana_program::msg; +use std::mem::size_of; + #[derive(Debug, Clone, Copy)] #[repr(C)] @@ -49,6 +53,10 @@ unsafe impl Zeroable for PriceAccountWrapper { unsafe impl Pod for PriceAccountWrapper { } +impl PythAccount for PriceAccountWrapper { + const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; + const INITIAL_SIZE: u32 = size_of::() as u32; +} #[cfg(test)] pub mod tests { From fbc394f3957c5a6cafa44f3ea659a04d8ca72a2e Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:07:05 +0000 Subject: [PATCH 38/58] read accounts using the same pattern as other instructions --- program/rust/src/rust_oracle.rs | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index f26e03b02..7e4f1bb70 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -111,9 +111,10 @@ pub fn resize_price_account( accounts: &[AccountInfo], _instruction_data: &[u8], ) -> OracleResult { - let funding_account_info = &accounts[0]; - let price_account_info = &accounts[1]; - let system_program = &accounts[2]; + let [funding_account_info, price_account_info, system_program] = match accounts { + [x, y, z] => Ok([x, y, z]), + _ => Err(ProgramError::InvalidArgument), + }?; check_valid_funding_account(funding_account_info)?; check_valid_signable_account(program_id, price_account_info, size_of::())?; From 33e04a171e94882c89c87a6ab3ef960378426730 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:10:48 +0000 Subject: [PATCH 39/58] added a new line at the end of the docker file --- docker/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 1cd2bd548..62e3dec84 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -73,4 +73,4 @@ RUN cd pyth-client && ./scripts/build-bpf.sh . RUN /bin/bash -l -c "pytest-3 --pyargs pyth" ENTRYPOINT [] -CMD [] \ No newline at end of file +CMD [] From fb01b27f7d1a30f9f9dbad6d6d55b0d4001cf6c8 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:17:35 +0000 Subject: [PATCH 40/58] removed resizing message --- program/rust/src/rust_oracle.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 7e4f1bb70..2a19ec2f7 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -77,7 +77,6 @@ pub fn update_price( if account_len != PRICE_T_SIZE { return Err(ProgramError::InvalidArgument); } - msg!("Please resize the account to allow for SMA tracking!"); return c_entrypoint_wrapper(input); } let c_ret_value = c_entrypoint_wrapper(input)?; From 1af547230d8a62fca28b0e9d638025f080c3be6e Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:25:24 +0000 Subject: [PATCH 41/58] fixed typo --- program/rust/src/rust_oracle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 2a19ec2f7..cc03f1924 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -91,9 +91,9 @@ fn send_lamports<'a>( from: &AccountInfo<'a>, to: &AccountInfo<'a>, system_program: &AccountInfo<'a>, - ammount: u64, + amount: u64, ) -> Result<(), ProgramError> { - let transfer_instruction = transfer(from.key, to.key, ammount); + let transfer_instruction = transfer(from.key, to.key, amount); invoke( &transfer_instruction, &[from.clone(), to.clone(), system_program.clone()], From 24476a11096859d5a11902b608d53ad4a12f6bbd Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:34:24 +0000 Subject: [PATCH 42/58] match instead of if in updatea_price --- program/rust/src/rust_oracle.rs | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index cc03f1924..5281ff667 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -11,7 +11,6 @@ use bytemuck::{ }; use solana_program::account_info::AccountInfo; use solana_program::entrypoint::SUCCESS; -use solana_program::msg; use solana_program::program_error::ProgramError; use solana_program::program_memory::{ sol_memcpy, @@ -73,19 +72,19 @@ pub fn update_price( ) -> OracleResult { let price_account_info = &accounts[1]; let account_len = price_account_info.try_data_len()?; - if account_len < PRICE_ACCOUNT_SIZE { - if account_len != PRICE_T_SIZE { - return Err(ProgramError::InvalidArgument); + match account_len { + PRICE_T_SIZE => c_entrypoint_wrapper(input), + PRICE_ACCOUNT_SIZE => { + let c_ret_value = c_entrypoint_wrapper(input)?; + if c_ret_value == SUCCESSFULLY_UPDATED_AGGREGATE { + let mut price_account = + load_account_as_mut::(price_account_info)?; + price_account.add_price_to_time_machine()?; + } + Ok(c_ret_value) } - return c_entrypoint_wrapper(input); - } - let c_ret_value = c_entrypoint_wrapper(input)?; - if c_ret_value == SUCCESSFULLY_UPDATED_AGGREGATE { - let mut price_account = load_account_as_mut::(price_account_info)?; - price_account.add_price_to_time_machine()?; - msg!("updated tracker!"); + _ => Err(ProgramError::InvalidArgument), } - Ok(c_ret_value) } fn send_lamports<'a>( from: &AccountInfo<'a>, From 67dab4146774ae53c2ab60ec33efbf9bb015bfdd Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 16:37:14 +0000 Subject: [PATCH 43/58] new style of reading accounts --- program/rust/src/rust_oracle.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 5281ff667..21d298021 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -70,7 +70,11 @@ pub fn update_price( _instruction_data: &[u8], input: *mut u8, ) -> OracleResult { - let price_account_info = &accounts[1]; + let [_funding_account_info, price_account_info] = match accounts { + [x, y] => Ok([x, y]), + _ => Err(ProgramError::InvalidArgument), + }?; + //accounts checks happen in c_entrypoint let account_len = price_account_info.try_data_len()?; match account_len { PRICE_T_SIZE => c_entrypoint_wrapper(input), From 89a14537e2008964959158d82fa22de61e0396d7 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 18:03:44 +0000 Subject: [PATCH 44/58] resolved non deterministic feepayer issue --- pyth/tests/test_publish.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index 29c876bc3..35e3b8ca5 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -68,6 +68,8 @@ def resize_account(price_account_address): program_id = PublicKey(solana_program_deploy), ) txn = Transaction().add(resize_instruction) + txn.fee_payer = funding_key + solana_client = Client("http://localhost:8899") sender = get_key_pair(solana_keygen[1]) From b5d0b243d39cf9670bee53102fa98f97eba615fd Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 18:26:10 +0000 Subject: [PATCH 45/58] added sysvar account to add_price --- program/rust/src/rust_oracle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 21d298021..9db7f7c9a 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -70,8 +70,8 @@ pub fn update_price( _instruction_data: &[u8], input: *mut u8, ) -> OracleResult { - let [_funding_account_info, price_account_info] = match accounts { - [x, y] => Ok([x, y]), + let [_funding_account_info, price_account_info, _sysvar_clock] = match accounts { + [x, y, z] => Ok([x, y, z]), _ => Err(ProgramError::InvalidArgument), }?; //accounts checks happen in c_entrypoint From fdb1be203b479163ae8433333550fad819d9bf4d Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 18:39:09 +0000 Subject: [PATCH 46/58] with as syntax instead of closing --- pyth/tests/test_publish.py | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index 35e3b8ca5..ee1b57b88 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -31,10 +31,8 @@ def get_price_acct(): return output['price_accounts'][0] def get_key_pair(path_to_file): - key_file = open(path_to_file) - key_data = json.load(key_file) - key_file.close() - + with open(path_to_file) as key_file: + key_data = json.load(key_file) return Keypair.from_secret_key(key_data) def get_path_to_pythdir_pair(account_addr): @@ -57,7 +55,6 @@ def resize_account(price_account_address): funding_key = PublicKey(solana_keygen[0]) price_key = PublicKey(price_account_address) system_key = PublicKey(SYSTEM_PROGRAM) - print("program id is", solana_program_deploy) resize_instruction = TransactionInstruction( data=data, keys=[ @@ -69,13 +66,11 @@ def resize_account(price_account_address): ) txn = Transaction().add(resize_instruction) txn.fee_payer = funding_key - - solana_client = Client("http://localhost:8899") - sender = get_key_pair(solana_keygen[1]) path_to_price = get_path_to_pythdir_pair(price_key) price_key_pair = get_key_pair(path_to_price) - solana_client.send_transaction(txn, sender, price_key_pair) + with Client("http://localhost:8899") as solana_client: + solana_client.send_transaction(txn, sender, price_key_pair) def get_account_size(acc_address): """ From 7fad134fab209d714ae1f36237c1a19a13dfc097 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 19:02:31 +0000 Subject: [PATCH 47/58] Client has no _enter, can not use with as --- pyth/tests/test_publish.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index ee1b57b88..49fea2130 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -69,8 +69,8 @@ def resize_account(price_account_address): sender = get_key_pair(solana_keygen[1]) path_to_price = get_path_to_pythdir_pair(price_key) price_key_pair = get_key_pair(path_to_price) - with Client("http://localhost:8899") as solana_client: - solana_client.send_transaction(txn, sender, price_key_pair) + solana_client = Client("http://localhost:8899") + solana_client.send_transaction(txn, sender, price_key_pair) def get_account_size(acc_address): """ From 40541437cc7f63ee77c2ffb4fc929f477c8b5e7b Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:05:33 +0000 Subject: [PATCH 48/58] fixed typo --- program/c/src/oracle/oracle.h | 2 +- program/rust/src/rust_oracle.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/program/c/src/oracle/oracle.h b/program/c/src/oracle/oracle.h index db19384aa..3db9b8b09 100644 --- a/program/c/src/oracle/oracle.h +++ b/program/c/src/oracle/oracle.h @@ -270,7 +270,7 @@ typedef enum { // key[2] sysvar_clock account [readable] e_cmd_upd_price_no_fail_on_error, - // resizes a price accpunt so that it fits the Time Machine + // resizes a price account so that it fits the Time Machine // key[0] funding account [signer writable] // key[1] price account [Signer writable] // key[2] system program [readable] diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 9db7f7c9a..278988a04 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -104,7 +104,7 @@ fn send_lamports<'a>( Ok(()) } -/// resizes a price accpunt so that it fits the Time Machine +/// resizes a price account so that it fits the Time Machine /// key[0] funding account [signer writable] /// key[1] price account [Signer writable] /// key[2] system program [readable] From 3fae498d52cb24465797d137acfdca90b80c630c Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:07:18 +0000 Subject: [PATCH 49/58] fixed update_price --- program/rust/src/rust_oracle.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 278988a04..027c09e4c 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -72,6 +72,7 @@ pub fn update_price( ) -> OracleResult { let [_funding_account_info, price_account_info, _sysvar_clock] = match accounts { [x, y, z] => Ok([x, y, z]), + [x, y, _, z] => Ok([x, y, z]), _ => Err(ProgramError::InvalidArgument), }?; //accounts checks happen in c_entrypoint From 0caeb04fd9ca3f0a45be5df1e5460b6ab457a91d Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:18:24 +0000 Subject: [PATCH 50/58] moved call to wrapper to the begining of upd_price --- program/rust/src/rust_oracle.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 027c09e4c..02f109cc6 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -70,6 +70,7 @@ pub fn update_price( _instruction_data: &[u8], input: *mut u8, ) -> OracleResult { + let c_ret_value = c_entrypoint_wrapper(input)?; let [_funding_account_info, price_account_info, _sysvar_clock] = match accounts { [x, y, z] => Ok([x, y, z]), [x, y, _, z] => Ok([x, y, z]), @@ -78,9 +79,8 @@ pub fn update_price( //accounts checks happen in c_entrypoint let account_len = price_account_info.try_data_len()?; match account_len { - PRICE_T_SIZE => c_entrypoint_wrapper(input), + PRICE_T_SIZE => Ok(c_ret_value), PRICE_ACCOUNT_SIZE => { - let c_ret_value = c_entrypoint_wrapper(input)?; if c_ret_value == SUCCESSFULLY_UPDATED_AGGREGATE { let mut price_account = load_account_as_mut::(price_account_info)?; From c44790fa6407962f4e4b6a2b0107a0ad70fa03fb Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:21:56 +0000 Subject: [PATCH 51/58] added load_checked to avoid human error --- program/rust/src/rust_oracle.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 02f109cc6..ae1ba01e5 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -125,6 +125,11 @@ pub fn resize_price_account( check_id(system_program.key), OracleError::InvalidSystemAccount.into(), )?; + //panick if not a price account + //need to makre sure it goes out of scope immediatly to avoid mutable borrow errors + { + load_checked::(price_account_info, PC_VERSION)?; + } let account_len = price_account_info.try_data_len()?; match account_len { PRICE_T_SIZE => { From 70dd6b8a845d0c9e8480301f252c8a6df7ea2e24 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:23:36 +0000 Subject: [PATCH 52/58] fixed typo --- pyth/tests/test_publish.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index 49fea2130..f8e830749 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -42,7 +42,7 @@ def get_path_to_pythdir_pair(account_addr): def resize_account(price_account_address): """ - given a string with the pubkey of a price accountm it calls the resize instruction of the Oracle on it + given a string with the pubkey of a price account it calls the resize instruction of the Oracle on it """ #constants from oracle.h PROGRAM_VERSION = 2 #TODO: update this From e287e80f6fb980cef72dc2e2cddc88d079e18920 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:24:44 +0000 Subject: [PATCH 53/58] renamed sender to publickeypair --- pyth/tests/test_publish.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyth/tests/test_publish.py b/pyth/tests/test_publish.py index f8e830749..c33a6caf3 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -66,11 +66,11 @@ def resize_account(price_account_address): ) txn = Transaction().add(resize_instruction) txn.fee_payer = funding_key - sender = get_key_pair(solana_keygen[1]) + funding_key_pair = get_key_pair(solana_keygen[1]) path_to_price = get_path_to_pythdir_pair(price_key) price_key_pair = get_key_pair(path_to_price) solana_client = Client("http://localhost:8899") - solana_client.send_transaction(txn, sender, price_key_pair) + solana_client.send_transaction(txn, funding_key_pair, price_key_pair) def get_account_size(acc_address): """ From 13f0998297bc2dbab721fd1f7dfda268c7a395bd Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:27:55 +0000 Subject: [PATCH 54/58] changed inital_size for PriceAccoutWrapper --- program/rust/src/time_machine_types.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 6ff8e67d2..f7e0b7838 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -55,7 +55,7 @@ unsafe impl Pod for PriceAccountWrapper { impl PythAccount for PriceAccountWrapper { const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; - const INITIAL_SIZE: u32 = size_of::() as u32; + const INITIAL_SIZE: u32 = size_of::() as u32; } #[cfg(test)] From 69302a35c5e3b8d96bd99afc6608aa2423528f37 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 20:34:03 +0000 Subject: [PATCH 55/58] switched to index for the wrapper --- program/rust/src/rust_oracle.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index ae1ba01e5..cd29776e2 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -71,11 +71,7 @@ pub fn update_price( input: *mut u8, ) -> OracleResult { let c_ret_value = c_entrypoint_wrapper(input)?; - let [_funding_account_info, price_account_info, _sysvar_clock] = match accounts { - [x, y, z] => Ok([x, y, z]), - [x, y, _, z] => Ok([x, y, z]), - _ => Err(ProgramError::InvalidArgument), - }?; + let price_account_info = &accounts[1]; //accounts checks happen in c_entrypoint let account_len = price_account_info.try_data_len()?; match account_len { From 22c6f2765f4b57e74742cc848fab6b99894407ce Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 22:10:52 +0000 Subject: [PATCH 56/58] another typo --- program/rust/src/rust_oracle.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index cd29776e2..6e1f9d3b2 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -121,7 +121,7 @@ pub fn resize_price_account( check_id(system_program.key), OracleError::InvalidSystemAccount.into(), )?; - //panick if not a price account + //throw an error if not a price account //need to makre sure it goes out of scope immediatly to avoid mutable borrow errors { load_checked::(price_account_info, PC_VERSION)?; From b72e93d2b7dad69aa6e8abec4a5c14850d9255b0 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 22:14:46 +0000 Subject: [PATCH 57/58] merge errors --- program/rust/src/processor.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/program/rust/src/processor.rs b/program/rust/src/processor.rs index 87f56fe4d..fbed5f8a9 100644 --- a/program/rust/src/processor.rs +++ b/program/rust/src/processor.rs @@ -12,6 +12,7 @@ use crate::c_oracle_header::{ command_t_e_cmd_agg_price, command_t_e_cmd_del_publisher, command_t_e_cmd_init_mapping, + command_t_e_cmd_init_price, command_t_e_cmd_resize_price_account, command_t_e_cmd_set_min_pub, command_t_e_cmd_upd_price, @@ -31,8 +32,8 @@ use crate::rust_oracle::{ add_publisher, del_publisher, init_mapping, - resize_price_account, init_price, + resize_price_account, set_min_pub, upd_product, update_price, From 8ca407b9ce38ac53ec17422067bbdf18b35743b6 Mon Sep 17 00:00:00 2001 From: Mark Jabbour Date: Thu, 11 Aug 2022 22:35:57 +0000 Subject: [PATCH 58/58] changed initial size to for price account --- program/rust/src/time_machine_types.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index f7e0b7838..bccc1e0c3 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -3,6 +3,7 @@ use crate::c_oracle_header::{ PythAccount, EXTRA_PUBLISHER_SPACE, PC_ACCTYPE_PRICE, + PC_PRICE_T_COMP_OFFSET, }; use crate::error::OracleError; use bytemuck::{ @@ -10,7 +11,6 @@ use bytemuck::{ Zeroable, }; use solana_program::msg; -use std::mem::size_of; #[derive(Debug, Clone, Copy)] @@ -55,7 +55,7 @@ unsafe impl Pod for PriceAccountWrapper { impl PythAccount for PriceAccountWrapper { const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; - const INITIAL_SIZE: u32 = size_of::() as u32; + const INITIAL_SIZE: u32 = PC_PRICE_T_COMP_OFFSET as u32; } #[cfg(test)]