Skip to content

Commit 90e7769

Browse files
jayantkJayant Krishnamurthy
andauthored
Implement init_price instruction (#242)
* init price instruction * better test * merge better * merge better better * unused function * doh Co-authored-by: Jayant Krishnamurthy <jkrishnamurthy@jumptrading.com>
1 parent e0f888f commit 90e7769

File tree

6 files changed

+260
-67
lines changed

6 files changed

+260
-67
lines changed

program/c/src/oracle/oracle.c

Lines changed: 1 addition & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -38,17 +38,6 @@ static bool valid_funding_account( SolAccountInfo *ka )
3838
ka->is_writable;
3939
}
4040

41-
static bool valid_signable_account( SolParameters *prm,
42-
SolAccountInfo *ka,
43-
uint64_t min_dlen )
44-
{
45-
return ka->is_signer &&
46-
ka->is_writable &&
47-
SolPubkey_same( ka->owner, prm->program_id ) &&
48-
ka->data_len >= min_dlen &&
49-
is_rent_exempt( *ka->lamports, ka->data_len );
50-
}
51-
5241
static bool valid_writable_account( SolParameters *prm,
5342
SolAccountInfo *ka,
5443
uint64_t min_dlen )
@@ -59,54 +48,6 @@ static bool valid_writable_account( SolParameters *prm,
5948
is_rent_exempt( *ka->lamports, ka->data_len );
6049
}
6150

62-
static uint64_t init_price( SolParameters *prm, SolAccountInfo *ka )
63-
{
64-
// Validate command parameters
65-
cmd_init_price_t *cptr = (cmd_init_price_t*)prm->data;
66-
if ( prm->data_len != sizeof( cmd_init_price_t ) ||
67-
cptr->expo_ > PC_MAX_NUM_DECIMALS ||
68-
cptr->expo_ < -PC_MAX_NUM_DECIMALS ) {
69-
return ERROR_INVALID_ARGUMENT;
70-
}
71-
72-
// Account (1) is the price account to (re)initialize
73-
// Verify that these are signed, writable accounts with correct ownership
74-
// and size
75-
if ( prm->ka_num != 2 ||
76-
!valid_funding_account( &ka[0] ) ||
77-
!valid_signable_account( prm, &ka[1], sizeof( pc_price_t ) )) {
78-
return ERROR_INVALID_ARGUMENT;
79-
}
80-
81-
// Verify that the price account is initialized
82-
pc_price_t *sptr = (pc_price_t*)ka[1].data;
83-
if ( sptr->magic_ != PC_MAGIC ||
84-
sptr->ver_ != cptr->ver_ ||
85-
sptr->type_ != PC_ACCTYPE_PRICE ||
86-
sptr->ptype_ != cptr->ptype_ ) {
87-
return ERROR_INVALID_ARGUMENT;
88-
}
89-
90-
// (re)initialize price exponent and clear-down all quotes
91-
sptr->expo_ = cptr->expo_;
92-
sptr->last_slot_ = 0UL;
93-
sptr->valid_slot_ = 0UL;
94-
sptr->agg_.pub_slot_ = 0UL;
95-
sptr->prev_slot_ = 0UL;
96-
sptr->prev_price_ = 0L;
97-
sptr->prev_conf_ = 0L;
98-
sptr->prev_timestamp_ = 0L;
99-
sol_memset( &sptr->twap_, 0, sizeof( pc_ema_t ) );
100-
sol_memset( &sptr->twac_, 0, sizeof( pc_ema_t ) );
101-
sol_memset( &sptr->agg_, 0, sizeof( pc_price_info_t ) );
102-
for(unsigned i=0; i != sptr->num_; ++i ) {
103-
pc_price_comp_t *iptr = &sptr->comp_[i];
104-
sol_memset( &iptr->agg_, 0, sizeof( pc_price_info_t ) );
105-
sol_memset( &iptr->latest_, 0, sizeof( pc_price_info_t ) );
106-
}
107-
return SUCCESS;
108-
}
109-
11051
static uint64_t upd_price( SolParameters *prm, SolAccountInfo *ka )
11152
{
11253
// Validate command parameters
@@ -212,7 +153,7 @@ static uint64_t dispatch( SolParameters *prm, SolAccountInfo *ka )
212153
case e_cmd_add_price: return ERROR_INVALID_ARGUMENT;
213154
case e_cmd_add_publisher: return ERROR_INVALID_ARGUMENT;
214155
case e_cmd_del_publisher: return ERROR_INVALID_ARGUMENT;
215-
case e_cmd_init_price: return init_price( prm, ka );
156+
case e_cmd_init_price: return ERROR_INVALID_ARGUMENT;
216157
case e_cmd_init_test: return ERROR_INVALID_ARGUMENT;
217158
case e_cmd_upd_test: return ERROR_INVALID_ARGUMENT;
218159
case e_cmd_set_min_pub: return ERROR_INVALID_ARGUMENT;

program/rust/src/c_oracle_header.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@ unsafe impl Pod for cmd_hdr {
9393
}
9494

9595
#[cfg(target_endian = "little")]
96-
9796
unsafe impl Zeroable for pc_price_info {
9897
}
9998

@@ -117,13 +116,22 @@ unsafe impl Zeroable for pc_ema {
117116
unsafe impl Pod for pc_ema {
118117
}
119118

119+
#[cfg(target_endian = "little")]
120120
unsafe impl Zeroable for cmd_add_price_t {
121121
}
122122

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

127+
#[cfg(target_endian = "little")]
128+
unsafe impl Zeroable for cmd_init_price_t {
129+
}
130+
131+
#[cfg(target_endian = "little")]
132+
unsafe impl Pod for cmd_init_price_t {
133+
}
134+
127135
#[cfg(target_endian = "little")]
128136
unsafe impl Zeroable for cmd_add_publisher_t {
129137
}

program/rust/src/processor.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::c_oracle_header::{
1212
command_t_e_cmd_agg_price,
1313
command_t_e_cmd_del_publisher,
1414
command_t_e_cmd_init_mapping,
15+
command_t_e_cmd_init_price,
1516
command_t_e_cmd_set_min_pub,
1617
command_t_e_cmd_upd_account_version,
1718
command_t_e_cmd_upd_price,
@@ -31,6 +32,7 @@ use crate::rust_oracle::{
3132
add_publisher,
3233
del_publisher,
3334
init_mapping,
35+
init_price,
3436
set_min_pub,
3537
upd_product,
3638
update_price,
@@ -66,6 +68,7 @@ pub fn process_instruction(
6668
}
6769
command_t_e_cmd_add_price => add_price(program_id, accounts, instruction_data),
6870
command_t_e_cmd_init_mapping => init_mapping(program_id, accounts, instruction_data),
71+
command_t_e_cmd_init_price => init_price(program_id, accounts, instruction_data),
6972
command_t_e_cmd_add_mapping => add_mapping(program_id, accounts, instruction_data),
7073
command_t_e_cmd_add_publisher => add_publisher(program_id, accounts, instruction_data),
7174
command_t_e_cmd_del_publisher => del_publisher(program_id, accounts, instruction_data),

program/rust/src/rust_oracle.rs

Lines changed: 79 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,11 +24,14 @@ use crate::c_oracle_header::{
2424
cmd_add_publisher_t,
2525
cmd_del_publisher_t,
2626
cmd_hdr_t,
27+
cmd_init_price_t,
2728
cmd_set_min_pub_t,
2829
cmd_upd_product_t,
2930
pc_acc,
31+
pc_ema_t,
3032
pc_map_table_t,
3133
pc_price_comp,
34+
pc_price_info_t,
3235
pc_price_t,
3336
pc_prod_t,
3437
pc_pub_key_t,
@@ -141,12 +144,11 @@ pub fn add_price(
141144
) -> OracleResult {
142145
let cmd_args = load::<cmd_add_price_t>(instruction_data)?;
143146

144-
if cmd_args.expo_ > PC_MAX_NUM_DECIMALS as i32
145-
|| cmd_args.expo_ < -(PC_MAX_NUM_DECIMALS as i32)
146-
|| cmd_args.ptype_ == PC_PTYPE_UNKNOWN
147-
{
148-
return Err(ProgramError::InvalidArgument);
149-
}
147+
check_exponent_range(cmd_args.expo_)?;
148+
pyth_assert(
149+
cmd_args.ptype_ != PC_PTYPE_UNKNOWN,
150+
ProgramError::InvalidArgument,
151+
)?;
150152

151153
let [funding_account, product_account, price_account] = match accounts {
152154
[x, y, z] => Ok([x, y, z]),
@@ -170,6 +172,69 @@ pub fn add_price(
170172
Ok(SUCCESS)
171173
}
172174

175+
pub fn init_price(
176+
program_id: &Pubkey,
177+
accounts: &[AccountInfo],
178+
instruction_data: &[u8],
179+
) -> OracleResult {
180+
let cmd_args = load::<cmd_init_price_t>(instruction_data)?;
181+
182+
check_exponent_range(cmd_args.expo_)?;
183+
184+
let [funding_account, price_account] = match accounts {
185+
[x, y] => Ok([x, y]),
186+
_ => Err(ProgramError::InvalidArgument),
187+
}?;
188+
189+
check_valid_funding_account(funding_account)?;
190+
check_valid_signable_account(program_id, price_account, size_of::<pc_price_t>())?;
191+
192+
let mut price_data = load_checked::<pc_price_t>(price_account, cmd_args.ver_)?;
193+
pyth_assert(
194+
price_data.ptype_ == cmd_args.ptype_,
195+
ProgramError::InvalidArgument,
196+
)?;
197+
198+
price_data.expo_ = cmd_args.expo_;
199+
200+
price_data.last_slot_ = 0;
201+
price_data.valid_slot_ = 0;
202+
price_data.agg_.pub_slot_ = 0;
203+
price_data.prev_slot_ = 0;
204+
price_data.prev_price_ = 0;
205+
price_data.prev_conf_ = 0;
206+
price_data.prev_timestamp_ = 0;
207+
sol_memset(
208+
bytes_of_mut(&mut price_data.twap_),
209+
0,
210+
size_of::<pc_ema_t>(),
211+
);
212+
sol_memset(
213+
bytes_of_mut(&mut price_data.twac_),
214+
0,
215+
size_of::<pc_ema_t>(),
216+
);
217+
sol_memset(
218+
bytes_of_mut(&mut price_data.agg_),
219+
0,
220+
size_of::<pc_price_info_t>(),
221+
);
222+
for i in 0..(price_data.comp_.len() as usize) {
223+
sol_memset(
224+
bytes_of_mut(&mut price_data.comp_[i].agg_),
225+
0,
226+
size_of::<pc_price_info_t>(),
227+
);
228+
sol_memset(
229+
bytes_of_mut(&mut price_data.comp_[i].latest_),
230+
0,
231+
size_of::<pc_price_info_t>(),
232+
);
233+
}
234+
235+
Ok(SUCCESS)
236+
}
237+
173238
/// add a publisher to a price account
174239
/// accounts[0] funding account [signer writable]
175240
/// accounts[1] price account to add the publisher to [signer writable]
@@ -445,6 +510,14 @@ fn check_valid_fresh_account(account: &AccountInfo) -> Result<(), ProgramError>
445510
)
446511
}
447512

513+
// Check that an exponent is within the range of permitted exponents for price accounts.
514+
fn check_exponent_range(expo: i32) -> Result<(), ProgramError> {
515+
pyth_assert(
516+
expo >= -(PC_MAX_NUM_DECIMALS as i32) && expo <= PC_MAX_NUM_DECIMALS as i32,
517+
ProgramError::InvalidArgument,
518+
)
519+
}
520+
448521
/// Sets the data of account to all-zero
449522
pub fn clear_account(account: &AccountInfo) -> Result<(), ProgramError> {
450523
let mut data = account

program/rust/src/tests/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ mod test_add_product;
44
mod test_add_publisher;
55
mod test_del_publisher;
66
mod test_init_mapping;
7+
mod test_init_price;
78
mod test_set_min_pub;
89
mod test_upd_product;
910
mod test_utils;

0 commit comments

Comments
 (0)