Skip to content

Commit 9662887

Browse files
authored
More logging (#217)
* Format * CI * Fixed * Add comment to README * Format config * Fix build * Log time and ema * Fix ema deserialize * Revert format * Add expo * Fix comments * Unused import Co-authored-by: Guillermo Bescos <guibescos>
1 parent f31a788 commit 9662887

File tree

6 files changed

+99
-27
lines changed

6 files changed

+99
-27
lines changed

program/rust/build.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ fn main() {
1212
parser.register_traits("pc_acc", borsh_derives.to_vec());
1313
parser.register_traits("pc_price_info", borsh_derives.to_vec());
1414
parser.register_traits("cmd_upd_price", borsh_derives.to_vec());
15+
parser.register_traits("pc_ema", borsh_derives.to_vec());
1516

1617
//generate and write bindings
1718
let bindings = Builder::default()

program/rust/src/deserialize.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
use crate::c_oracle_header::size_t;
2+
use crate::error::OracleError;
3+
use borsh::BorshDeserialize;
4+
use solana_program::account_info::AccountInfo;
5+
use solana_program::program_error::ProgramError;
6+
use std::mem::size_of;
7+
use std::result::Result;
8+
9+
/// Deserialize field in `source` with offset `offset`
10+
pub fn deserialize_single_field_from_buffer<T: BorshDeserialize>(
11+
source: &[u8],
12+
offset: Option<size_t>,
13+
) -> Result<T, ProgramError> {
14+
let start: usize = offset
15+
.unwrap_or(0)
16+
.try_into()
17+
.map_err(|_| OracleError::IntegerCastingError)?;
18+
19+
let res: T = T::try_from_slice(&source[start..(start + size_of::<T>())])?;
20+
Ok(res)
21+
}
22+
23+
/// Deserialize field in `i` rank of `accounts` with offset `offset`
24+
pub fn deserialize_single_field_from_account<T: BorshDeserialize>(
25+
accounts: &[AccountInfo],
26+
i: usize,
27+
offset: Option<size_t>,
28+
) -> Result<T, ProgramError> {
29+
Ok(deserialize_single_field_from_buffer::<T>(
30+
&accounts
31+
.get(i)
32+
.ok_or(ProgramError::NotEnoughAccountKeys)?
33+
.try_borrow_data()?,
34+
offset,
35+
)?)
36+
}

program/rust/src/error.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,15 @@ pub type OracleResult = Result<u64, ProgramError>;
1010
pub enum OracleError {
1111
/// Generic catch all error
1212
#[error("Generic")]
13-
Generic = 600,
13+
Generic = 600,
1414
/// integer casting error
1515
#[error("IntegerCastingError")]
16-
IntegerCastingError = 601,
16+
IntegerCastingError = 601,
1717
/// c_entrypoint returned an unexpected value
1818
#[error("UnknownCError")]
19-
UnknownCError = 602,
19+
UnknownCError = 602,
20+
#[error("UnrecognizedInstruction")]
21+
UnrecognizedInstruction = 603,
2022
}
2123

2224
impl From<OracleError> for ProgramError {

program/rust/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
mod c_oracle_header;
2+
mod deserialize;
23
mod error;
34
mod log;
45
mod processor;

program/rust/src/log.rs

Lines changed: 55 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,46 +1,71 @@
11
use crate::c_oracle_header::*;
2+
use crate::deserialize::{
3+
deserialize_single_field_from_account,
4+
deserialize_single_field_from_buffer,
5+
};
26
use crate::error::OracleError;
37
use borsh::BorshDeserialize;
48
use solana_program::account_info::AccountInfo;
9+
use solana_program::clock::Clock;
510
use solana_program::entrypoint::ProgramResult;
611
use solana_program::msg;
7-
use std::mem::size_of;
12+
use solana_program::program_error::ProgramError;
13+
use solana_program::sysvar::Sysvar;
814

915
pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResult {
1016
msg!("Pyth oracle contract");
1117

12-
let instruction_header: cmd_hdr = cmd_hdr::try_from_slice(&instruction_data[..8])?;
18+
let instruction_header: cmd_hdr =
19+
deserialize_single_field_from_buffer::<cmd_hdr>(&instruction_data, None)?;
1320
let instruction_id: u32 = instruction_header
1421
.cmd_
1522
.try_into()
16-
.map_err(|_| OracleError::Generic)?;
23+
.map_err(|_| OracleError::IntegerCastingError)?;
24+
25+
1726
match instruction_id {
1827
command_t_e_cmd_upd_price | command_t_e_cmd_agg_price => {
1928
let instruction: cmd_upd_price = cmd_upd_price::try_from_slice(instruction_data)?;
29+
// Account 1 is price_info in this instruction
30+
let expo: i32 = deserialize_single_field_from_account::<i32>(
31+
accounts,
32+
1,
33+
Some(PRICE_T_EXPO_OFFSET),
34+
)?;
2035
msg!(
21-
"UpdatePrice: publisher={:}, price_account={:}, price={:}, conf={:}, status={:}, slot={:}",
36+
"UpdatePrice: publisher={:}, price_account={:}, price={:}, conf={:}, expo={:}, status={:}, slot={:}, solana_time={:}",
2237
accounts.get(0)
23-
.ok_or(OracleError::Generic)?.key,
38+
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
2439
accounts.get(1)
25-
.ok_or(OracleError::Generic)?.key,
40+
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
2641
instruction.price_,
2742
instruction.conf_,
43+
expo,
2844
instruction.status_,
29-
instruction.pub_slot_
45+
instruction.pub_slot_,
46+
Clock::get()?.unix_timestamp
3047
);
3148
}
3249
command_t_e_cmd_upd_price_no_fail_on_error => {
3350
let instruction: cmd_upd_price = cmd_upd_price::try_from_slice(instruction_data)?;
51+
// Account 1 is price_info in this instruction
52+
let expo: i32 = deserialize_single_field_from_account::<i32>(
53+
accounts,
54+
1,
55+
Some(PRICE_T_EXPO_OFFSET),
56+
)?;
3457
msg!(
35-
"UpdatePriceNoFailOnError: publisher={:}, price_account={:}, price={:}, conf={:}, status={:}, slot={:}",
58+
"UpdatePriceNoFailOnError: publisher={:}, price_account={:}, price={:}, conf={:}, expo={:}, status={:}, slot={:}, solana_time={:}",
3659
accounts.get(0)
37-
.ok_or(OracleError::Generic)?.key,
60+
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
3861
accounts.get(1)
39-
.ok_or(OracleError::Generic)?.key,
62+
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
4063
instruction.price_,
4164
instruction.conf_,
65+
expo,
4266
instruction.status_,
43-
instruction.pub_slot_
67+
instruction.pub_slot_,
68+
Clock::get()?.unix_timestamp
4469
);
4570
}
4671
command_t_e_cmd_add_mapping => {
@@ -73,31 +98,37 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu
7398
}
7499
_ => {
75100
msg!("UnrecognizedInstruction");
76-
return Err(OracleError::Generic.into());
101+
return Err(OracleError::UnrecognizedInstruction.into());
77102
}
78103
}
79104
Ok(())
80105
}
81106

82107
pub fn post_log(c_ret_val: u64, accounts: &[AccountInfo]) -> ProgramResult {
83108
if c_ret_val == SUCCESSFULLY_UPDATED_AGGREGATE {
84-
let start: usize = PRICE_T_AGGREGATE_OFFSET
85-
.try_into()
86-
.map_err(|_| OracleError::Generic)?;
87-
// We trust that the C oracle has properly checked this account
88-
let aggregate_price_info: pc_price_info = pc_price_info::try_from_slice(
89-
&accounts
90-
.get(1)
91-
.ok_or(OracleError::Generic)?
92-
.try_borrow_data()?[start..(start + size_of::<pc_price_info>())],
109+
// We trust that the C oracle has properly checked account 1, we can only get here through
110+
// the update price instructions
111+
let aggregate_price_info: pc_price_info = deserialize_single_field_from_account::<
112+
pc_price_info,
113+
>(
114+
accounts, 1, Some(PRICE_T_AGGREGATE_OFFSET)
93115
)?;
116+
let ema_info: pc_ema =
117+
deserialize_single_field_from_account::<pc_ema>(accounts, 1, Some(PRICE_T_EMA_OFFSET))?;
118+
let expo: i32 =
119+
deserialize_single_field_from_account::<i32>(accounts, 1, Some(PRICE_T_EXPO_OFFSET))?;
120+
94121
msg!(
95-
"UpdateAggregate : price_account={:}, price={:}, conf={:}, status={:}, slot={:}",
96-
accounts.get(1).ok_or(OracleError::Generic)?.key,
122+
"UpdateAggregate : price_account={:}, price={:}, conf={:}, expo={:}, status={:}, slot={:}, solana_time={:}, ema={:}",
123+
accounts.get(1)
124+
.ok_or(ProgramError::NotEnoughAccountKeys)?.key,
97125
aggregate_price_info.price_,
98126
aggregate_price_info.conf_,
127+
expo,
99128
aggregate_price_info.status_,
100-
aggregate_price_info.pub_slot_
129+
aggregate_price_info.pub_slot_,
130+
Clock::get()?.unix_timestamp,
131+
ema_info.val_
101132
);
102133
}
103134
Ok(())

program/rust/src/price_t_offsets.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ const size_t PRICE_T_AGGREGATE_OFFSET = offsetof(struct pc_price, agg_);
99
const size_t PRICE_T_AGGREGATE_CONF_OFFSET = offsetof(struct pc_price, agg_) + offsetof(struct pc_price_info, conf_);
1010
const size_t PRICE_T_AGGREGATE_PRICE_OFFSET = offsetof(struct pc_price, agg_) + offsetof(struct pc_price_info, price_);
1111
const size_t PRICE_T_AGGREGATE_STATUS_OFFSET = offsetof(struct pc_price, agg_) + offsetof(struct pc_price_info, status_);
12+
const size_t PRICE_T_EMA_OFFSET = offsetof(struct pc_price, twap_);
1213
const size_t PRICE_T_PREV_TIMESTAMP_OFFSET = offsetof(struct pc_price, prev_timestamp_);
1314
const size_t PRICE_T_PREV_CONF_OFFSET = offsetof(struct pc_price, prev_conf_);
1415
const size_t PRICE_T_PREV_AGGREGATE_OFFSET = offsetof(struct pc_price, prev_price_);

0 commit comments

Comments
 (0)