From d95623f26097ab66aac1cfbeb194041cce77b23c Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Tue, 30 Aug 2022 18:49:42 -0500 Subject: [PATCH 01/30] Pseudocode --- program/rust/src/lib.rs | 1 - program/rust/src/time_machine_types.rs | 102 ++++++++++++++++++++++++- 2 files changed, 100 insertions(+), 3 deletions(-) diff --git a/program/rust/src/lib.rs b/program/rust/src/lib.rs index 544457554..6472c2856 100644 --- a/program/rust/src/lib.rs +++ b/program/rust/src/lib.rs @@ -1,4 +1,3 @@ -#![deny(warnings)] // Allow non upper case globals from C #![allow(non_upper_case_globals)] // Allow using the solana_program::entrypoint::deserialize function diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 27d1c79f4..d212a88f2 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -6,6 +6,7 @@ use crate::c_oracle_header::{ PC_PRICE_T_COMP_OFFSET, }; use crate::error::OracleError; +use crate::utils::try_convert; use bytemuck::{ Pod, Zeroable, @@ -30,11 +31,11 @@ pub struct PriceAccountWrapper { //space for more publishers pub extra_publisher_space: [u8; EXTRA_PUBLISHER_SPACE as usize], //TimeMachine - pub time_machine: TimeMachineWrapper, + pub time_machine: SmaTracker<48>, } impl PriceAccountWrapper { pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { - // TO DO + self.time_machine.initialize(THIRTY_MINUTES, TWENTY_SECONDS); Ok(()) } @@ -44,6 +45,103 @@ impl PriceAccountWrapper { } } +const TWENTY_SECONDS: u64 = 20; +const THIRTY_MINUTES: i64 = 30 * 60; + +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq)] +enum Status { + Invalid = 0, + Valid = 1 +} + + +#[derive(Debug, Copy, Clone)] +#[repr(C)] +/// Represents a Simple Moving Average Tracker Tracker that has NUM_ENTRIES entries +/// each tracking time weighted sums for granularity seconds periods. +///The prices are assumed to be provided under some fixed point representation, and the computation +/// guarantees accuracy up to the last decimal digit in the fixed point representation. +/// Assumes threshold < granularity +/// Both threshold and granularity are set on initialization +pub struct SmaTracker { + threshold: u64, /* the maximum slot gap we are willing + * to accept */ + granularity: i64, //the length of the time covered per entry + current_entry_slot_accumulator: u64, /* accumulates the number of slots that + * went into the + * weights of the current entry, reset + * to 0 before + * moving to the next one */ + current_entry_status: Status, /* the status of the current entry, + * INVALID if an update takes too + * long, PENDING if it is still being + * updated but the updates have been + * consistent so far. */ + current_entry_weighted_price_accumulator: i64, /* accumulates + * slot_delta * + * (inflated_p1 + + * inflated_p2) / 2 + * to compute + * averages */ + running_entry_prices: [i64; NUM_ENTRIES], /* A running sum of the slot weighted average of each entry. */ + running_valid_entry_counter: [u64; NUM_ENTRIES], /* Each entry + * increment the + * counter of the + * previous one if + * it is valid */ +} + + + +impl SmaTracker { + + pub fn time_to_entry(&self, time : i64)-> Result { + Ok(try_convert::(time / self.granularity)? % NUM_ENTRIES) + } + + pub fn initialize(&mut self, granularity : i64, threshold : u64){ + self.threshold = threshold; + self.granularity = granularity; + } + + pub fn initialize_epoch(&mut self, epoch : usize){ + if self.current_entry_status == Status::Valid{ + self.running_valid_entry_counter[epoch] == self.running_valid_entry_counter[epoch - 1]; + } + self.running_entry_prices[epoch] = self.running_entry_prices[epoch-1] + self.current_entry_weighted_price_accumulator / self.current_entry_slot_accumulator as i64; + self.current_entry_slot_accumulator = 0; + self.current_entry_weighted_price_accumulator = 0; + self.current_entry_status = Status::Valid; + } + + pub fn add_datapoint(&mut self, last_two_times : (i64,i64) , last_two_slot : (u64, u64), last_two_prices: (i64, i64), + last_two_confs: (u64, u64))-> Result<(), OracleError>{ + + let epoch_gap = self.time_to_entry(last_two_times.1)? - self.time_to_entry(last_two_times.0)?; + + self.current_entry_weighted_price_accumulator = (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; + self.current_entry_slot_accumulator += (last_two_slot.1 - last_two_slot.0); + if (last_two_slot.1 - last_two_slot.0) > self.threshold { + self.current_entry_status = Status::Invalid; + } + + for i in last_two_times.0+1..last_two_times.1 { + self.initialize_epoch(i); + self.current_entry_weighted_price_accumulator = (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; + self.current_entry_slot_accumulator += (last_two_slot.1 - last_two_slot.0); + if (last_two_slot.1 - last_two_slot.0) > self.threshold { + self.current_entry_status = Status::Invalid; + } + } + + + + + Ok(()) + } +} + #[cfg(target_endian = "little")] unsafe impl Zeroable for PriceAccountWrapper { } From e2b47398f270cd9d9c44c179429eec248b85fc86 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Tue, 30 Aug 2022 18:51:52 -0500 Subject: [PATCH 02/30] Pseudocode --- 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 d212a88f2..5705c9048 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -120,7 +120,7 @@ impl SmaTracker { let epoch_gap = self.time_to_entry(last_two_times.1)? - self.time_to_entry(last_two_times.0)?; - self.current_entry_weighted_price_accumulator = (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; + self.current_entry_weighted_price_accumulator += (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; self.current_entry_slot_accumulator += (last_two_slot.1 - last_two_slot.0); if (last_two_slot.1 - last_two_slot.0) > self.threshold { self.current_entry_status = Status::Invalid; @@ -128,7 +128,7 @@ impl SmaTracker { for i in last_two_times.0+1..last_two_times.1 { self.initialize_epoch(i); - self.current_entry_weighted_price_accumulator = (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; + self.current_entry_weighted_price_accumulator += (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; self.current_entry_slot_accumulator += (last_two_slot.1 - last_two_slot.0); if (last_two_slot.1 - last_two_slot.0) > self.threshold { self.current_entry_status = Status::Invalid; From ee9686ac254c8c665a546948b725149cc2120885 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Thu, 1 Sep 2022 10:36:34 -0500 Subject: [PATCH 03/30] Check --- program/rust/src/time_machine_types.rs | 139 ++++++++++++++----------- 1 file changed, 77 insertions(+), 62 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 5705c9048..4a39d348c 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -12,7 +12,6 @@ use bytemuck::{ Zeroable, }; - #[derive(Debug, Clone, Copy)] #[repr(C)] /// this wraps multiple SMA and tick trackers, and includes all the state @@ -40,7 +39,12 @@ impl PriceAccountWrapper { } pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { - // TO DO + self.time_machine.add_datapoint( + (self.price_data.prev_timestamp_, self.price_data.timestamp_), + (self.price_data.prev_slot_, self.price_data.last_slot_), + (self.price_data.prev_price_, self.price_data.agg_.price_), + (0, 0), + )?; Ok(()) } } @@ -49,13 +53,12 @@ const TWENTY_SECONDS: u64 = 20; const THIRTY_MINUTES: i64 = 30 * 60; #[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq)] -enum Status { +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +pub enum Status { Invalid = 0, - Valid = 1 + Valid = 1, } - #[derive(Debug, Copy, Clone)] #[repr(C)] /// Represents a Simple Moving Average Tracker Tracker that has NUM_ENTRIES entries @@ -65,81 +68,93 @@ enum Status { /// Assumes threshold < granularity /// Both threshold and granularity are set on initialization pub struct SmaTracker { - threshold: u64, /* the maximum slot gap we are willing - * to accept */ - granularity: i64, //the length of the time covered per entry - current_entry_slot_accumulator: u64, /* accumulates the number of slots that - * went into the - * weights of the current entry, reset - * to 0 before - * moving to the next one */ - current_entry_status: Status, /* the status of the current entry, - * INVALID if an update takes too - * long, PENDING if it is still being - * updated but the updates have been - * consistent so far. */ - current_entry_weighted_price_accumulator: i64, /* accumulates - * slot_delta * - * (inflated_p1 + - * inflated_p2) / 2 - * to compute - * averages */ - running_entry_prices: [i64; NUM_ENTRIES], /* A running sum of the slot weighted average of each entry. */ - running_valid_entry_counter: [u64; NUM_ENTRIES], /* Each entry - * increment the - * counter of the - * previous one if - * it is valid */ + pub threshold: u64, /* the maximum slot gap we are willing + * to accept */ + pub granularity: i64, //the length of the time covered per entry + pub current_entry_slot_accumulator: u64, /* accumulates the number of slots that + * went into the + * weights of the current entry, reset + * to 0 before + * moving to the next one */ + pub current_entry_status: Status, /* the status of the current entry, + * INVALID if an update takes too + * long, PENDING if it is still being + * updated but the updates have been + * consistent so far. */ + pub current_entry_weighted_price_accumulator: i128, /* accumulates + * slot_delta * + * (inflated_p1 + + * inflated_p2) / 2 + * to compute + * averages */ + pub running_entry_prices: [i128; NUM_ENTRIES], /* A running sum of the + * slot weighted average + * of each entry. */ + pub running_valid_entry_counter: [u64; NUM_ENTRIES], /* Each entry + * increment the + * counter of the + * previous one if + * it is valid */ } - - -impl SmaTracker { - - pub fn time_to_entry(&self, time : i64)-> Result { - Ok(try_convert::(time / self.granularity)? % NUM_ENTRIES) +impl SmaTracker { + /// Should never fail because time is positive and usize = u64 + pub fn time_to_epoch(&self, time: i64) -> Result { + try_convert::(time / self.granularity) } - pub fn initialize(&mut self, granularity : i64, threshold : u64){ + pub fn initialize(&mut self, granularity: i64, threshold: u64) { self.threshold = threshold; self.granularity = granularity; } - pub fn initialize_epoch(&mut self, epoch : usize){ - if self.current_entry_status == Status::Valid{ - self.running_valid_entry_counter[epoch] == self.running_valid_entry_counter[epoch - 1]; - } - self.running_entry_prices[epoch] = self.running_entry_prices[epoch-1] + self.current_entry_weighted_price_accumulator / self.current_entry_slot_accumulator as i64; - self.current_entry_slot_accumulator = 0; - self.current_entry_weighted_price_accumulator = 0; - self.current_entry_status = Status::Valid; - } - - pub fn add_datapoint(&mut self, last_two_times : (i64,i64) , last_two_slot : (u64, u64), last_two_prices: (i64, i64), - last_two_confs: (u64, u64))-> Result<(), OracleError>{ - - let epoch_gap = self.time_to_entry(last_two_times.1)? - self.time_to_entry(last_two_times.0)?; - - self.current_entry_weighted_price_accumulator += (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; - self.current_entry_slot_accumulator += (last_two_slot.1 - last_two_slot.0); + pub fn add_datapoint( + &mut self, + last_two_times: (i64, i64), + last_two_slot: (u64, u64), + last_two_prices: (i64, i64), + _last_two_confs: (u64, u64), + ) -> Result<(), OracleError> { + let epoch_0 = self.time_to_epoch(last_two_times.0)?; + let epoch_1 = self.time_to_epoch(last_two_times.1)?; + + self.current_entry_weighted_price_accumulator += + i128::from(last_two_slot.1 - last_two_slot.0) + * i128::from(last_two_prices.1 + last_two_prices.0) + / 2; + self.current_entry_slot_accumulator += last_two_slot.1 - last_two_slot.0; if (last_two_slot.1 - last_two_slot.0) > self.threshold { self.current_entry_status = Status::Invalid; } - for i in last_two_times.0+1..last_two_times.1 { + for i in epoch_0 + 1..epoch_1 { self.initialize_epoch(i); - self.current_entry_weighted_price_accumulator += (last_two_slot.1 - last_two_slot.0) as i64 * (last_two_prices.1 + last_two_prices.0) / 2; - self.current_entry_slot_accumulator += (last_two_slot.1 - last_two_slot.0); + self.current_entry_weighted_price_accumulator += + i128::from(last_two_slot.1 - last_two_slot.0) + * (i128::from(last_two_prices.1) + i128::from(last_two_prices.0)) + / 2; + self.current_entry_slot_accumulator += last_two_slot.1 - last_two_slot.0; if (last_two_slot.1 - last_two_slot.0) > self.threshold { self.current_entry_status = Status::Invalid; } } - - - - Ok(()) } + + pub fn initialize_epoch(&mut self, epoch: usize) { + let index = epoch % NUM_ENTRIES; + let prev_index = (epoch - 1) % NUM_ENTRIES; + if self.current_entry_status == Status::Valid { + self.running_valid_entry_counter[index] = + self.running_valid_entry_counter[prev_index] + 1; + } + self.running_entry_prices[epoch] = self.running_entry_prices[prev_index] + + self.current_entry_weighted_price_accumulator + / i128::from(self.current_entry_slot_accumulator); + self.current_entry_slot_accumulator = 0; + self.current_entry_weighted_price_accumulator = 0; + self.current_entry_status = Status::Valid; + } } #[cfg(target_endian = "little")] From d5fdb7d141360c70b0d4f2b1d5523ecb610496c4 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Thu, 1 Sep 2022 20:07:31 -0500 Subject: [PATCH 04/30] Wrote tests --- program/rust/Cargo.toml | 2 + program/rust/src/tests/mod.rs | 1 + program/rust/src/tests/test_sma.rs | 297 +++++++++++++++++++++++++ program/rust/src/time_machine_types.rs | 176 +++++++++------ 4 files changed, 408 insertions(+), 68 deletions(-) create mode 100644 program/rust/src/tests/test_sma.rs diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index 3994f6d23..d30afb330 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -20,6 +20,8 @@ solana-program-test = "=1.10.29" solana-sdk = "=1.10.29" tokio = "1.14.1" hex = "0.3.1" +quickcheck = "1" +quickcheck_macros = "1" [features] debug = [] diff --git a/program/rust/src/tests/mod.rs b/program/rust/src/tests/mod.rs index 060746f11..315bc1370 100644 --- a/program/rust/src/tests/mod.rs +++ b/program/rust/src/tests/mod.rs @@ -11,6 +11,7 @@ mod test_init_price; mod test_resize_account; mod test_set_min_pub; mod test_sizes; +mod test_sma; mod test_upd_aggregate; mod test_upd_price; mod test_upd_price_no_fail_on_error; diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs new file mode 100644 index 000000000..6eddb2596 --- /dev/null +++ b/program/rust/src/tests/test_sma.rs @@ -0,0 +1,297 @@ +use quickcheck::Arbitrary; +use quickcheck_macros::quickcheck; +use solana_program::nonce::state::Data; +use std::collections::BTreeMap; +use std::mem::{ + align_of, + size_of, +}; + +use crate::c_oracle_header::PriceAccount; +use crate::time_machine_types::{ + PriceAccountWrapper, + SmaTracker, + TimeMachineWrapper, + THIRTY_MINUTES, +}; + +// #[test] +// fn unit_tests() { +// let mut tracker = SmaTracker::<10> { +// granularity : 10, +// threshold : TWENTY_SECONDS, +// current_epoch_denominator : 0, +// current_epoch_is_valid : false, +// current_epoch_numerator : 0, +// running_valid_entry_counter: [0u64; 10], +// running_sum_of_price_averages : [0i128; 10], +// }; + +// for i in 0u32..6000 { +// tracker.add_datapoint((i64::from(i), i64::from(i+1)), 1 , 20, (0,0)).unwrap(); +// } + +// println!("{:?}", tracker); + +// tracker.add_datapoint((6000, 6010), 21, 30, (0,0)).unwrap(); +// println!("{:?}", tracker); +// tracker.add_datapoint((6010, 6080), 100, 30, (0,0)).unwrap(); +// println!("{:?}", tracker); + +// // let mut tracker2 = SmaTracker::<48> { +// // granularity : THIRTY_MINUTES, +// // threshold : 20, +// // current_epoch_denominator : 0, +// // current_epoch_is_valid : false, +// // current_epoch_numerator : 0, +// // running_valid_entry_counter: [0u64; 48], +// // running_sum_of_price_averages : [0i128; 48], +// // }; + +// // for i in 0u32..6000 { +// // tracker2.add_datapoint((i64::from(i* 20), i64::from((i+1) * 20)), (u64::from(i* 21), +// u64::from((i+1) * 21)), (20, 20), (0,0)).unwrap(); // } +// // println!("{:?}", tracker2); +// // for i in 6000u32..6180 { +// // tracker2.add_datapoint((i64::from(i* 20), i64::from((i+1) * 20)), (u64::from(i) + +// 126000, u64::from(i+1) + 126000), (20, 20), (0,0)).unwrap(); // } + + +// // println!("{:?}", tracker2); +// // println!("{:?}", tracker2.running_sum_of_price_averages[19]); +// // println!("{:?}", tracker2.running_valid_entry_counter[19]); + + +// // let tracker : & mut SmaTracker<48> = bytemuck::from_bytes_mut(&mut buffer.as_ptr()); +// // unsafe{ +// // println!("{:?}", buffer.as_ptr() as usize); +// // println!("{:?}", align_of::>()); +// // println!("{:?}", align_of::()); +// // println!("{:?}", align_of::()); + +// // } +// // tracker.initialize(THIRTY_MINUTES, TWENTY_SECONDS); + +// } + +#[derive(Clone, Debug, Copy)] +struct DataEvent { + timegap: i64, + slot_gap: u64, + price: i64, +} + +#[derive(Debug)] +pub struct DataPoint { + last_two_times: (i64, i64), + slot_gap: u64, + price: i64, +} + +impl Arbitrary for DataEvent { + fn arbitrary(g: &mut quickcheck::Gen) -> Self { + DataEvent { + timegap: i64::from(u8::arbitrary(g)), + slot_gap: u64::from(u8::arbitrary(g)) + 1, + price: i64::arbitrary(g), + } + } +} + +#[quickcheck] +fn test_add_and_delete(input: Vec) -> bool { + // No gaps, no skipped epochs + let mut tracker1 = SmaTracker::<10> { + granularity: 0, + threshold: 0, + current_epoch_denominator: 0, + current_epoch_is_valid: false, + current_epoch_numerator: 0, + running_valid_entry_counter: [0u64; 10], + running_sum_of_price_averages: [0i128; 10], + }; + + tracker1.initialize(i64::from(u8::MAX), u64::from(u8::MAX)); + + // Likely skipped, no gaps + let mut tracker2 = SmaTracker::<10> { + granularity: 0, + threshold: 0, + current_epoch_denominator: 0, + current_epoch_is_valid: false, + current_epoch_numerator: 0, + running_valid_entry_counter: [0u64; 10], + running_sum_of_price_averages: [0i128; 10], + }; + + tracker2.initialize(i64::from(u8::MAX / 5), u64::from(u8::MAX / 5)); + + // Gaps + let mut tracker3 = SmaTracker::<10> { + granularity: 0, + threshold: 0, + current_epoch_denominator: 0, + current_epoch_is_valid: false, + current_epoch_numerator: 0, + running_valid_entry_counter: [0u64; 10], + running_sum_of_price_averages: [0i128; 10], + }; + + tracker3.initialize(i64::from(u8::MAX), u64::from(u8::MAX / 5)); + + let mut tracker4 = SmaTracker::<10> { + granularity: 0, + threshold: 0, + current_epoch_denominator: 0, + current_epoch_is_valid: false, + current_epoch_numerator: 0, + running_valid_entry_counter: [0u64; 10], + running_sum_of_price_averages: [0i128; 10], + }; + + tracker4.initialize(i64::from(u8::MAX / 5), 250); + + let mut tracker5 = SmaTracker::<10> { + granularity: 0, + threshold: 0, + current_epoch_denominator: 0, + current_epoch_is_valid: false, + current_epoch_numerator: 0, + running_valid_entry_counter: [0u64; 10], + running_sum_of_price_averages: [0i128; 10], + }; + + tracker5.initialize(1, u64::from(u8::MAX / 5)); + + let mut data = Vec::::new(); + + let mut initial_time = 0i64; + for data_event in input.clone() { + tracker1 + .add_datapoint( + (initial_time, initial_time + data_event.timegap), + data_event.slot_gap, + data_event.price, + (0, 0), + ) + .unwrap(); + tracker2 + .add_datapoint( + (initial_time, initial_time + data_event.timegap), + data_event.slot_gap, + data_event.price, + (0, 0), + ) + .unwrap(); + tracker3 + .add_datapoint( + (initial_time, initial_time + data_event.timegap), + data_event.slot_gap, + data_event.price, + (0, 0), + ) + .unwrap(); + + tracker4 + .add_datapoint( + (initial_time, initial_time + data_event.timegap), + data_event.slot_gap, + data_event.price, + (0, 0), + ) + .unwrap(); + tracker5 + .add_datapoint( + (initial_time, initial_time + data_event.timegap), + data_event.slot_gap, + data_event.price, + (0, 0), + ) + .unwrap(); + data.push(DataPoint { + last_two_times: (initial_time, initial_time + data_event.timegap), + slot_gap: data_event.slot_gap, + price: data_event.price, + }); + initial_time += data_event.timegap; + + check_epoch_fields(&tracker1, &data, initial_time); + check_epoch_fields(&tracker2, &data, initial_time); + check_epoch_fields(&tracker3, &data, initial_time); + check_epoch_fields(&tracker4, &data, initial_time); + check_epoch_fields(&tracker5, &data, initial_time); + + check_all_fields(&tracker1, &data, initial_time); + check_all_fields(&tracker2, &data, initial_time); + check_all_fields(&tracker3, &data, initial_time); + check_all_fields(&tracker4, &data, initial_time); + check_all_fields(&tracker5, &data, initial_time); + } + + + // println!("{:?}", tracker1); + + + return true; +} + +pub fn check_epoch_fields(tracker: &SmaTracker<10>, data: &Vec, time: i64) { + let last_epoch_1 = tracker.time_to_epoch(time).unwrap(); + + let result = compute_epoch_fields(tracker, data, last_epoch_1); + assert_eq!(tracker.current_epoch_denominator, result.0); + assert_eq!(tracker.current_epoch_numerator, result.1); + assert_eq!(tracker.current_epoch_is_valid, result.2); +} +pub fn check_all_fields(tracker: &SmaTracker<10>, data: &Vec, time: i64) { + let last_epoch_1 = tracker.time_to_epoch(time).unwrap(); + let mut values = vec![]; + + for i in 0..last_epoch_1 { + values.push(compute_epoch_fields(tracker, data, i)); + } + + let iter = values.iter().scan(0, |state, &y| { + *state = *state + y.1.clone() / i128::from(y.0.clone()); + Some(*state) + }); + + let mut i = (last_epoch_1 + 9) % 10; + + let collected = iter.collect::>(); + for x in collected.iter().rev().take(9) { + assert_eq!(tracker.running_sum_of_price_averages[i], *x); + i = (i + 9) % 10; + } +} + +pub fn compute_epoch_fields( + tracker: &SmaTracker<10>, + data: &Vec, + epoch_number: usize, +) -> (u64, i128, bool) { + let left_bound = epoch_number + .checked_mul(tracker.granularity.try_into().unwrap()) + .unwrap(); + + let right_bound = (epoch_number + 1) + .checked_mul(tracker.granularity.try_into().unwrap()) + .unwrap(); + + + let result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { + if y.last_two_times.0 == y.last_two_times.1 {} + if !((left_bound > y.last_two_times.1.try_into().unwrap()) + || (right_bound <= y.last_two_times.0.try_into().unwrap())) + { + let is_valid = y.slot_gap <= tracker.threshold; + return ( + x.0 + y.slot_gap, + x.1 + i128::from(y.slot_gap) * i128::from(y.price), + x.2 && is_valid, + ); + } + return x; + }); + return result; +} diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 4a39d348c..38f5855f8 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_MAX_SEND_LATENCY, PC_PRICE_T_COMP_OFFSET, }; use crate::error::OracleError; @@ -34,30 +35,24 @@ pub struct PriceAccountWrapper { } impl PriceAccountWrapper { pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { - self.time_machine.initialize(THIRTY_MINUTES, TWENTY_SECONDS); + self.time_machine + .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY.into()); Ok(()) } pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { self.time_machine.add_datapoint( (self.price_data.prev_timestamp_, self.price_data.timestamp_), - (self.price_data.prev_slot_, self.price_data.last_slot_), - (self.price_data.prev_price_, self.price_data.agg_.price_), + self.price_data.last_slot_ - self.price_data.prev_slot_, + (self.price_data.prev_price_ + self.price_data.agg_.price_) / 2, (0, 0), )?; Ok(()) } } -const TWENTY_SECONDS: u64 = 20; -const THIRTY_MINUTES: i64 = 30 * 60; +pub const THIRTY_MINUTES: i64 = 30 * 60; -#[repr(u8)] -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -pub enum Status { - Invalid = 0, - Valid = 1, -} #[derive(Debug, Copy, Clone)] #[repr(C)] @@ -68,33 +63,33 @@ pub enum Status { /// Assumes threshold < granularity /// Both threshold and granularity are set on initialization pub struct SmaTracker { - pub threshold: u64, /* the maximum slot gap we are willing - * to accept */ - pub granularity: i64, //the length of the time covered per entry - pub current_entry_slot_accumulator: u64, /* accumulates the number of slots that - * went into the - * weights of the current entry, reset - * to 0 before - * moving to the next one */ - pub current_entry_status: Status, /* the status of the current entry, - * INVALID if an update takes too - * long, PENDING if it is still being - * updated but the updates have been - * consistent so far. */ - pub current_entry_weighted_price_accumulator: i128, /* accumulates - * slot_delta * - * (inflated_p1 + - * inflated_p2) / 2 - * to compute - * averages */ - pub running_entry_prices: [i128; NUM_ENTRIES], /* A running sum of the - * slot weighted average - * of each entry. */ - pub running_valid_entry_counter: [u64; NUM_ENTRIES], /* Each entry - * increment the - * counter of the - * previous one if - * it is valid */ + pub threshold: u64, /* the maximum slot gap we are willing + * to accept */ + pub granularity: i64, //the length of the time covered per entry + pub current_epoch_numerator: i128, /* accumulates + * slot_delta * + * (inflated_p1 + + * inflated_p2) / 2 + * to compute + * averages */ + pub current_epoch_denominator: u64, /* accumulates the number of slots that + * went into the + * weights of the current entry, reset + * to 0 before + * moving to the next one */ + pub current_epoch_is_valid: bool, /* the status of the current entry, + * * INVALID if an update takes too + * * long, PENDING if it is still being + * * updated but the updates have been + * * consistent so far. */ + pub running_sum_of_price_averages: [i128; NUM_ENTRIES], /* A running sum of the + * slot weighted average + * of each entry. */ + pub running_valid_entry_counter: [u64; NUM_ENTRIES], /* Each entry + * * increment the + * * counter of the + * * previous one if + * * it is valid */ } impl SmaTracker { @@ -106,57 +101,94 @@ impl SmaTracker { pub fn initialize(&mut self, granularity: i64, threshold: u64) { self.threshold = threshold; self.granularity = granularity; + self.current_epoch_is_valid = true; } pub fn add_datapoint( &mut self, last_two_times: (i64, i64), - last_two_slot: (u64, u64), - last_two_prices: (i64, i64), + slot_gap: u64, + price_to_be_added: i64, _last_two_confs: (u64, u64), ) -> Result<(), OracleError> { let epoch_0 = self.time_to_epoch(last_two_times.0)?; let epoch_1 = self.time_to_epoch(last_two_times.1)?; - self.current_entry_weighted_price_accumulator += - i128::from(last_two_slot.1 - last_two_slot.0) - * i128::from(last_two_prices.1 + last_two_prices.0) - / 2; - self.current_entry_slot_accumulator += last_two_slot.1 - last_two_slot.0; - if (last_two_slot.1 - last_two_slot.0) > self.threshold { - self.current_entry_status = Status::Invalid; - } + let datapoint_numerator = i128::from(slot_gap) * i128::from(price_to_be_added); + let datapoint_denominator = slot_gap; + + self.current_epoch_denominator += datapoint_denominator; + self.current_epoch_numerator += datapoint_numerator; + self.current_epoch_is_valid = + self.current_epoch_is_valid && datapoint_denominator <= self.threshold; - for i in epoch_0 + 1..epoch_1 { - self.initialize_epoch(i); - self.current_entry_weighted_price_accumulator += - i128::from(last_two_slot.1 - last_two_slot.0) - * (i128::from(last_two_prices.1) + i128::from(last_two_prices.0)) - / 2; - self.current_entry_slot_accumulator += last_two_slot.1 - last_two_slot.0; - if (last_two_slot.1 - last_two_slot.0) > self.threshold { - self.current_entry_status = Status::Invalid; - } + // Next epoch transition + for i in epoch_0..epoch_1 { + self.conclude_epoch_and_initialize_next(i, datapoint_numerator, datapoint_denominator); + self.current_epoch_is_valid = datapoint_denominator <= self.threshold; } Ok(()) } - pub fn initialize_epoch(&mut self, epoch: usize) { + // pub fn update_skipped_epochs(&mut self, epoch_0: usize, epoch_1 :usize, + // datapoint_average:i128){ + + // for i in epoch_0+1..cmp::min(epoch_0 + NUM_ENTRIES, epoch_1){ + // let index = i % NUM_ENTRIES; + // let prev_index = (i + (NUM_ENTRIES - 1)) % NUM_ENTRIES; + + // self.running_sum_of_price_averages[index] = + // self.running_sum_of_price_averages[prev_index] + datapoint_average; } + + // if epoch_1 > epoch_0 + NUM_ENTRIES{ + // for i in 0..NUM_ENTRIES { + // let times_skipped = self.get_times_skipped(i, epoch_0, epoch_1); + // if times_skipped > 1 { + // self.running_sum_of_price_averages[i] = self.running_sum_of_price_averages[i] + // + datapoint_average * (times_skipped as i128 -1); + // } + // } + // } + // } + + + pub fn conclude_epoch_and_initialize_next( + &mut self, + epoch: usize, + datapoint_numerator: i128, + datapoint_denominator: u64, + ) { let index = epoch % NUM_ENTRIES; - let prev_index = (epoch - 1) % NUM_ENTRIES; - if self.current_entry_status == Status::Valid { + let prev_index = (epoch + (NUM_ENTRIES - 1)) % NUM_ENTRIES; + + self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] + + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); + + if self.current_epoch_is_valid { self.running_valid_entry_counter[index] = self.running_valid_entry_counter[prev_index] + 1; - } - self.running_entry_prices[epoch] = self.running_entry_prices[prev_index] - + self.current_entry_weighted_price_accumulator - / i128::from(self.current_entry_slot_accumulator); - self.current_entry_slot_accumulator = 0; - self.current_entry_weighted_price_accumulator = 0; - self.current_entry_status = Status::Valid; + } else { + self.running_valid_entry_counter[index] = self.running_valid_entry_counter[prev_index] + }; + + self.current_epoch_denominator = datapoint_denominator; + self.current_epoch_numerator = datapoint_numerator; } + + // pub fn get_times_skipped(&self, i : usize, epoch_0 : usize, epoch_1 : usize) -> usize{ + // let base = epoch_1 - epoch_0 / NUM_ENTRIES; + // let remainder_0 = epoch_0 % NUM_ENTRIES; + // let remainder_1 = epoch_1 % NUM_ENTRIES; + // let is_included = (remainder_0 < i && i < remainder_1) || (remainder_0 >= remainder_1) && + // (i < remainder_1 ) && (remainder_0 < i); if is_included { + // return base; + // } else { + // return base +1; + // } + // } } + #[cfg(target_endian = "little")] unsafe impl Zeroable for PriceAccountWrapper { } @@ -165,6 +197,14 @@ unsafe impl Zeroable for PriceAccountWrapper { unsafe impl Pod for PriceAccountWrapper { } +#[cfg(target_endian = "little")] +unsafe impl Zeroable for SmaTracker<48> { +} + +#[cfg(target_endian = "little")] +unsafe impl Pod for SmaTracker<48> { +} + impl PythAccount for PriceAccountWrapper { const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; const INITIAL_SIZE: u32 = PC_PRICE_T_COMP_OFFSET as u32; From 424997c98a5748f6bc392bddb7091283dd153413 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Thu, 1 Sep 2022 20:42:05 -0500 Subject: [PATCH 05/30] some comments --- program/rust/src/tests/test_sizes.rs | 7 ++ program/rust/src/tests/test_sma.rs | 10 +-- program/rust/src/time_machine_types.rs | 90 ++++++-------------------- 3 files changed, 31 insertions(+), 76 deletions(-) diff --git a/program/rust/src/tests/test_sizes.rs b/program/rust/src/tests/test_sizes.rs index d4de35bf8..83ec2319a 100644 --- a/program/rust/src/tests/test_sizes.rs +++ b/program/rust/src/tests/test_sizes.rs @@ -121,3 +121,10 @@ fn test_pubkey() { "4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM" ); } +#[test] +fn test_check() { + let a = u64::MAX; + let b = i64::MAX; + let c = i128::MAX / i128::from(i64::MAX); + println!("{:?}", c); +} diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index 6eddb2596..ec926c0db 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -107,7 +107,7 @@ fn test_add_and_delete(input: Vec) -> bool { current_epoch_denominator: 0, current_epoch_is_valid: false, current_epoch_numerator: 0, - running_valid_entry_counter: [0u64; 10], + running_valid_epoch_counter: [0u64; 10], running_sum_of_price_averages: [0i128; 10], }; @@ -120,7 +120,7 @@ fn test_add_and_delete(input: Vec) -> bool { current_epoch_denominator: 0, current_epoch_is_valid: false, current_epoch_numerator: 0, - running_valid_entry_counter: [0u64; 10], + running_valid_epoch_counter: [0u64; 10], running_sum_of_price_averages: [0i128; 10], }; @@ -133,7 +133,7 @@ fn test_add_and_delete(input: Vec) -> bool { current_epoch_denominator: 0, current_epoch_is_valid: false, current_epoch_numerator: 0, - running_valid_entry_counter: [0u64; 10], + running_valid_epoch_counter: [0u64; 10], running_sum_of_price_averages: [0i128; 10], }; @@ -145,7 +145,7 @@ fn test_add_and_delete(input: Vec) -> bool { current_epoch_denominator: 0, current_epoch_is_valid: false, current_epoch_numerator: 0, - running_valid_entry_counter: [0u64; 10], + running_valid_epoch_counter: [0u64; 10], running_sum_of_price_averages: [0i128; 10], }; @@ -157,7 +157,7 @@ fn test_add_and_delete(input: Vec) -> bool { current_epoch_denominator: 0, current_epoch_is_valid: false, current_epoch_numerator: 0, - running_valid_entry_counter: [0u64; 10], + running_valid_epoch_counter: [0u64; 10], running_sum_of_price_averages: [0i128; 10], }; diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 38f5855f8..670e5f6c5 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -53,7 +53,6 @@ impl PriceAccountWrapper { pub const THIRTY_MINUTES: i64 = 30 * 60; - #[derive(Debug, Copy, Clone)] #[repr(C)] /// Represents a Simple Moving Average Tracker Tracker that has NUM_ENTRIES entries @@ -63,37 +62,16 @@ pub const THIRTY_MINUTES: i64 = 30 * 60; /// Assumes threshold < granularity /// Both threshold and granularity are set on initialization pub struct SmaTracker { - pub threshold: u64, /* the maximum slot gap we are willing - * to accept */ - pub granularity: i64, //the length of the time covered per entry - pub current_epoch_numerator: i128, /* accumulates - * slot_delta * - * (inflated_p1 + - * inflated_p2) / 2 - * to compute - * averages */ - pub current_epoch_denominator: u64, /* accumulates the number of slots that - * went into the - * weights of the current entry, reset - * to 0 before - * moving to the next one */ - pub current_epoch_is_valid: bool, /* the status of the current entry, - * * INVALID if an update takes too - * * long, PENDING if it is still being - * * updated but the updates have been - * * consistent so far. */ - pub running_sum_of_price_averages: [i128; NUM_ENTRIES], /* A running sum of the - * slot weighted average - * of each entry. */ - pub running_valid_entry_counter: [u64; NUM_ENTRIES], /* Each entry - * * increment the - * * counter of the - * * previous one if - * * it is valid */ + pub threshold: u64, + pub granularity: i64, + pub current_epoch_numerator: i128, + pub current_epoch_denominator: u64, + pub current_epoch_is_valid: bool, + pub running_sum_of_price_averages: [i128; NUM_ENTRIES], + pub running_valid_epoch_counter: [u64; NUM_ENTRIES], } impl SmaTracker { - /// Should never fail because time is positive and usize = u64 pub fn time_to_epoch(&self, time: i64) -> Result { try_convert::(time / self.granularity) } @@ -114,15 +92,19 @@ impl SmaTracker { let epoch_0 = self.time_to_epoch(last_two_times.0)?; let epoch_1 = self.time_to_epoch(last_two_times.1)?; - let datapoint_numerator = i128::from(slot_gap) * i128::from(price_to_be_added); + let datapoint_numerator = i128::from(slot_gap) * i128::from(price_to_be_added); //Can't overflow because u64::MAX * i64::MAX = i28::MAX let datapoint_denominator = slot_gap; + // Can't overflow, it's always smaller than the current solana slot self.current_epoch_denominator += datapoint_denominator; + // Can't overflow, it's always smaller than u64::MAX * i64::MAX = i28::MAX self.current_epoch_numerator += datapoint_numerator; self.current_epoch_is_valid = self.current_epoch_is_valid && datapoint_denominator <= self.threshold; - // Next epoch transition + // This for loop is highly inefficient, but this is what the behavior should be + // It updated all the epochs that got skipped + // This will allow unchecked requests to be fullfilled for i in epoch_0..epoch_1 { self.conclude_epoch_and_initialize_next(i, datapoint_numerator, datapoint_denominator); self.current_epoch_is_valid = datapoint_denominator <= self.threshold; @@ -130,28 +112,6 @@ impl SmaTracker { Ok(()) } - // pub fn update_skipped_epochs(&mut self, epoch_0: usize, epoch_1 :usize, - // datapoint_average:i128){ - - // for i in epoch_0+1..cmp::min(epoch_0 + NUM_ENTRIES, epoch_1){ - // let index = i % NUM_ENTRIES; - // let prev_index = (i + (NUM_ENTRIES - 1)) % NUM_ENTRIES; - - // self.running_sum_of_price_averages[index] = - // self.running_sum_of_price_averages[prev_index] + datapoint_average; } - - // if epoch_1 > epoch_0 + NUM_ENTRIES{ - // for i in 0..NUM_ENTRIES { - // let times_skipped = self.get_times_skipped(i, epoch_0, epoch_1); - // if times_skipped > 1 { - // self.running_sum_of_price_averages[i] = self.running_sum_of_price_averages[i] - // + datapoint_average * (times_skipped as i128 -1); - // } - // } - // } - // } - - pub fn conclude_epoch_and_initialize_next( &mut self, epoch: usize, @@ -159,36 +119,24 @@ impl SmaTracker { datapoint_denominator: u64, ) { let index = epoch % NUM_ENTRIES; - let prev_index = (epoch + (NUM_ENTRIES - 1)) % NUM_ENTRIES; + let prev_index = (epoch.wrapping_sub(1)) % NUM_ENTRIES; - self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] + self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] // This buffer will be able to support u64::MAX epochs, no one will be alive when it overflows + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); if self.current_epoch_is_valid { - self.running_valid_entry_counter[index] = - self.running_valid_entry_counter[prev_index] + 1; + self.running_valid_epoch_counter[index] = + self.running_valid_epoch_counter[prev_index] + 1; // Likewise can support u64::MAX + // epochs } else { - self.running_valid_entry_counter[index] = self.running_valid_entry_counter[prev_index] + self.running_valid_epoch_counter[index] = self.running_valid_epoch_counter[prev_index] }; self.current_epoch_denominator = datapoint_denominator; self.current_epoch_numerator = datapoint_numerator; } - - // pub fn get_times_skipped(&self, i : usize, epoch_0 : usize, epoch_1 : usize) -> usize{ - // let base = epoch_1 - epoch_0 / NUM_ENTRIES; - // let remainder_0 = epoch_0 % NUM_ENTRIES; - // let remainder_1 = epoch_1 % NUM_ENTRIES; - // let is_included = (remainder_0 < i && i < remainder_1) || (remainder_0 >= remainder_1) && - // (i < remainder_1 ) && (remainder_0 < i); if is_included { - // return base; - // } else { - // return base +1; - // } - // } } - #[cfg(target_endian = "little")] unsafe impl Zeroable for PriceAccountWrapper { } From 7fb12c2b37d7e9b3cf255bd1bf54cfae6fa5c359 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Thu, 1 Sep 2022 23:34:53 -0500 Subject: [PATCH 06/30] Cleanup --- program/rust/src/rust_oracle.rs | 16 +- program/rust/src/tests/test_resize_account.rs | 6 +- program/rust/src/tests/test_sizes.rs | 4 +- program/rust/src/tests/test_sma.rs | 286 +++++++----------- program/rust/src/time_machine_types.rs | 130 ++++---- 5 files changed, 176 insertions(+), 266 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index 76cc4828a..b8ee15e60 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -32,7 +32,7 @@ use crate::instruction::{ SetMinPubArgs, UpdPriceArgs, }; -use crate::time_machine_types::PriceAccountWrapper; +use crate::time_machine_types::PriceAccountExtended; use crate::utils::{ check_exponent_range, check_valid_funding_account, @@ -61,7 +61,7 @@ use solana_program::system_program::check_id; use solana_program::sysvar::Sysvar; const PRICE_T_SIZE: usize = size_of::(); -const PRICE_ACCOUNT_SIZE: usize = size_of::(); +const PRICE_ACCOUNT_SIZE: usize = size_of::(); #[cfg(target_arch = "bpf")] @@ -120,7 +120,7 @@ pub fn resize_price_account( // Ensure account is still rent exempt after resizing let rent: Rent = Default::default(); let lamports_needed: u64 = rent - .minimum_balance(size_of::()) + .minimum_balance(size_of::()) .saturating_sub(price_account_info.lamports()); if lamports_needed > 0 { send_lamports( @@ -132,14 +132,14 @@ pub fn resize_price_account( } // We do not need to zero allocate because we won't access the data in the same // instruction - price_account_info.realloc(size_of::(), false)?; + price_account_info.realloc(size_of::(), false)?; // Check that everything is ok check_valid_signable_account(program_id, price_account_info)?; let mut price_account = - load_checked::(price_account_info, PC_VERSION)?; + load_checked::(price_account_info, PC_VERSION)?; // Initialize Time Machine - price_account.initialize_time_machine()?; + price_account.initialize()?; Ok(()) } PRICE_ACCOUNT_SIZE => Ok(()), @@ -266,8 +266,8 @@ pub fn upd_price( let account_len = price_account.try_data_len()?; if aggregate_updated && account_len == PRICE_ACCOUNT_SIZE { let mut price_account = - load_checked::(price_account, cmd_args.header.version)?; - price_account.add_price_to_time_machine()?; + load_checked::(price_account, cmd_args.header.version)?; + price_account.add_datapoint()?; } // Try to update the publisher's price diff --git a/program/rust/src/tests/test_resize_account.rs b/program/rust/src/tests/test_resize_account.rs index a1d5b46bb..28a8371fa 100644 --- a/program/rust/src/tests/test_resize_account.rs +++ b/program/rust/src/tests/test_resize_account.rs @@ -3,7 +3,7 @@ use std::mem::size_of; use crate::c_oracle_header::pc_price_t; use crate::tests::pyth_simulator::PythSimulator; -use crate::time_machine_types::PriceAccountWrapper; +use crate::time_machine_types::PriceAccountExtended; /// Warning : This test will fail if you run cargo test instead of cargo test-bpf @@ -22,10 +22,10 @@ async fn test_resize_account() { assert!(sim.resize_price_account(&price1).await.is_ok()); // Check new size let price1_account = sim.get_account(price1.pubkey()).await.unwrap(); - assert_eq!(price1_account.data.len(), size_of::()); + assert_eq!(price1_account.data.len(), size_of::()); // Future calls don't change the size assert!(sim.resize_price_account(&price1).await.is_ok()); let price1_account = sim.get_account(price1.pubkey()).await.unwrap(); - assert_eq!(price1_account.data.len(), size_of::()); + assert_eq!(price1_account.data.len(), size_of::()); } diff --git a/program/rust/src/tests/test_sizes.rs b/program/rust/src/tests/test_sizes.rs index 83ec2319a..52936a3ff 100644 --- a/program/rust/src/tests/test_sizes.rs +++ b/program/rust/src/tests/test_sizes.rs @@ -27,7 +27,7 @@ use crate::instruction::{ UpdPriceArgs, }; use crate::tests::test_utils::AccountSetup; -use crate::time_machine_types::PriceAccountWrapper; +use crate::time_machine_types::PriceAccountExtended; use crate::utils::try_convert; use solana_program::pubkey::Pubkey; use std::mem::{ @@ -69,7 +69,7 @@ fn test_sizes() { assert_eq!(size_of::(), 24); assert_eq!(size_of::(), 3312); assert_eq!( - size_of::(), + size_of::(), try_convert::<_, usize>(PRICE_ACCOUNT_SIZE).unwrap() ); } diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index ec926c0db..d65be31a6 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -9,9 +9,10 @@ use std::mem::{ use crate::c_oracle_header::PriceAccount; use crate::time_machine_types::{ - PriceAccountWrapper, + DataPoint, + PriceAccountExtended, SmaTracker, - TimeMachineWrapper, + NUM_BUCKETS_THIRTY_MIN, THIRTY_MINUTES, }; @@ -81,13 +82,6 @@ struct DataEvent { price: i64, } -#[derive(Debug)] -pub struct DataPoint { - last_two_times: (i64, i64), - slot_gap: u64, - price: i64, -} - impl Arbitrary for DataEvent { fn arbitrary(g: &mut quickcheck::Gen) -> Self { DataEvent { @@ -98,200 +92,144 @@ impl Arbitrary for DataEvent { } } + #[quickcheck] fn test_add_and_delete(input: Vec) -> bool { // No gaps, no skipped epochs - let mut tracker1 = SmaTracker::<10> { - granularity: 0, - threshold: 0, - current_epoch_denominator: 0, - current_epoch_is_valid: false, - current_epoch_numerator: 0, - running_valid_epoch_counter: [0u64; 10], - running_sum_of_price_averages: [0i128; 10], - }; - + let mut tracker1 = SmaTracker::::zero(); tracker1.initialize(i64::from(u8::MAX), u64::from(u8::MAX)); - // Likely skipped, no gaps - let mut tracker2 = SmaTracker::<10> { - granularity: 0, - threshold: 0, - current_epoch_denominator: 0, - current_epoch_is_valid: false, - current_epoch_numerator: 0, - running_valid_epoch_counter: [0u64; 10], - running_sum_of_price_averages: [0i128; 10], - }; - + // Skipped and gaps + let mut tracker2 = SmaTracker::::zero(); tracker2.initialize(i64::from(u8::MAX / 5), u64::from(u8::MAX / 5)); - // Gaps - let mut tracker3 = SmaTracker::<10> { - granularity: 0, - threshold: 0, - current_epoch_denominator: 0, - current_epoch_is_valid: false, - current_epoch_numerator: 0, - running_valid_epoch_counter: [0u64; 10], - running_sum_of_price_averages: [0i128; 10], - }; - + // Gaps, no skips + let mut tracker3 = SmaTracker::::zero(); tracker3.initialize(i64::from(u8::MAX), u64::from(u8::MAX / 5)); - let mut tracker4 = SmaTracker::<10> { - granularity: 0, - threshold: 0, - current_epoch_denominator: 0, - current_epoch_is_valid: false, - current_epoch_numerator: 0, - running_valid_epoch_counter: [0u64; 10], - running_sum_of_price_averages: [0i128; 10], - }; - - tracker4.initialize(i64::from(u8::MAX / 5), 250); - - let mut tracker5 = SmaTracker::<10> { - granularity: 0, - threshold: 0, - current_epoch_denominator: 0, - current_epoch_is_valid: false, - current_epoch_numerator: 0, - running_valid_epoch_counter: [0u64; 10], - running_sum_of_price_averages: [0i128; 10], - }; + // No skips, gaps + let mut tracker4 = SmaTracker::::zero(); + tracker4.initialize(i64::from(u8::MAX), u64::from(u8::MAX / 5) * 4); + // Each epoch is 1 second + let mut tracker5 = SmaTracker::::zero(); tracker5.initialize(1, u64::from(u8::MAX / 5)); let mut data = Vec::::new(); - let mut initial_time = 0i64; + let mut current_time = 0i64; for data_event in input.clone() { - tracker1 - .add_datapoint( - (initial_time, initial_time + data_event.timegap), - data_event.slot_gap, - data_event.price, - (0, 0), - ) - .unwrap(); - tracker2 - .add_datapoint( - (initial_time, initial_time + data_event.timegap), - data_event.slot_gap, - data_event.price, - (0, 0), - ) - .unwrap(); - tracker3 - .add_datapoint( - (initial_time, initial_time + data_event.timegap), - data_event.slot_gap, - data_event.price, - (0, 0), - ) - .unwrap(); - - tracker4 - .add_datapoint( - (initial_time, initial_time + data_event.timegap), - data_event.slot_gap, - data_event.price, - (0, 0), - ) - .unwrap(); - tracker5 - .add_datapoint( - (initial_time, initial_time + data_event.timegap), - data_event.slot_gap, - data_event.price, - (0, 0), - ) - .unwrap(); - data.push(DataPoint { - last_two_times: (initial_time, initial_time + data_event.timegap), - slot_gap: data_event.slot_gap, - price: data_event.price, - }); - initial_time += data_event.timegap; - - check_epoch_fields(&tracker1, &data, initial_time); - check_epoch_fields(&tracker2, &data, initial_time); - check_epoch_fields(&tracker3, &data, initial_time); - check_epoch_fields(&tracker4, &data, initial_time); - check_epoch_fields(&tracker5, &data, initial_time); - - check_all_fields(&tracker1, &data, initial_time); - check_all_fields(&tracker2, &data, initial_time); - check_all_fields(&tracker3, &data, initial_time); - check_all_fields(&tracker4, &data, initial_time); - check_all_fields(&tracker5, &data, initial_time); + let datapoint = DataPoint { + last_two_timestamps: (current_time, current_time + data_event.timegap), + slot_gap: data_event.slot_gap, + price: data_event.price, + }; + + tracker1.add_datapoint(&datapoint).unwrap(); + tracker2.add_datapoint(&datapoint).unwrap(); + tracker3.add_datapoint(&datapoint).unwrap(); + + tracker4.add_datapoint(&datapoint).unwrap(); + tracker5.add_datapoint(&datapoint).unwrap(); + data.push(datapoint); + current_time += data_event.timegap; + + tracker1.check_current_epoch_fields(&data, current_time); + tracker2.check_current_epoch_fields(&data, current_time); + tracker3.check_current_epoch_fields(&data, current_time); + tracker4.check_current_epoch_fields(&data, current_time); + tracker5.check_current_epoch_fields(&data, current_time); + tracker1.check_array_fields(&data, current_time); + tracker2.check_array_fields(&data, current_time); + tracker3.check_array_fields(&data, current_time); + tracker4.check_array_fields(&data, current_time); + tracker5.check_array_fields(&data, current_time); } - - // println!("{:?}", tracker1); - - return true; } -pub fn check_epoch_fields(tracker: &SmaTracker<10>, data: &Vec, time: i64) { - let last_epoch_1 = tracker.time_to_epoch(time).unwrap(); - let result = compute_epoch_fields(tracker, data, last_epoch_1); - assert_eq!(tracker.current_epoch_denominator, result.0); - assert_eq!(tracker.current_epoch_numerator, result.1); - assert_eq!(tracker.current_epoch_is_valid, result.2); -} -pub fn check_all_fields(tracker: &SmaTracker<10>, data: &Vec, time: i64) { - let last_epoch_1 = tracker.time_to_epoch(time).unwrap(); - let mut values = vec![]; - - for i in 0..last_epoch_1 { - values.push(compute_epoch_fields(tracker, data, i)); +impl SmaTracker { + pub fn zero() -> Self { + return SmaTracker:: { + granularity: 0, + threshold: 0, + current_epoch_denominator: 0, + current_epoch_is_valid: false, + current_epoch_numerator: 0, + running_valid_epoch_counter: [0u64; NUM_ENTRIES], + running_sum_of_price_averages: [0i128; NUM_ENTRIES], + }; } - let iter = values.iter().scan(0, |state, &y| { - *state = *state + y.1.clone() / i128::from(y.0.clone()); - Some(*state) - }); + pub fn check_current_epoch_fields(&self, data: &Vec, time: i64) { + let curent_epoch = self.time_to_epoch(time).unwrap(); - let mut i = (last_epoch_1 + 9) % 10; - - let collected = iter.collect::>(); - for x in collected.iter().rev().take(9) { - assert_eq!(tracker.running_sum_of_price_averages[i], *x); - i = (i + 9) % 10; + let result = self.compute_epoch_expected_values(data, curent_epoch); + assert_eq!(self.current_epoch_denominator, result.0); + assert_eq!(self.current_epoch_numerator, result.1); + assert_eq!(self.current_epoch_is_valid, result.2); } -} -pub fn compute_epoch_fields( - tracker: &SmaTracker<10>, - data: &Vec, - epoch_number: usize, -) -> (u64, i128, bool) { - let left_bound = epoch_number - .checked_mul(tracker.granularity.try_into().unwrap()) - .unwrap(); + pub fn check_array_fields(&self, data: &Vec, time: i64) { + let current_epoch = self.time_to_epoch(time).unwrap(); + let mut values = vec![]; - let right_bound = (epoch_number + 1) - .checked_mul(tracker.granularity.try_into().unwrap()) - .unwrap(); + // Compute all epoch averages + for i in 0..current_epoch { + values.push(self.compute_epoch_expected_values(data, i)); + } + // Get running sums + let running_sum_price_iter = values.iter().scan((0, 0), |res, &y| { + res.0 = res.0 + y.1.clone() / i128::from(y.0.clone()); + res.1 = res.1 + u64::from(y.2); + Some(*res) + }); - let result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { - if y.last_two_times.0 == y.last_two_times.1 {} - if !((left_bound > y.last_two_times.1.try_into().unwrap()) - || (right_bound <= y.last_two_times.0.try_into().unwrap())) + // Compare to running_sum_of_price_averages + let mut i = (current_epoch + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); + for x in running_sum_price_iter + .collect::>() + .iter() + .rev() + .take(NUM_ENTRIES) { - let is_valid = y.slot_gap <= tracker.threshold; - return ( - x.0 + y.slot_gap, - x.1 + i128::from(y.slot_gap) * i128::from(y.price), - x.2 && is_valid, - ); + assert_eq!(self.running_sum_of_price_averages[i], x.0); + assert_eq!(self.running_valid_epoch_counter[i], x.1); + i = (i + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); } - return x; - }); - return result; + } + + pub fn compute_epoch_expected_values( + &self, + data: &Vec, + epoch_number: usize, + ) -> (u64, i128, bool) { + let left_bound = self + .granularity + .checked_mul(epoch_number.try_into().unwrap()) + .unwrap(); + + let right_bound = self + .granularity + .checked_mul((epoch_number + 1).try_into().unwrap()) + .unwrap(); + + + let result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { + if !((left_bound > y.last_two_timestamps.1) || (right_bound <= y.last_two_timestamps.0)) + { + let is_valid = y.slot_gap <= self.threshold; + return ( + x.0 + y.slot_gap, + x.1 + i128::from(y.slot_gap) * i128::from(y.price), + x.2 && is_valid, + ); + } + return x; + }); + return result; + } } diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 670e5f6c5..807d312e0 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -13,62 +13,55 @@ use bytemuck::{ Zeroable, }; -#[derive(Debug, Clone, Copy)] -#[repr(C)] -/// this wraps multiple SMA and tick trackers, and includes all the state -/// used by the time machine -pub struct TimeMachineWrapper { - //Place holder with the size of the fields I am planning to add - place_holder: [u8; 1864], -} - +pub const THIRTY_MINUTES: i64 = 30 * 60; +pub const NUM_BUCKETS_THIRTY_MIN: usize = 48; #[derive(Copy, Clone)] #[repr(C)] -/// wraps everything stored in a price account -pub struct PriceAccountWrapper { - //an instance of the c price_t type +pub struct PriceAccountExtended { + // An instance of price account pub price_data: PriceAccount, - //space for more publishers + /// Space for more publishers pub extra_publisher_space: [u8; EXTRA_PUBLISHER_SPACE as usize], - //TimeMachine - pub time_machine: SmaTracker<48>, + // TimeMachine + pub time_machine: SmaTracker, } -impl PriceAccountWrapper { - pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { + + +#[derive(Debug)] +pub struct DataPoint { + pub last_two_timestamps: (i64, i64), + pub slot_gap: u64, + pub price: i64, +} + +impl PriceAccountExtended { + pub fn initialize(&mut self) -> Result<(), OracleError> { self.time_machine .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY.into()); Ok(()) } - pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { - self.time_machine.add_datapoint( - (self.price_data.prev_timestamp_, self.price_data.timestamp_), - self.price_data.last_slot_ - self.price_data.prev_slot_, - (self.price_data.prev_price_ + self.price_data.agg_.price_) / 2, - (0, 0), + pub fn add_datapoint(&mut self) -> Result<(), OracleError> { + self.time_machine.add_datapoint( &DataPoint{ + last_two_timestamps : (self.price_data.prev_timestamp_, self.price_data.timestamp_), + slot_gap : (self.price_data.last_slot_ - self.price_data.prev_slot_), + price: self.price_data.prev_price_ /2 + self.price_data.agg_.price_ / 2 + (self.price_data.prev_price_ % 2) * (self.price_data.agg_.price_ % 2), // Hack to avoid overflow? + } )?; Ok(()) } } -pub const THIRTY_MINUTES: i64 = 30 * 60; - #[derive(Debug, Copy, Clone)] #[repr(C)] -/// Represents a Simple Moving Average Tracker Tracker that has NUM_ENTRIES entries -/// each tracking time weighted sums for granularity seconds periods. -///The prices are assumed to be provided under some fixed point representation, and the computation -/// guarantees accuracy up to the last decimal digit in the fixed point representation. -/// Assumes threshold < granularity -/// Both threshold and granularity are set on initialization -pub struct SmaTracker { +pub struct SmaTracker { pub threshold: u64, pub granularity: i64, pub current_epoch_numerator: i128, pub current_epoch_denominator: u64, pub current_epoch_is_valid: bool, - pub running_sum_of_price_averages: [i128; NUM_ENTRIES], - pub running_valid_epoch_counter: [u64; NUM_ENTRIES], + pub running_sum_of_price_averages: [i128; NUM_BUCKETS], + pub running_valid_epoch_counter: [u64; NUM_BUCKETS], } impl SmaTracker { @@ -82,18 +75,12 @@ impl SmaTracker { self.current_epoch_is_valid = true; } - pub fn add_datapoint( - &mut self, - last_two_times: (i64, i64), - slot_gap: u64, - price_to_be_added: i64, - _last_two_confs: (u64, u64), - ) -> Result<(), OracleError> { - let epoch_0 = self.time_to_epoch(last_two_times.0)?; - let epoch_1 = self.time_to_epoch(last_two_times.1)?; + pub fn add_datapoint(&mut self, datapoint: &DataPoint) -> Result<(), OracleError> { + let epoch_0 = self.time_to_epoch(datapoint.last_two_timestamps.0)?; + let epoch_1 = self.time_to_epoch(datapoint.last_two_timestamps.1)?; - let datapoint_numerator = i128::from(slot_gap) * i128::from(price_to_be_added); //Can't overflow because u64::MAX * i64::MAX = i28::MAX - let datapoint_denominator = slot_gap; + let datapoint_numerator = i128::from(datapoint.slot_gap) * i128::from(datapoint.price); //Can't overflow because u64::MAX * i64::MAX = i28::MAX + let datapoint_denominator = datapoint.slot_gap; // Can't overflow, it's always smaller than the current solana slot self.current_epoch_denominator += datapoint_denominator; @@ -103,8 +90,8 @@ impl SmaTracker { self.current_epoch_is_valid && datapoint_denominator <= self.threshold; // This for loop is highly inefficient, but this is what the behavior should be - // It updated all the epochs that got skipped - // This will allow unchecked requests to be fullfilled + // It updates all the epochs that got skipped + // This will always yield an estimate of the average, even for invalid epochs for i in epoch_0..epoch_1 { self.conclude_epoch_and_initialize_next(i, datapoint_numerator, datapoint_denominator); self.current_epoch_is_valid = datapoint_denominator <= self.threshold; @@ -118,16 +105,19 @@ impl SmaTracker { datapoint_numerator: i128, datapoint_denominator: u64, ) { - let index = epoch % NUM_ENTRIES; - let prev_index = (epoch.wrapping_sub(1)) % NUM_ENTRIES; + let index = epoch.rem_euclid(NUM_ENTRIES); + let prev_index = (epoch + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); - self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] // This buffer will be able to support u64::MAX epochs, no one will be alive when it overflows + // This buffer will be able to support u64::MAX epochs, no one will be alive when it + // overflows, that's because every epoch we add a number that's smaller than i64::MAX + self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); + // Likewise can support u64::MAX + // epochs if self.current_epoch_is_valid { self.running_valid_epoch_counter[index] = - self.running_valid_epoch_counter[prev_index] + 1; // Likewise can support u64::MAX - // epochs + self.running_valid_epoch_counter[prev_index] + 1; } else { self.running_valid_epoch_counter[index] = self.running_valid_epoch_counter[prev_index] }; @@ -138,58 +128,40 @@ impl SmaTracker { } #[cfg(target_endian = "little")] -unsafe impl Zeroable for PriceAccountWrapper { +unsafe impl Zeroable for PriceAccountExtended { } #[cfg(target_endian = "little")] -unsafe impl Pod for PriceAccountWrapper { +unsafe impl Pod for PriceAccountExtended { } #[cfg(target_endian = "little")] -unsafe impl Zeroable for SmaTracker<48> { +unsafe impl Zeroable for SmaTracker { } #[cfg(target_endian = "little")] -unsafe impl Pod for SmaTracker<48> { +unsafe impl Pod for SmaTracker { } -impl PythAccount for PriceAccountWrapper { +impl PythAccount for PriceAccountExtended { const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; const INITIAL_SIZE: u32 = PC_PRICE_T_COMP_OFFSET as u32; } #[cfg(test)] pub mod tests { - use crate::c_oracle_header::{ - PRICE_ACCOUNT_SIZE, - TIME_MACHINE_STRUCT_SIZE, - }; - use crate::time_machine_types::{ - PriceAccountWrapper, - TimeMachineWrapper, - }; + use crate::c_oracle_header::PRICE_ACCOUNT_SIZE; + use crate::time_machine_types::PriceAccountExtended; use std::mem::size_of; #[test] - ///test that the size defined in C matches that - ///defined in Rust - fn c_time_machine_size_is_correct() { - assert_eq!( - size_of::(), - TIME_MACHINE_STRUCT_SIZE as usize, - "expected TIME_MACHINE_STRUCT_SIZE ({}) in oracle.h to the same as the size of TimeMachineWrapper ({})", - TIME_MACHINE_STRUCT_SIZE, - size_of::() - ); - } - #[test] ///test that priceAccountWrapper has a correct size fn c_price_account_size_is_correct() { assert_eq!( - size_of::(), + size_of::(), PRICE_ACCOUNT_SIZE as usize, "expected PRICE_ACCOUNT_SIZE ({}) in oracle.h to the same as the size of PriceAccountWrapper ({})", PRICE_ACCOUNT_SIZE, - size_of::() + size_of::() ); } } From b5f8a515a0b345aa8387db8c97b9d465d613b84e Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Fri, 2 Sep 2022 12:44:29 -0500 Subject: [PATCH 07/30] Should pass CI --- program/c/src/oracle/oracle.h | 4 +- program/rust/src/lib.rs | 1 + program/rust/src/tests/pyth_simulator.rs | 1 + program/rust/src/tests/test_sizes.rs | 7 --- program/rust/src/tests/test_sma.rs | 68 ------------------------ program/rust/src/time_machine_types.rs | 20 ++++++- 6 files changed, 22 insertions(+), 79 deletions(-) diff --git a/program/c/src/oracle/oracle.h b/program/c/src/oracle/oracle.h index 77590f5e5..881e802d5 100644 --- a/program/c/src/oracle/oracle.h +++ b/program/c/src/oracle/oracle.h @@ -9,9 +9,9 @@ extern "C" { // The size of the "time machine" account defined in the // Rust portion of the codebase. -const uint64_t TIME_MACHINE_STRUCT_SIZE = 1864ULL; +const uint64_t TIME_MACHINE_STRUCT_SIZE = 1200ULL; -const uint64_t EXTRA_PUBLISHER_SPACE = 1000ULL; +const uint64_t EXTRA_PUBLISHER_SPACE = 3072ULL; // magic number at head of account diff --git a/program/rust/src/lib.rs b/program/rust/src/lib.rs index 6472c2856..544457554 100644 --- a/program/rust/src/lib.rs +++ b/program/rust/src/lib.rs @@ -1,3 +1,4 @@ +#![deny(warnings)] // Allow non upper case globals from C #![allow(non_upper_case_globals)] // Allow using the solana_program::entrypoint::deserialize function diff --git a/program/rust/src/tests/pyth_simulator.rs b/program/rust/src/tests/pyth_simulator.rs index 3a7f4d6e8..da5be04dc 100644 --- a/program/rust/src/tests/pyth_simulator.rs +++ b/program/rust/src/tests/pyth_simulator.rs @@ -98,6 +98,7 @@ impl PythSimulator { /// The account will be created with enough lamports to be rent-exempt. pub async fn create_pyth_account(&mut self, size: usize) -> Keypair { let keypair = Keypair::new(); + let rent = Rent::minimum_balance(&Rent::default(), size); let instruction = system_instruction::create_account( &self.payer.pubkey(), diff --git a/program/rust/src/tests/test_sizes.rs b/program/rust/src/tests/test_sizes.rs index 52936a3ff..558254c45 100644 --- a/program/rust/src/tests/test_sizes.rs +++ b/program/rust/src/tests/test_sizes.rs @@ -121,10 +121,3 @@ fn test_pubkey() { "4aDoSXJ5o3AuvL7QFeR6h44jALQfTmUUCTVGDD6aoJTM" ); } -#[test] -fn test_check() { - let a = u64::MAX; - let b = i64::MAX; - let c = i128::MAX / i128::from(i64::MAX); - println!("{:?}", c); -} diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index d65be31a6..2e9241a4e 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -1,80 +1,12 @@ use quickcheck::Arbitrary; use quickcheck_macros::quickcheck; -use solana_program::nonce::state::Data; -use std::collections::BTreeMap; -use std::mem::{ - align_of, - size_of, -}; -use crate::c_oracle_header::PriceAccount; use crate::time_machine_types::{ DataPoint, - PriceAccountExtended, SmaTracker, NUM_BUCKETS_THIRTY_MIN, - THIRTY_MINUTES, }; -// #[test] -// fn unit_tests() { -// let mut tracker = SmaTracker::<10> { -// granularity : 10, -// threshold : TWENTY_SECONDS, -// current_epoch_denominator : 0, -// current_epoch_is_valid : false, -// current_epoch_numerator : 0, -// running_valid_entry_counter: [0u64; 10], -// running_sum_of_price_averages : [0i128; 10], -// }; - -// for i in 0u32..6000 { -// tracker.add_datapoint((i64::from(i), i64::from(i+1)), 1 , 20, (0,0)).unwrap(); -// } - -// println!("{:?}", tracker); - -// tracker.add_datapoint((6000, 6010), 21, 30, (0,0)).unwrap(); -// println!("{:?}", tracker); -// tracker.add_datapoint((6010, 6080), 100, 30, (0,0)).unwrap(); -// println!("{:?}", tracker); - -// // let mut tracker2 = SmaTracker::<48> { -// // granularity : THIRTY_MINUTES, -// // threshold : 20, -// // current_epoch_denominator : 0, -// // current_epoch_is_valid : false, -// // current_epoch_numerator : 0, -// // running_valid_entry_counter: [0u64; 48], -// // running_sum_of_price_averages : [0i128; 48], -// // }; - -// // for i in 0u32..6000 { -// // tracker2.add_datapoint((i64::from(i* 20), i64::from((i+1) * 20)), (u64::from(i* 21), -// u64::from((i+1) * 21)), (20, 20), (0,0)).unwrap(); // } -// // println!("{:?}", tracker2); -// // for i in 6000u32..6180 { -// // tracker2.add_datapoint((i64::from(i* 20), i64::from((i+1) * 20)), (u64::from(i) + -// 126000, u64::from(i+1) + 126000), (20, 20), (0,0)).unwrap(); // } - - -// // println!("{:?}", tracker2); -// // println!("{:?}", tracker2.running_sum_of_price_averages[19]); -// // println!("{:?}", tracker2.running_valid_entry_counter[19]); - - -// // let tracker : & mut SmaTracker<48> = bytemuck::from_bytes_mut(&mut buffer.as_ptr()); -// // unsafe{ -// // println!("{:?}", buffer.as_ptr() as usize); -// // println!("{:?}", align_of::>()); -// // println!("{:?}", align_of::()); -// // println!("{:?}", align_of::()); - -// // } -// // tracker.initialize(THIRTY_MINUTES, TWENTY_SECONDS); - -// } - #[derive(Clone, Debug, Copy)] struct DataEvent { timegap: i64, diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 807d312e0..9d3071de0 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -150,10 +150,26 @@ impl PythAccount for PriceAccountExtended { #[cfg(test)] pub mod tests { - use crate::c_oracle_header::PRICE_ACCOUNT_SIZE; - use crate::time_machine_types::PriceAccountExtended; + use crate::c_oracle_header::{ + PRICE_ACCOUNT_SIZE, + TIME_MACHINE_STRUCT_SIZE, + }; + use crate::time_machine_types::{ + PriceAccountExtended, + SmaTracker, + NUM_BUCKETS_THIRTY_MIN, + }; use std::mem::size_of; #[test] + ///test that the size defined in C matches that + ///defined in Rust + fn c_time_machine_size_is_correct() { + assert_eq!( + TIME_MACHINE_STRUCT_SIZE as usize, + size_of::>() + ); + } + #[test] ///test that priceAccountWrapper has a correct size fn c_price_account_size_is_correct() { assert_eq!( From ce8138d4df8d65e2904ab14845e39f33faef3465 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Fri, 2 Sep 2022 13:43:11 -0500 Subject: [PATCH 08/30] Starting tests --- program/rust/src/lib.rs | 2 +- program/rust/src/tests/mod.rs | 1 + program/rust/src/tests/test_resize_account.rs | 19 +- program/rust/src/tests/test_upd_sma.rs | 348 ++++++++++++++++++ program/rust/src/tests/test_utils.rs | 1 + 5 files changed, 368 insertions(+), 3 deletions(-) create mode 100644 program/rust/src/tests/test_upd_sma.rs diff --git a/program/rust/src/lib.rs b/program/rust/src/lib.rs index 544457554..0b01b6d8b 100644 --- a/program/rust/src/lib.rs +++ b/program/rust/src/lib.rs @@ -1,4 +1,4 @@ -#![deny(warnings)] +// #![deny(warnings)] // Allow non upper case globals from C #![allow(non_upper_case_globals)] // Allow using the solana_program::entrypoint::deserialize function diff --git a/program/rust/src/tests/mod.rs b/program/rust/src/tests/mod.rs index 315bc1370..7c53bb5f4 100644 --- a/program/rust/src/tests/mod.rs +++ b/program/rust/src/tests/mod.rs @@ -16,4 +16,5 @@ mod test_upd_aggregate; mod test_upd_price; mod test_upd_price_no_fail_on_error; mod test_upd_product; +mod test_upd_sma; mod test_utils; diff --git a/program/rust/src/tests/test_resize_account.rs b/program/rust/src/tests/test_resize_account.rs index 28a8371fa..5dacbce6e 100644 --- a/program/rust/src/tests/test_resize_account.rs +++ b/program/rust/src/tests/test_resize_account.rs @@ -1,9 +1,15 @@ use solana_sdk::signer::Signer; use std::mem::size_of; -use crate::c_oracle_header::pc_price_t; +use crate::c_oracle_header::{ + pc_price_t, + PC_MAX_SEND_LATENCY, +}; use crate::tests::pyth_simulator::PythSimulator; -use crate::time_machine_types::PriceAccountExtended; +use crate::time_machine_types::{ + PriceAccountExtended, + THIRTY_MINUTES, +}; /// Warning : This test will fail if you run cargo test instead of cargo test-bpf @@ -28,4 +34,13 @@ async fn test_resize_account() { assert!(sim.resize_price_account(&price1).await.is_ok()); let price1_account = sim.get_account(price1.pubkey()).await.unwrap(); assert_eq!(price1_account.data.len(), size_of::()); + let price1_account_data = sim + .get_account_data_as::(price1.pubkey()) + .await + .unwrap(); + assert_eq!(price1_account_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price1_account_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); } diff --git a/program/rust/src/tests/test_upd_sma.rs b/program/rust/src/tests/test_upd_sma.rs new file mode 100644 index 000000000..4ffe748d4 --- /dev/null +++ b/program/rust/src/tests/test_upd_sma.rs @@ -0,0 +1,348 @@ +use solana_program::program_error::ProgramError; +use solana_program::pubkey::Pubkey; +use std::mem::size_of; + +use crate::c_oracle_header::{ + PriceAccount, + PC_MAX_SEND_LATENCY, + PC_STATUS_TRADING, + PC_STATUS_UNKNOWN, + PC_VERSION, +}; + +use crate::deserialize::{ + initialize_pyth_account_checked, + load_checked, + load_mut, +}; +use crate::instruction::{ + OracleCommand, + UpdPriceArgs, +}; +use crate::processor::process_instruction; +// use crate::processor::process_instruction; +use crate::tests::test_utils::{ + update_clock_slot, + AccountSetup, +}; +use crate::time_machine_types::{ + PriceAccountExtended, + THIRTY_MINUTES, +}; +#[test] +fn test_upd_sma() { + let mut instruction_data = [0u8; size_of::()]; + populate_instruction(&mut instruction_data, 42, 2, 1); + + let program_id = Pubkey::new_unique(); + + let mut funding_setup = AccountSetup::new_funding(); + let funding_account = funding_setup.to_account_info(); + + let mut price_setup = AccountSetup::new::(&program_id); + let mut price_account = price_setup.to_account_info(); + price_account.is_signer = false; + initialize_pyth_account_checked::(&price_account, PC_VERSION).unwrap(); + + + { + let mut price_data = + load_checked::(&price_account, PC_VERSION).unwrap(); + price_data + .time_machine + .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY as u64); + + price_data.price_data.num_ = 1; + price_data.price_data.comp_[0].pub_ = *funding_account.key; + } + + let mut clock_setup = AccountSetup::new_clock(); + let mut clock_account = clock_setup.to_account_info(); + clock_account.is_signer = false; + clock_account.is_writable = false; + + update_clock_slot(&mut clock_account, 1); + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 42); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 1); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + assert_eq!(price_data.price_data.valid_slot_, 0); + assert_eq!(price_data.price_data.agg_.pub_slot_, 1); + assert_eq!(price_data.price_data.agg_.price_, 0); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_UNKNOWN); + + assert_eq!(price_data.time_machine.current_epoch_numerator, 0); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 0); + } + + // add some prices for current slot - get rejected + populate_instruction(&mut instruction_data, 43, 2, 1); + + assert_eq!( + process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ), + Err(ProgramError::InvalidArgument) + ); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 42); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 1); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + assert_eq!(price_data.price_data.valid_slot_, 0); + assert_eq!(price_data.price_data.agg_.pub_slot_, 1); + assert_eq!(price_data.price_data.agg_.price_, 0); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_UNKNOWN); + + assert_eq!(price_data.time_machine.current_epoch_numerator, 0); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 0); + } + + // add next price in new slot triggering snapshot and aggregate calc + populate_instruction(&mut instruction_data, 81, 2, 2); + update_clock_slot(&mut clock_account, 3); + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 2); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + assert_eq!(price_data.price_data.valid_slot_, 1); + assert_eq!(price_data.price_data.agg_.pub_slot_, 3); + assert_eq!(price_data.price_data.agg_.price_, 42); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + + assert_eq!(price_data.time_machine.current_epoch_numerator, 42 / 2 * 3); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 3); + } + + // next price doesnt change but slot does + populate_instruction(&mut instruction_data, 81, 2, 3); + update_clock_slot(&mut clock_account, 4); + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 3); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + assert_eq!(price_data.price_data.valid_slot_, 3); + assert_eq!(price_data.price_data.agg_.pub_slot_, 4); + assert_eq!(price_data.price_data.agg_.price_, 81); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + + assert_eq!( + price_data.time_machine.current_epoch_numerator, + 42 / 2 * 3 + (81 + 42) / 2 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 3 + 1); + } + + // next price doesnt change and neither does aggregate but slot does + populate_instruction(&mut instruction_data, 81, 2, 4); + update_clock_slot(&mut clock_account, 5); + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 4); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + assert_eq!(price_data.price_data.valid_slot_, 4); + assert_eq!(price_data.price_data.agg_.pub_slot_, 5); + assert_eq!(price_data.price_data.agg_.price_, 81); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + + assert_eq!( + price_data.time_machine.current_epoch_numerator, + 42 / 2 * 3 + (81 + 42) / 2 + 81 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 3 + 1 + 1); + } + + // try to publish back-in-time + populate_instruction(&mut instruction_data, 81, 2, 1); + update_clock_slot(&mut clock_account, 5); + assert_eq!( + process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ), + Err(ProgramError::InvalidArgument) + ); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 4); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + assert_eq!(price_data.price_data.valid_slot_, 4); + assert_eq!(price_data.price_data.agg_.pub_slot_, 5); + assert_eq!(price_data.price_data.agg_.price_, 81); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + } + + populate_instruction(&mut instruction_data, 50, 6, 5); + update_clock_slot(&mut clock_account, 6); + + // Publishing a wide CI results in a status of unknown. + + // check that someone doesn't accidentally break the test. + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_TRADING + ); + } + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 50); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 6); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 5); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_UNKNOWN + ); + assert_eq!(price_data.price_data.valid_slot_, 5); + assert_eq!(price_data.price_data.agg_.pub_slot_, 6); + assert_eq!(price_data.price_data.agg_.price_, 81); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + } + + // Crank one more time and aggregate should be unknown + populate_instruction(&mut instruction_data, 50, 6, 6); + update_clock_slot(&mut clock_account, 7); + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + assert_eq!(price_data.price_data.comp_[0].latest_.price_, 50); + assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 6); + assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 6); + assert_eq!( + price_data.price_data.comp_[0].latest_.status_, + PC_STATUS_UNKNOWN + ); + assert_eq!(price_data.price_data.valid_slot_, 6); + assert_eq!(price_data.price_data.agg_.pub_slot_, 7); + assert_eq!(price_data.price_data.agg_.price_, 81); + assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_UNKNOWN); + } +} + +// Create an upd_price instruction with the provided parameters +fn populate_instruction(instruction_data: &mut [u8], price: i64, conf: u64, pub_slot: u64) -> () { + let mut cmd = load_mut::(instruction_data).unwrap(); + cmd.header = OracleCommand::UpdPrice.into(); + cmd.status = PC_STATUS_TRADING; + cmd.price = price; + cmd.confidence = conf; + cmd.publishing_slot = pub_slot; + cmd.unused_ = 0; +} diff --git a/program/rust/src/tests/test_utils.rs b/program/rust/src/tests/test_utils.rs index 87b863b24..a8aadf615 100644 --- a/program/rust/src/tests/test_utils.rs +++ b/program/rust/src/tests/test_utils.rs @@ -31,6 +31,7 @@ const UPPER_BOUND_OF_ALL_ACCOUNT_SIZES: usize = 20536; /// After instantiating the setup `AccountSetup` with `new` (that line will transfer the fields to /// the outer scope), `to_account_info` gives the user an `AccountInfo` pointing to the fields of /// the AccountSetup. +#[repr(align(16))] pub struct AccountSetup { key: Pubkey, owner: Pubkey, From be2f5e037dd0394e9aa10bdd1be4ceabe7d9243e Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Fri, 2 Sep 2022 16:24:06 -0500 Subject: [PATCH 09/30] Update python tests --- 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 c33a6caf3..88a0088fa 100644 --- a/pyth/tests/test_publish.py +++ b/pyth/tests/test_publish.py @@ -120,7 +120,7 @@ def get_account_size(acc_address): resize_account(pyth_init_price['LTC']) time.sleep(20) #defined in oracle.h - new_account_size = 6176 + new_account_size = 7584 assert get_account_size(pyth_init_price['LTC']) == new_account_size From 32d851577e064c8520fee3b92c12e64b0d7f13da Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Fri, 2 Sep 2022 17:06:12 -0500 Subject: [PATCH 10/30] Test upd sma --- program/rust/src/tests/test_upd_sma.rs | 27 ++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/program/rust/src/tests/test_upd_sma.rs b/program/rust/src/tests/test_upd_sma.rs index 4ffe748d4..40f02f3a6 100644 --- a/program/rust/src/tests/test_upd_sma.rs +++ b/program/rust/src/tests/test_upd_sma.rs @@ -263,6 +263,13 @@ fn test_upd_sma() { assert_eq!(price_data.price_data.agg_.pub_slot_, 5); assert_eq!(price_data.price_data.agg_.price_, 81); assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + + assert_eq!( + price_data.time_machine.current_epoch_numerator, + 42 / 2 * 3 + (81 + 42) / 2 + 81 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 3 + 1 + 1); } populate_instruction(&mut instruction_data, 50, 6, 5); @@ -303,6 +310,16 @@ fn test_upd_sma() { assert_eq!(price_data.price_data.agg_.pub_slot_, 6); assert_eq!(price_data.price_data.agg_.price_, 81); assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); + + assert_eq!( + price_data.time_machine.current_epoch_numerator, + 42 / 2 * 3 + (81 + 42) / 2 + 81 + 81 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!( + price_data.time_machine.current_epoch_denominator, + 3 + 1 + 1 + 1 + ); } // Crank one more time and aggregate should be unknown @@ -333,6 +350,16 @@ fn test_upd_sma() { assert_eq!(price_data.price_data.agg_.pub_slot_, 7); assert_eq!(price_data.price_data.agg_.price_, 81); assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_UNKNOWN); + + assert_eq!( + price_data.time_machine.current_epoch_numerator, + 42 / 2 * 3 + (81 + 42) / 2 + 81 + 81 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!( + price_data.time_machine.current_epoch_denominator, + 3 + 1 + 1 + 1 + ); } } From 7276986d3ed9b15e965fb82c5c4a96aba3570de3 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Tue, 6 Sep 2022 13:15:36 -0500 Subject: [PATCH 11/30] Another test --- program/rust/src/lib.rs | 2 +- program/rust/src/tests/mod.rs | 1 + program/rust/src/tests/test_sma.rs | 1 - .../src/tests/test_sma_epoch_transition.rs | 455 ++++++++++++++++++ program/rust/src/tests/test_upd_sma.rs | 3 +- program/rust/src/tests/test_utils.rs | 6 + 6 files changed, 465 insertions(+), 3 deletions(-) create mode 100644 program/rust/src/tests/test_sma_epoch_transition.rs diff --git a/program/rust/src/lib.rs b/program/rust/src/lib.rs index 0b01b6d8b..544457554 100644 --- a/program/rust/src/lib.rs +++ b/program/rust/src/lib.rs @@ -1,4 +1,4 @@ -// #![deny(warnings)] +#![deny(warnings)] // Allow non upper case globals from C #![allow(non_upper_case_globals)] // Allow using the solana_program::entrypoint::deserialize function diff --git a/program/rust/src/tests/mod.rs b/program/rust/src/tests/mod.rs index 7c53bb5f4..f3151ce2d 100644 --- a/program/rust/src/tests/mod.rs +++ b/program/rust/src/tests/mod.rs @@ -12,6 +12,7 @@ mod test_resize_account; mod test_set_min_pub; mod test_sizes; mod test_sma; +mod test_sma_epoch_transition; mod test_upd_aggregate; mod test_upd_price; mod test_upd_price_no_fail_on_error; diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index 2e9241a4e..f0574d0ef 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -60,7 +60,6 @@ fn test_add_and_delete(input: Vec) -> bool { tracker1.add_datapoint(&datapoint).unwrap(); tracker2.add_datapoint(&datapoint).unwrap(); tracker3.add_datapoint(&datapoint).unwrap(); - tracker4.add_datapoint(&datapoint).unwrap(); tracker5.add_datapoint(&datapoint).unwrap(); data.push(datapoint); diff --git a/program/rust/src/tests/test_sma_epoch_transition.rs b/program/rust/src/tests/test_sma_epoch_transition.rs new file mode 100644 index 000000000..417f2f88c --- /dev/null +++ b/program/rust/src/tests/test_sma_epoch_transition.rs @@ -0,0 +1,455 @@ +use solana_program::pubkey::Pubkey; +use std::mem::size_of; + +use crate::c_oracle_header::{ + PC_MAX_SEND_LATENCY, + PC_STATUS_TRADING, + PC_VERSION, +}; + +use crate::deserialize::{ + initialize_pyth_account_checked, + load_checked, + load_mut, +}; +use crate::instruction::{ + OracleCommand, + UpdPriceArgs, +}; +use crate::processor::process_instruction; +use crate::tests::test_utils::{ + update_clock_slot, + update_clock_timestamp, + AccountSetup, +}; +use crate::time_machine_types::{ + PriceAccountExtended, + NUM_BUCKETS_THIRTY_MIN, + THIRTY_MINUTES, +}; + +/// Manually test some epoch transitions +#[test] +fn test_sma_epoch_transition() { + let mut instruction_data = [0u8; size_of::()]; + + let program_id = Pubkey::new_unique(); + + let mut funding_setup = AccountSetup::new_funding(); + let funding_account = funding_setup.to_account_info(); + + let mut price_setup = AccountSetup::new::(&program_id); + let mut price_account = price_setup.to_account_info(); + price_account.is_signer = false; + initialize_pyth_account_checked::(&price_account, PC_VERSION).unwrap(); + + + { + let mut price_data = + load_checked::(&price_account, PC_VERSION).unwrap(); + price_data + .time_machine + .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY as u64); + + price_data.price_data.num_ = 1; + price_data.price_data.comp_[0].pub_ = *funding_account.key; + } + + let mut clock_setup = AccountSetup::new_clock(); + let mut clock_account = clock_setup.to_account_info(); + clock_account.is_signer = false; + clock_account.is_writable = false; + + update_clock_slot(&mut clock_account, 1); + update_clock_timestamp(&mut clock_account, 1); + populate_instruction(&mut instruction_data, 42, 2, 1); + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!(price_data.time_machine.current_epoch_numerator, 0); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 0); + for i in 0..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + } + + // Same epoch, small slot gap + update_clock_slot(&mut clock_account, 2); + update_clock_timestamp(&mut clock_account, 2); + populate_instruction(&mut instruction_data, 80, 2, 2); + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!(price_data.time_machine.current_epoch_numerator, 42 / 2 * 2); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 2); + for i in 0..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + } + + // Next epoch, small slot gap + update_clock_slot(&mut clock_account, 3); + update_clock_timestamp(&mut clock_account, THIRTY_MINUTES); + populate_instruction(&mut instruction_data, 120, 1, 3); + + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price_data.time_machine.current_epoch_numerator, + (80 + 42) / 2 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 1); + + for i in 1..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[0], + ((42 + (80 + 42) / 2) / 3) + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + } + + // Same epoch, big slot gap + update_clock_slot(&mut clock_account, 30); + update_clock_timestamp(&mut clock_account, THIRTY_MINUTES + 1); + populate_instruction(&mut instruction_data, 40, 1, 30); + + // Unsuccesful aggregation + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price_data.time_machine.current_epoch_numerator, + (80 + 42) / 2 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 1); + + for i in 1..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[0], + ((42 + (80 + 42) / 2) / 3) + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + } + + update_clock_slot(&mut clock_account, 31); + update_clock_timestamp(&mut clock_account, 2 * THIRTY_MINUTES + 1); + populate_instruction(&mut instruction_data, 41, 1, 31); + + // Triggers aggregation! + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price_data.time_machine.current_epoch_numerator, + (40 + 80) / 2 * 28 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); + assert_eq!(price_data.time_machine.current_epoch_denominator, 28); + + for i in 2..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[0], + ((42 + (80 + 42) / 2) / 3) + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[1], + price_data.time_machine.running_sum_of_price_averages[0] + 60 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 1); + } + + // A big gap in time (more than 1 epoch) but not in slots, all skipped epochs are "valid" + update_clock_slot(&mut clock_account, 32); + update_clock_timestamp(&mut clock_account, 5 * THIRTY_MINUTES + 1); + populate_instruction(&mut instruction_data, 30, 1, 32); + + // Triggers aggregation! + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price_data.time_machine.current_epoch_numerator, + (40 + 41) / 2 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 1); + + for i in 5..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[0], + ((42 + (80 + 42) / 2) / 3) + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[1], + price_data.time_machine.running_sum_of_price_averages[0] + 60 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[2], + price_data.time_machine.running_sum_of_price_averages[1] + (60 * 28 + 1 * 41) / 29 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[2], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[3], + price_data.time_machine.running_sum_of_price_averages[2] + 40 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[3], 2); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[4], + price_data.time_machine.running_sum_of_price_averages[3] + 40 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[4], 3); + } + + // Really big gap both in slots and epochs (the entire buffers gets rewritten) + update_clock_slot(&mut clock_account, 100); + update_clock_timestamp(&mut clock_account, 100 * THIRTY_MINUTES + 1); + populate_instruction(&mut instruction_data, 100, 1, 100); + + // Unsuccesful aggregation + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price_data.time_machine.current_epoch_numerator, + (40 + 41) / 2 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_denominator, 1); + + for i in 5..NUM_BUCKETS_THIRTY_MIN { + assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[i], 0); + } + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[0], + ((42 + (80 + 42) / 2) / 3) + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[1], + price_data.time_machine.running_sum_of_price_averages[0] + 60 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[2], + price_data.time_machine.running_sum_of_price_averages[1] + (60 * 28 + 1 * 41) / 29 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[2], 1); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[3], + price_data.time_machine.running_sum_of_price_averages[2] + 40 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[3], 2); + + assert_eq!( + price_data.time_machine.running_sum_of_price_averages[4], + price_data.time_machine.running_sum_of_price_averages[3] + 40 + ); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[4], 3); + } + + update_clock_slot(&mut clock_account, 101); + update_clock_timestamp(&mut clock_account, 100 * THIRTY_MINUTES + 2); + populate_instruction(&mut instruction_data, 100, 1, 101); + + // Aggregation triggered + assert!(process_instruction( + &program_id, + &[ + funding_account.clone(), + price_account.clone(), + clock_account.clone() + ], + &instruction_data + ) + .is_ok()); + + { + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + + assert_eq!( + price_data.time_machine.threshold, + PC_MAX_SEND_LATENCY as u64 + ); + assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); + assert_eq!( + price_data.time_machine.current_epoch_numerator, + (41 + 100) / 2 * 69 + ); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); + assert_eq!(price_data.time_machine.current_epoch_denominator, 69); + + for i in 0..NUM_BUCKETS_THIRTY_MIN { + assert_eq!( + price_data.time_machine.running_sum_of_price_averages + [(i + 4) % NUM_BUCKETS_THIRTY_MIN], + 233 + 69 + 70 * (NUM_BUCKETS_THIRTY_MIN as i128 - 1) + 70 * i as i128 + ); + assert_eq!( + price_data.time_machine.running_valid_epoch_counter + [(i + 4) % NUM_BUCKETS_THIRTY_MIN], + 3 + ); + } + } +} + +// Create an upd_price instruction with the provided parameters +fn populate_instruction(instruction_data: &mut [u8], price: i64, conf: u64, pub_slot: u64) -> () { + let mut cmd = load_mut::(instruction_data).unwrap(); + cmd.header = OracleCommand::UpdPrice.into(); + cmd.status = PC_STATUS_TRADING; + cmd.price = price; + cmd.confidence = conf; + cmd.publishing_slot = pub_slot; + cmd.unused_ = 0; +} diff --git a/program/rust/src/tests/test_upd_sma.rs b/program/rust/src/tests/test_upd_sma.rs index 40f02f3a6..eba3e5ff5 100644 --- a/program/rust/src/tests/test_upd_sma.rs +++ b/program/rust/src/tests/test_upd_sma.rs @@ -3,7 +3,6 @@ use solana_program::pubkey::Pubkey; use std::mem::size_of; use crate::c_oracle_header::{ - PriceAccount, PC_MAX_SEND_LATENCY, PC_STATUS_TRADING, PC_STATUS_UNKNOWN, @@ -29,6 +28,8 @@ use crate::time_machine_types::{ PriceAccountExtended, THIRTY_MINUTES, }; + +/// Clone of test_upd_price that also checks sma fields #[test] fn test_upd_sma() { let mut instruction_data = [0u8; size_of::()]; diff --git a/program/rust/src/tests/test_utils.rs b/program/rust/src/tests/test_utils.rs index a8aadf615..63f4c0a3b 100644 --- a/program/rust/src/tests/test_utils.rs +++ b/program/rust/src/tests/test_utils.rs @@ -106,6 +106,12 @@ pub fn update_clock_slot(clock_account: &mut AccountInfo, slot: u64) { clock_data.to_account_info(clock_account); } +pub fn update_clock_timestamp(clock_account: &mut AccountInfo, timestamp: i64) { + let mut clock_data = clock::Clock::from_account_info(clock_account).unwrap(); + clock_data.unix_timestamp = timestamp; + clock_data.to_account_info(clock_account); +} + impl Into for OracleCommand { fn into(self) -> CommandHeader { return CommandHeader { From 7973d074e0599a94f9412e87da179b72e2889f35 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Tue, 6 Sep 2022 17:01:56 -0500 Subject: [PATCH 12/30] More comments --- program/rust/src/time_machine_types.rs | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 9d3071de0..62ac579cf 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -66,7 +66,8 @@ pub struct SmaTracker { impl SmaTracker { pub fn time_to_epoch(&self, time: i64) -> Result { - try_convert::(time / self.granularity) + try_convert::(time / self.granularity) // Can never fail because usize is u64 + // and time is positive } pub fn initialize(&mut self, granularity: i64, threshold: u64) { @@ -82,10 +83,11 @@ impl SmaTracker { let datapoint_numerator = i128::from(datapoint.slot_gap) * i128::from(datapoint.price); //Can't overflow because u64::MAX * i64::MAX = i28::MAX let datapoint_denominator = datapoint.slot_gap; - // Can't overflow, it's always smaller than the current solana slot - self.current_epoch_denominator += datapoint_denominator; - // Can't overflow, it's always smaller than u64::MAX * i64::MAX = i28::MAX - self.current_epoch_numerator += datapoint_numerator; + self.current_epoch_denominator += datapoint_denominator; // Can't overflow, it's always smaller than the current solana slot + self.current_epoch_numerator += datapoint_numerator; // Can't overflow, it's always smaller than u64::MAX * i64::MAX = i28::MAX, + // self.current_epoch_numerator = slot_gap1 * price1 + slot_gap2 * price2 + slot_gap3 * + // price3 <= (slot_gap1 + slot_gap2 + slot_gap3) * i64::MAX <= u64::MAX * i64::MAX + // =i128::MAX self.current_epoch_is_valid = self.current_epoch_is_valid && datapoint_denominator <= self.threshold; @@ -106,18 +108,16 @@ impl SmaTracker { datapoint_denominator: u64, ) { let index = epoch.rem_euclid(NUM_ENTRIES); - let prev_index = (epoch + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); + let prev_index = (epoch + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); // epoch <= time <= i64::MAX <= u64::MAX / 2, so this will only overflow if NUM_ENTRIES ~ + // u64::MAX / 2 - // This buffer will be able to support u64::MAX epochs, no one will be alive when it - // overflows, that's because every epoch we add a number that's smaller than i64::MAX self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] - + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); + + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); // The fraction here is smaller than i64::MAX , so we can support u64::MAX updates - // Likewise can support u64::MAX - // epochs if self.current_epoch_is_valid { self.running_valid_epoch_counter[index] = - self.running_valid_epoch_counter[prev_index] + 1; + self.running_valid_epoch_counter[prev_index] + 1; // Likewise can support u64::MAX + // epochs } else { self.running_valid_epoch_counter[index] = self.running_valid_epoch_counter[prev_index] }; From af5407b2798409d3a1e47bed041a769acd49a78e Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Tue, 6 Sep 2022 21:01:36 -0500 Subject: [PATCH 13/30] New implementation --- program/rust/src/time_machine_types.rs | 80 ++++++++++++++++++-------- 1 file changed, 55 insertions(+), 25 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 62ac579cf..38666ce78 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -94,36 +94,66 @@ impl SmaTracker { // This for loop is highly inefficient, but this is what the behavior should be // It updates all the epochs that got skipped // This will always yield an estimate of the average, even for invalid epochs - for i in epoch_0..epoch_1 { - self.conclude_epoch_and_initialize_next(i, datapoint_numerator, datapoint_denominator); + + if epoch_0 < epoch_1 { + let index = epoch_0.rem_euclid(NUM_ENTRIES); + let prev_index = (epoch_0 + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); // epoch <= time <= i64::MAX <= u64::MAX / 2, so this will only overflow if NUM_ENTRIES + // ~ + // u64::MAX / 2 + + self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages + [prev_index] + + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); + // The fraction here is smaller than i64::MAX , so we can support u64::MAX updates + + if self.current_epoch_is_valid { + self.running_valid_epoch_counter[index] = + self.running_valid_epoch_counter[prev_index] + 1; // Likewise can support + // u64::MAX + // epochs + } else { + self.running_valid_epoch_counter[index] = + self.running_valid_epoch_counter[prev_index] + }; + + self.current_epoch_denominator = datapoint_denominator; + self.current_epoch_numerator = datapoint_numerator; self.current_epoch_is_valid = datapoint_denominator <= self.threshold; + + let fraction = datapoint_numerator / i128::from(datapoint_denominator); + if epoch_0 + 1 < epoch_1 { + for i in 1..NUM_ENTRIES + 1 { + let current_index = (epoch_0 + i) % NUM_ENTRIES; + let number_of_time_skipped = + self.number_times_skipped(current_index, epoch_0, epoch_1); + if number_of_time_skipped > 0 { + self.running_sum_of_price_averages[current_index % NUM_ENTRIES] = self + .running_sum_of_price_averages[(epoch_0) % NUM_ENTRIES] + + ((i + (number_of_time_skipped - 1) * NUM_ENTRIES) as i128) * fraction; + + if self.current_epoch_is_valid { + self.running_valid_epoch_counter[current_index % NUM_ENTRIES] = self + .running_valid_epoch_counter[(epoch_0) % NUM_ENTRIES] + + (i as u64) + + ((number_of_time_skipped - 1) as u64) * (NUM_ENTRIES as u64); + } else { + self.running_valid_epoch_counter[current_index % NUM_ENTRIES] = self + .running_valid_epoch_counter + [(epoch_0 + i + NUM_ENTRIES - 1) % NUM_ENTRIES]; + } + } + } + } } + Ok(()) } - pub fn conclude_epoch_and_initialize_next( - &mut self, - epoch: usize, - datapoint_numerator: i128, - datapoint_denominator: u64, - ) { - let index = epoch.rem_euclid(NUM_ENTRIES); - let prev_index = (epoch + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); // epoch <= time <= i64::MAX <= u64::MAX / 2, so this will only overflow if NUM_ENTRIES ~ - // u64::MAX / 2 - - self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages[prev_index] - + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); // The fraction here is smaller than i64::MAX , so we can support u64::MAX updates - - if self.current_epoch_is_valid { - self.running_valid_epoch_counter[index] = - self.running_valid_epoch_counter[prev_index] + 1; // Likewise can support u64::MAX - // epochs - } else { - self.running_valid_epoch_counter[index] = self.running_valid_epoch_counter[prev_index] - }; - - self.current_epoch_denominator = datapoint_denominator; - self.current_epoch_numerator = datapoint_numerator; + pub fn number_times_skipped(&self, i: usize, epoch_0: usize, epoch_1: usize) -> usize { + let is_between = ((epoch_0 % NUM_ENTRIES) < i && i < (epoch_1 % NUM_ENTRIES)) + || ((epoch_1 % NUM_ENTRIES) <= (epoch_0 % NUM_ENTRIES)) + && ((i < (epoch_1 % NUM_ENTRIES)) || (i > (epoch_0 % NUM_ENTRIES))); + (epoch_1 - 1 - epoch_0) / NUM_ENTRIES + usize::from(is_between) } } From 444c68578c966043424463e5de90a8d0d3f50e63 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Tue, 6 Sep 2022 21:28:45 -0500 Subject: [PATCH 14/30] Cleanup --- program/rust/src/time_machine_types.rs | 36 +++++++++++++------------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 38666ce78..9cfb9adcb 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -123,23 +123,22 @@ impl SmaTracker { let fraction = datapoint_numerator / i128::from(datapoint_denominator); if epoch_0 + 1 < epoch_1 { for i in 1..NUM_ENTRIES + 1 { - let current_index = (epoch_0 + i) % NUM_ENTRIES; - let number_of_time_skipped = - self.number_times_skipped(current_index, epoch_0, epoch_1); - if number_of_time_skipped > 0 { - self.running_sum_of_price_averages[current_index % NUM_ENTRIES] = self - .running_sum_of_price_averages[(epoch_0) % NUM_ENTRIES] - + ((i + (number_of_time_skipped - 1) * NUM_ENTRIES) as i128) * fraction; + let current_bucket = (epoch_0 + i) % NUM_ENTRIES; + let times_bucket_skipped = + self.get_times_bucket_skipped(current_bucket, epoch_0, epoch_1); + let bucket_0 = (epoch_0) % NUM_ENTRIES; + if times_bucket_skipped > 0 { + self.running_sum_of_price_averages[current_bucket] = self + .running_sum_of_price_averages[bucket_0] + + ((i + (times_bucket_skipped - 1) * NUM_ENTRIES) as i128) * fraction; if self.current_epoch_is_valid { - self.running_valid_epoch_counter[current_index % NUM_ENTRIES] = self - .running_valid_epoch_counter[(epoch_0) % NUM_ENTRIES] - + (i as u64) - + ((number_of_time_skipped - 1) as u64) * (NUM_ENTRIES as u64); + self.running_valid_epoch_counter[current_bucket] = self + .running_valid_epoch_counter[bucket_0] + + ((i + (times_bucket_skipped - 1) * NUM_ENTRIES) as u64); } else { - self.running_valid_epoch_counter[current_index % NUM_ENTRIES] = self - .running_valid_epoch_counter - [(epoch_0 + i + NUM_ENTRIES - 1) % NUM_ENTRIES]; + self.running_valid_epoch_counter[current_bucket] = + self.running_valid_epoch_counter[bucket_0]; } } } @@ -149,10 +148,11 @@ impl SmaTracker { Ok(()) } - pub fn number_times_skipped(&self, i: usize, epoch_0: usize, epoch_1: usize) -> usize { - let is_between = ((epoch_0 % NUM_ENTRIES) < i && i < (epoch_1 % NUM_ENTRIES)) - || ((epoch_1 % NUM_ENTRIES) <= (epoch_0 % NUM_ENTRIES)) - && ((i < (epoch_1 % NUM_ENTRIES)) || (i > (epoch_0 % NUM_ENTRIES))); + pub fn get_times_bucket_skipped(&self, bucket: usize, epoch_0: usize, epoch_1: usize) -> usize { + let bucket_0 = epoch_0 % NUM_ENTRIES; + let bucket_1 = epoch_1 % NUM_ENTRIES; + let is_between = (bucket_0 < bucket && bucket < bucket_1) + || (bucket_1 <= bucket_0) && ((bucket < bucket_1) || (bucket > bucket_0)); (epoch_1 - 1 - epoch_0) / NUM_ENTRIES + usize::from(is_between) } } From 62144b07a53055518f2528df969e357e0913828c Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 09:50:53 -0500 Subject: [PATCH 15/30] Add comment --- program/rust/src/time_machine_types.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 9cfb9adcb..1bafc9f51 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -148,6 +148,7 @@ impl SmaTracker { Ok(()) } + /// Counts the times bucket `bucket` was skipped when going from `epoch_0` to `epoch_1` pub fn get_times_bucket_skipped(&self, bucket: usize, epoch_0: usize, epoch_1: usize) -> usize { let bucket_0 = epoch_0 % NUM_ENTRIES; let bucket_1 = epoch_1 % NUM_ENTRIES; From d0738d553363bef4a1cfdf057c84fac5f571ee68 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 09:56:29 -0500 Subject: [PATCH 16/30] Renames --- program/rust/src/rust_oracle.rs | 18 ++++++------- program/rust/src/tests/pyth_simulator.rs | 1 - program/rust/src/tests/test_resize_account.rs | 8 +++--- program/rust/src/tests/test_sizes.rs | 4 +-- .../src/tests/test_sma_epoch_transition.rs | 24 ++++++++--------- program/rust/src/tests/test_upd_sma.rs | 26 +++++++++---------- program/rust/src/time_machine_types.rs | 20 +++++++------- 7 files changed, 50 insertions(+), 51 deletions(-) diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index f3da48df2..871c1349c 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -38,7 +38,7 @@ use crate::instruction::{ UpdPermissionsArgs, UpdPriceArgs, }; -use crate::time_machine_types::PriceAccountExtended; +use crate::time_machine_types::PriceAccountWrapper; use crate::utils::{ check_exponent_range, check_is_upgrade_authority_for_program, @@ -109,7 +109,7 @@ pub fn resize_price_account( // Ensure account is still rent exempt after resizing let rent: Rent = Default::default(); let lamports_needed: u64 = rent - .minimum_balance(size_of::()) + .minimum_balance(size_of::()) .saturating_sub(price_account_info.lamports()); if lamports_needed > 0 { send_lamports( @@ -121,17 +121,17 @@ pub fn resize_price_account( } // We do not need to zero allocate because we won't access the data in the same // instruction - price_account_info.realloc(size_of::(), false)?; + price_account_info.realloc(size_of::(), false)?; // Check that everything is ok check_valid_signable_account(program_id, price_account_info)?; let mut price_account = - load_checked::(price_account_info, PC_VERSION)?; + load_checked::(price_account_info, PC_VERSION)?; // Initialize Time Machine - price_account.initialize()?; + price_account.initialize_time_machine()?; Ok(()) } - PriceAccountExtended::MINIMUM_SIZE => Ok(()), + PriceAccountWrapper::MINIMUM_SIZE => Ok(()), _ => Err(ProgramError::InvalidArgument), } } @@ -253,10 +253,10 @@ pub fn upd_price( } let account_len = price_account.try_data_len()?; - if aggregate_updated && account_len == PriceAccountExtended::MINIMUM_SIZE { + if aggregate_updated && account_len == PriceAccountWrapper::MINIMUM_SIZE { let mut price_account = - load_checked::(price_account, cmd_args.header.version)?; - price_account.add_datapoint()?; + load_checked::(price_account, cmd_args.header.version)?; + price_account.add_price_to_time_machine()?; } // Try to update the publisher's price diff --git a/program/rust/src/tests/pyth_simulator.rs b/program/rust/src/tests/pyth_simulator.rs index 051e74544..d06e5b23d 100644 --- a/program/rust/src/tests/pyth_simulator.rs +++ b/program/rust/src/tests/pyth_simulator.rs @@ -163,7 +163,6 @@ impl PythSimulator { /// The account will be created with enough lamports to be rent-exempt. pub async fn create_pyth_account(&mut self, size: usize) -> Keypair { let keypair = Keypair::new(); - let rent = Rent::minimum_balance(&Rent::default(), size); let instruction = system_instruction::create_account( &self.genesis_keypair.pubkey(), diff --git a/program/rust/src/tests/test_resize_account.rs b/program/rust/src/tests/test_resize_account.rs index 5dacbce6e..fca51370b 100644 --- a/program/rust/src/tests/test_resize_account.rs +++ b/program/rust/src/tests/test_resize_account.rs @@ -7,7 +7,7 @@ use crate::c_oracle_header::{ }; use crate::tests::pyth_simulator::PythSimulator; use crate::time_machine_types::{ - PriceAccountExtended, + PriceAccountWrapper, THIRTY_MINUTES, }; @@ -28,14 +28,14 @@ async fn test_resize_account() { assert!(sim.resize_price_account(&price1).await.is_ok()); // Check new size let price1_account = sim.get_account(price1.pubkey()).await.unwrap(); - assert_eq!(price1_account.data.len(), size_of::()); + assert_eq!(price1_account.data.len(), size_of::()); // Future calls don't change the size assert!(sim.resize_price_account(&price1).await.is_ok()); let price1_account = sim.get_account(price1.pubkey()).await.unwrap(); - assert_eq!(price1_account.data.len(), size_of::()); + assert_eq!(price1_account.data.len(), size_of::()); let price1_account_data = sim - .get_account_data_as::(price1.pubkey()) + .get_account_data_as::(price1.pubkey()) .await .unwrap(); assert_eq!(price1_account_data.time_machine.granularity, THIRTY_MINUTES); diff --git a/program/rust/src/tests/test_sizes.rs b/program/rust/src/tests/test_sizes.rs index fd47dbd74..cdb34ffa4 100644 --- a/program/rust/src/tests/test_sizes.rs +++ b/program/rust/src/tests/test_sizes.rs @@ -28,7 +28,7 @@ use crate::instruction::{ UpdPriceArgs, }; use crate::tests::test_utils::AccountSetup; -use crate::time_machine_types::PriceAccountExtended; +use crate::time_machine_types::PriceAccountWrapper; use crate::utils::try_convert; use solana_program::pubkey::Pubkey; use std::mem::{ @@ -70,7 +70,7 @@ fn test_sizes() { assert_eq!(size_of::(), 24); assert_eq!(size_of::(), 3312); assert_eq!( - size_of::(), + size_of::(), try_convert::<_, usize>(PRICE_ACCOUNT_SIZE).unwrap() ); assert_eq!(size_of::(), 112); diff --git a/program/rust/src/tests/test_sma_epoch_transition.rs b/program/rust/src/tests/test_sma_epoch_transition.rs index 417f2f88c..69c48f949 100644 --- a/program/rust/src/tests/test_sma_epoch_transition.rs +++ b/program/rust/src/tests/test_sma_epoch_transition.rs @@ -23,7 +23,7 @@ use crate::tests::test_utils::{ AccountSetup, }; use crate::time_machine_types::{ - PriceAccountExtended, + PriceAccountWrapper, NUM_BUCKETS_THIRTY_MIN, THIRTY_MINUTES, }; @@ -38,15 +38,15 @@ fn test_sma_epoch_transition() { let mut funding_setup = AccountSetup::new_funding(); let funding_account = funding_setup.to_account_info(); - let mut price_setup = AccountSetup::new::(&program_id); + let mut price_setup = AccountSetup::new::(&program_id); let mut price_account = price_setup.to_account_info(); price_account.is_signer = false; - initialize_pyth_account_checked::(&price_account, PC_VERSION).unwrap(); + initialize_pyth_account_checked::(&price_account, PC_VERSION).unwrap(); { let mut price_data = - load_checked::(&price_account, PC_VERSION).unwrap(); + load_checked::(&price_account, PC_VERSION).unwrap(); price_data .time_machine .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY as u64); @@ -76,7 +76,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -109,7 +109,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -142,7 +142,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -186,7 +186,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -229,7 +229,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -279,7 +279,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -347,7 +347,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, @@ -414,7 +414,7 @@ fn test_sma_epoch_transition() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.time_machine.threshold, diff --git a/program/rust/src/tests/test_upd_sma.rs b/program/rust/src/tests/test_upd_sma.rs index eba3e5ff5..503d9f538 100644 --- a/program/rust/src/tests/test_upd_sma.rs +++ b/program/rust/src/tests/test_upd_sma.rs @@ -25,7 +25,7 @@ use crate::tests::test_utils::{ AccountSetup, }; use crate::time_machine_types::{ - PriceAccountExtended, + PriceAccountWrapper, THIRTY_MINUTES, }; @@ -40,15 +40,15 @@ fn test_upd_sma() { let mut funding_setup = AccountSetup::new_funding(); let funding_account = funding_setup.to_account_info(); - let mut price_setup = AccountSetup::new::(&program_id); + let mut price_setup = AccountSetup::new::(&program_id); let mut price_account = price_setup.to_account_info(); price_account.is_signer = false; - initialize_pyth_account_checked::(&price_account, PC_VERSION).unwrap(); + initialize_pyth_account_checked::(&price_account, PC_VERSION).unwrap(); { let mut price_data = - load_checked::(&price_account, PC_VERSION).unwrap(); + load_checked::(&price_account, PC_VERSION).unwrap(); price_data .time_machine .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY as u64); @@ -76,7 +76,7 @@ fn test_upd_sma() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 42); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 1); @@ -111,7 +111,7 @@ fn test_upd_sma() { ); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 42); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 1); @@ -145,7 +145,7 @@ fn test_upd_sma() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 2); @@ -178,7 +178,7 @@ fn test_upd_sma() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 3); @@ -214,7 +214,7 @@ fn test_upd_sma() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 4); @@ -252,7 +252,7 @@ fn test_upd_sma() { ); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 81); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 2); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 4); @@ -280,7 +280,7 @@ fn test_upd_sma() { // check that someone doesn't accidentally break the test. { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!( price_data.price_data.comp_[0].latest_.status_, PC_STATUS_TRADING @@ -299,7 +299,7 @@ fn test_upd_sma() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 50); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 6); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 5); @@ -339,7 +339,7 @@ fn test_upd_sma() { .is_ok()); { - let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); assert_eq!(price_data.price_data.comp_[0].latest_.price_, 50); assert_eq!(price_data.price_data.comp_[0].latest_.conf_, 6); assert_eq!(price_data.price_data.comp_[0].latest_.pub_slot_, 6); diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 1bafc9f51..0b6fa0505 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -17,7 +17,7 @@ pub const THIRTY_MINUTES: i64 = 30 * 60; pub const NUM_BUCKETS_THIRTY_MIN: usize = 48; #[derive(Copy, Clone)] #[repr(C)] -pub struct PriceAccountExtended { +pub struct PriceAccountWrapper { // An instance of price account pub price_data: PriceAccount, /// Space for more publishers @@ -34,14 +34,14 @@ pub struct DataPoint { pub price: i64, } -impl PriceAccountExtended { - pub fn initialize(&mut self) -> Result<(), OracleError> { +impl PriceAccountWrapper { + pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { self.time_machine .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY.into()); Ok(()) } - pub fn add_datapoint(&mut self) -> Result<(), OracleError> { + pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { self.time_machine.add_datapoint( &DataPoint{ last_two_timestamps : (self.price_data.prev_timestamp_, self.price_data.timestamp_), slot_gap : (self.price_data.last_slot_ - self.price_data.prev_slot_), @@ -159,11 +159,11 @@ impl SmaTracker { } #[cfg(target_endian = "little")] -unsafe impl Zeroable for PriceAccountExtended { +unsafe impl Zeroable for PriceAccountWrapper { } #[cfg(target_endian = "little")] -unsafe impl Pod for PriceAccountExtended { +unsafe impl Pod for PriceAccountWrapper { } #[cfg(target_endian = "little")] @@ -174,7 +174,7 @@ unsafe impl Zeroable for SmaTracker { unsafe impl Pod for SmaTracker { } -impl PythAccount for PriceAccountExtended { +impl PythAccount for PriceAccountWrapper { const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; const INITIAL_SIZE: u32 = PC_PRICE_T_COMP_OFFSET as u32; } @@ -186,7 +186,7 @@ pub mod tests { TIME_MACHINE_STRUCT_SIZE, }; use crate::time_machine_types::{ - PriceAccountExtended, + PriceAccountWrapper, SmaTracker, NUM_BUCKETS_THIRTY_MIN, }; @@ -204,11 +204,11 @@ pub mod tests { ///test that priceAccountWrapper has a correct size fn c_price_account_size_is_correct() { assert_eq!( - size_of::(), + size_of::(), PRICE_ACCOUNT_SIZE as usize, "expected PRICE_ACCOUNT_SIZE ({}) in oracle.h to the same as the size of PriceAccountWrapper ({})", PRICE_ACCOUNT_SIZE, - size_of::() + size_of::() ); } } From eeb0fefbe995555b0178ad518b443a41128a8202 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 10:09:47 -0500 Subject: [PATCH 17/30] Cleanup --- program/rust/src/time_machine_types.rs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 0b6fa0505..83d39ee5d 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -166,14 +166,6 @@ unsafe impl Zeroable for PriceAccountWrapper { unsafe impl Pod for PriceAccountWrapper { } -#[cfg(target_endian = "little")] -unsafe impl Zeroable for SmaTracker { -} - -#[cfg(target_endian = "little")] -unsafe impl Pod for SmaTracker { -} - impl PythAccount for PriceAccountWrapper { const ACCOUNT_TYPE: u32 = PC_ACCTYPE_PRICE; const INITIAL_SIZE: u32 = PC_PRICE_T_COMP_OFFSET as u32; From 3de4bd9b921c9480b27761c2ad259216d23d9f63 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 10:46:28 -0500 Subject: [PATCH 18/30] Cleanup --- program/rust/src/tests/test_utils.rs | 2 +- program/rust/src/time_machine_types.rs | 38 ++++++++++++++++---------- 2 files changed, 24 insertions(+), 16 deletions(-) diff --git a/program/rust/src/tests/test_utils.rs b/program/rust/src/tests/test_utils.rs index 199e4a018..dc6e4f716 100644 --- a/program/rust/src/tests/test_utils.rs +++ b/program/rust/src/tests/test_utils.rs @@ -35,7 +35,7 @@ const UPPER_BOUND_OF_ALL_ACCOUNT_SIZES: usize = 20536; /// After instantiating the setup `AccountSetup` with `new` (that line will transfer the fields to /// the outer scope), `to_account_info` gives the user an `AccountInfo` pointing to the fields of /// the AccountSetup. -#[repr(align(16))] +#[repr(align(16))] // On Apple systems this is needed to support u128 in the struct pub struct AccountSetup { key: Pubkey, owner: Pubkey, diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 83d39ee5d..d9734a486 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -83,23 +83,23 @@ impl SmaTracker { let datapoint_numerator = i128::from(datapoint.slot_gap) * i128::from(datapoint.price); //Can't overflow because u64::MAX * i64::MAX = i28::MAX let datapoint_denominator = datapoint.slot_gap; - self.current_epoch_denominator += datapoint_denominator; // Can't overflow, it's always smaller than the current solana slot - self.current_epoch_numerator += datapoint_numerator; // Can't overflow, it's always smaller than u64::MAX * i64::MAX = i28::MAX, - // self.current_epoch_numerator = slot_gap1 * price1 + slot_gap2 * price2 + slot_gap3 * - // price3 <= (slot_gap1 + slot_gap2 + slot_gap3) * i64::MAX <= u64::MAX * i64::MAX - // =i128::MAX + // Can't overflow, it's always smaller than the current solana slot + self.current_epoch_denominator += datapoint_denominator; + + // Can't overflow, it's always smaller than u64::MAX * i64::MAX = i28::MAX, + // self.current_epoch_numerator = slot_gap1 * price1 + slot_gap2 * price2 + slot_gap3 * + // price3 <= (slot_gap1 + slot_gap2 + slot_gap3) * i64::MAX <= u64::MAX * i64::MAX + // =i128::MAX + self.current_epoch_numerator += datapoint_numerator; self.current_epoch_is_valid = self.current_epoch_is_valid && datapoint_denominator <= self.threshold; - // This for loop is highly inefficient, but this is what the behavior should be - // It updates all the epochs that got skipped - // This will always yield an estimate of the average, even for invalid epochs - + // If epoch changed, if epoch_0 < epoch_1 { let index = epoch_0.rem_euclid(NUM_ENTRIES); - let prev_index = (epoch_0 + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); // epoch <= time <= i64::MAX <= u64::MAX / 2, so this will only overflow if NUM_ENTRIES - // ~ - // u64::MAX / 2 + // epoch <= time <= i64::MAX <= u64::MAX / 2, so this will only overflow if + // NUM_ENTRIES~u64::MAX / 2 + let prev_index = (epoch_0 + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages [prev_index] @@ -120,18 +120,26 @@ impl SmaTracker { self.current_epoch_numerator = datapoint_numerator; self.current_epoch_is_valid = datapoint_denominator <= self.threshold; - let fraction = datapoint_numerator / i128::from(datapoint_denominator); + let one_point_average = datapoint_numerator / i128::from(datapoint_denominator); + + // If at least one epoch got skipped, check all buckets for updates if epoch_0 + 1 < epoch_1 { for i in 1..NUM_ENTRIES + 1 { let current_bucket = (epoch_0 + i) % NUM_ENTRIES; let times_bucket_skipped = self.get_times_bucket_skipped(current_bucket, epoch_0, epoch_1); let bucket_0 = (epoch_0) % NUM_ENTRIES; + // If bucket got skipped, we need to update the running sum if times_bucket_skipped > 0 { + // The running sums are always smaller than epoch_1 * i64::MAX, so it should + // never overflow self.running_sum_of_price_averages[current_bucket] = self .running_sum_of_price_averages[bucket_0] - + ((i + (times_bucket_skipped - 1) * NUM_ENTRIES) as i128) * fraction; + + ((i + (times_bucket_skipped - 1) * NUM_ENTRIES) as i128) + * one_point_average; + // The running counter is always smaller than epoch_1, so it should never + // overflow if self.current_epoch_is_valid { self.running_valid_epoch_counter[current_bucket] = self .running_valid_epoch_counter[bucket_0] @@ -153,7 +161,7 @@ impl SmaTracker { let bucket_0 = epoch_0 % NUM_ENTRIES; let bucket_1 = epoch_1 % NUM_ENTRIES; let is_between = (bucket_0 < bucket && bucket < bucket_1) - || (bucket_1 <= bucket_0) && ((bucket < bucket_1) || (bucket > bucket_0)); + || (bucket_1 <= bucket_0) && ((bucket_0 < bucket) || (bucket < bucket_1)); (epoch_1 - 1 - epoch_0) / NUM_ENTRIES + usize::from(is_between) } } From d71c0f68274ed434b6bc9d5a1d1ae636ca6c4f66 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 12:23:25 -0500 Subject: [PATCH 19/30] New implementation --- .../src/tests/test_sma_epoch_transition.rs | 26 +++--- program/rust/src/time_machine_types.rs | 84 +++++++++++-------- 2 files changed, 65 insertions(+), 45 deletions(-) diff --git a/program/rust/src/tests/test_sma_epoch_transition.rs b/program/rust/src/tests/test_sma_epoch_transition.rs index 69c48f949..02c5b938f 100644 --- a/program/rust/src/tests/test_sma_epoch_transition.rs +++ b/program/rust/src/tests/test_sma_epoch_transition.rs @@ -78,6 +78,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + // No successful aggregation yet, so everything is 0 assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -92,7 +93,7 @@ fn test_sma_epoch_transition() { } } - // Same epoch, small slot gap + // Same epoch, valid slot gap update_clock_slot(&mut clock_account, 2); update_clock_timestamp(&mut clock_account, 2); populate_instruction(&mut instruction_data, 80, 2, 2); @@ -110,7 +111,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); - + // successful aggregation, price update is average between 0 and 42 assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -125,7 +126,7 @@ fn test_sma_epoch_transition() { } } - // Next epoch, small slot gap + // Next epoch, valid slot gap update_clock_slot(&mut clock_account, 3); update_clock_timestamp(&mut clock_account, THIRTY_MINUTES); populate_instruction(&mut instruction_data, 120, 1, 3); @@ -144,6 +145,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + // Slot gap is valid, so successful aggregation and 1 epoch transition should happen assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -168,12 +170,12 @@ fn test_sma_epoch_transition() { assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); } - // Same epoch, big slot gap + // Same epoch, invalid slot gap update_clock_slot(&mut clock_account, 30); update_clock_timestamp(&mut clock_account, THIRTY_MINUTES + 1); populate_instruction(&mut instruction_data, 40, 1, 30); - // Unsuccesful aggregation + // Unsuccessful aggregation assert!(process_instruction( &program_id, &[ @@ -187,7 +189,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); - + // Slot gap is invalid, so aggregation didn't take place and smas are not updated assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -212,6 +214,7 @@ fn test_sma_epoch_transition() { assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); } + // Next epoch, valid slot gap update_clock_slot(&mut clock_account, 31); update_clock_timestamp(&mut clock_account, 2 * THIRTY_MINUTES + 1); populate_instruction(&mut instruction_data, 41, 1, 31); @@ -230,7 +233,8 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); - + // Aggregation is successful and sma is computed, update is invalid because slot_gap from + // previous successful aggregation is big assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -280,7 +284,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); - + // Aggregation was successful, check that all skipped buckets got updated assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -334,7 +338,7 @@ fn test_sma_epoch_transition() { update_clock_timestamp(&mut clock_account, 100 * THIRTY_MINUTES + 1); populate_instruction(&mut instruction_data, 100, 1, 100); - // Unsuccesful aggregation + // Unsuccessful aggregation assert!(process_instruction( &program_id, &[ @@ -348,6 +352,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); + // Nothing got updated, since slot gap was too big, so aggregation was not successful assert_eq!( price_data.time_machine.threshold, @@ -415,7 +420,7 @@ fn test_sma_epoch_transition() { { let price_data = load_checked::(&price_account, PC_VERSION).unwrap(); - + // The entire buffer got rewritten assert_eq!( price_data.time_machine.threshold, PC_MAX_SEND_LATENCY as u64 @@ -427,7 +432,6 @@ fn test_sma_epoch_transition() { ); assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 69); - for i in 0..NUM_BUCKETS_THIRTY_MIN { assert_eq!( price_data.time_machine.running_sum_of_price_averages diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index d9734a486..6bae3f18c 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -119,36 +119,52 @@ impl SmaTracker { self.current_epoch_denominator = datapoint_denominator; self.current_epoch_numerator = datapoint_numerator; self.current_epoch_is_valid = datapoint_denominator <= self.threshold; + } + if epoch_0 + 1 < epoch_1 { let one_point_average = datapoint_numerator / i128::from(datapoint_denominator); + let mut i = 1; + let mut current_bucket = (epoch_0 + 1) % NUM_ENTRIES; + let bucket_0 = epoch_0 % NUM_ENTRIES; + let bucket_1 = epoch_1 % NUM_ENTRIES; + let number_of_full_wraparound = (epoch_1 - 1 - epoch_0) / NUM_ENTRIES; + while current_bucket != bucket_1 { + self.running_sum_of_price_averages[current_bucket] = self + .running_sum_of_price_averages[bucket_0] + + ((i + number_of_full_wraparound * NUM_ENTRIES) as i128) * one_point_average; + + // // The running counter is always smaller than epoch_1, so it + // should never // overflow + if self.current_epoch_is_valid { + self.running_valid_epoch_counter[current_bucket] = self + .running_valid_epoch_counter[bucket_0] + + ((i + number_of_full_wraparound * NUM_ENTRIES) as u64); + } else { + self.running_valid_epoch_counter[current_bucket] = + self.running_valid_epoch_counter[bucket_0]; + } - // If at least one epoch got skipped, check all buckets for updates - if epoch_0 + 1 < epoch_1 { - for i in 1..NUM_ENTRIES + 1 { - let current_bucket = (epoch_0 + i) % NUM_ENTRIES; - let times_bucket_skipped = - self.get_times_bucket_skipped(current_bucket, epoch_0, epoch_1); - let bucket_0 = (epoch_0) % NUM_ENTRIES; - // If bucket got skipped, we need to update the running sum - if times_bucket_skipped > 0 { - // The running sums are always smaller than epoch_1 * i64::MAX, so it should - // never overflow - self.running_sum_of_price_averages[current_bucket] = self - .running_sum_of_price_averages[bucket_0] - + ((i + (times_bucket_skipped - 1) * NUM_ENTRIES) as i128) - * one_point_average; - - // The running counter is always smaller than epoch_1, so it should never - // overflow - if self.current_epoch_is_valid { - self.running_valid_epoch_counter[current_bucket] = self - .running_valid_epoch_counter[bucket_0] - + ((i + (times_bucket_skipped - 1) * NUM_ENTRIES) as u64); - } else { - self.running_valid_epoch_counter[current_bucket] = - self.running_valid_epoch_counter[bucket_0]; - } + i += 1; + current_bucket = (current_bucket + 1) % NUM_ENTRIES; + } + + if number_of_full_wraparound > 0 { + while i != NUM_ENTRIES + 1 { + self.running_sum_of_price_averages[current_bucket] = self + .running_sum_of_price_averages[bucket_0] + + ((i + (number_of_full_wraparound - 1) * NUM_ENTRIES) as i128) + * one_point_average; + + if self.current_epoch_is_valid { + self.running_valid_epoch_counter[current_bucket] = self + .running_valid_epoch_counter[bucket_0] + + ((i + (number_of_full_wraparound - 1) * NUM_ENTRIES) as u64); + } else { + self.running_valid_epoch_counter[current_bucket] = + self.running_valid_epoch_counter[bucket_0]; } + i += 1; + current_bucket = (current_bucket + 1) % NUM_ENTRIES; } } } @@ -156,14 +172,14 @@ impl SmaTracker { Ok(()) } - /// Counts the times bucket `bucket` was skipped when going from `epoch_0` to `epoch_1` - pub fn get_times_bucket_skipped(&self, bucket: usize, epoch_0: usize, epoch_1: usize) -> usize { - let bucket_0 = epoch_0 % NUM_ENTRIES; - let bucket_1 = epoch_1 % NUM_ENTRIES; - let is_between = (bucket_0 < bucket && bucket < bucket_1) - || (bucket_1 <= bucket_0) && ((bucket_0 < bucket) || (bucket < bucket_1)); - (epoch_1 - 1 - epoch_0) / NUM_ENTRIES + usize::from(is_between) - } + // Counts the times bucket `bucket` was skipped when going from `epoch_0` to `epoch_1` + // pub fn get_times_bucket_skipped(&self, bucket: usize, epoch_0: usize, epoch_1: usize) -> + // usize { let bucket_0 = epoch_0 % NUM_ENTRIES; + // let bucket_1 = epoch_1 % NUM_ENTRIES; + // let is_between = (bucket_0 < bucket && bucket < bucket_1) + // || (bucket_1 <= bucket_0) && ((bucket_0 < bucket) || (bucket < bucket_1)); + // (epoch_1 - 1 - epoch_0) / NUM_ENTRIES + usize::from(is_between) + // } } #[cfg(target_endian = "little")] From d5956c36ccc21eda7f49bdbfe457b5c47c032ed4 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 12:33:31 -0500 Subject: [PATCH 20/30] New implementation --- program/rust/src/time_machine_types.rs | 37 +++++++++++++------------- 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 6bae3f18c..d50cea9bd 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -55,12 +55,27 @@ impl PriceAccountWrapper { #[derive(Debug, Copy, Clone)] #[repr(C)] pub struct SmaTracker { + /// The maximum gap in slots for an epoch's sma to be valid, we set it to PC_MAX_SEND_LATENCY pub threshold: u64, + /// The legth of one sma epoch. pub granularity: i64, + /// Numerator for the current epoch (ex : slot_gap1 * price_1 + slot_gap2 * price_2 + slot_gap3 + /// * price_3) + /// It can never overflow because : + /// slot_gap1 * price_1 + slot_gap2 * price_2 + slot_gap3 * price_3 <= (slot_gap1 + slot_gap2 + + /// slot_gap3) * i64::MAX <= clock_slot * i128::MAX pub current_epoch_numerator: i128, + /// Denominator for the current epoch (ex : slot_gap1 + slot_gap2 + slot_gap3) + /// It can never overflow because : (slot_gap1 + slot_gap2 + slot_gap3) <= clock_slot pub current_epoch_denominator: u64, + /// Whether the current epoch is valid (i.e. max slot_gap <= threshold) for all the epochs + /// updates pub current_epoch_is_valid: bool, + /// Stores the running sum of individual epoch averages, we can support u64::MAX epochs. And + /// clock.unix_timestamp <= u64::MAX so the clock will break first. pub running_sum_of_price_averages: [i128; NUM_BUCKETS], + /// Stores the number of valid epochs since inception, we can support u64::MAX epochs. And + /// clock.unix_timestamp <= u64::MAX so the clock will break first. pub running_valid_epoch_counter: [u64; NUM_BUCKETS], } @@ -80,17 +95,12 @@ impl SmaTracker { let epoch_0 = self.time_to_epoch(datapoint.last_two_timestamps.0)?; let epoch_1 = self.time_to_epoch(datapoint.last_two_timestamps.1)?; - let datapoint_numerator = i128::from(datapoint.slot_gap) * i128::from(datapoint.price); //Can't overflow because u64::MAX * i64::MAX = i28::MAX + let datapoint_numerator = i128::from(datapoint.slot_gap) * i128::from(datapoint.price); let datapoint_denominator = datapoint.slot_gap; - // Can't overflow, it's always smaller than the current solana slot self.current_epoch_denominator += datapoint_denominator; - - // Can't overflow, it's always smaller than u64::MAX * i64::MAX = i28::MAX, - // self.current_epoch_numerator = slot_gap1 * price1 + slot_gap2 * price2 + slot_gap3 * - // price3 <= (slot_gap1 + slot_gap2 + slot_gap3) * i64::MAX <= u64::MAX * i64::MAX - // =i128::MAX self.current_epoch_numerator += datapoint_numerator; + self.current_epoch_is_valid = self.current_epoch_is_valid && datapoint_denominator <= self.threshold; @@ -121,20 +131,20 @@ impl SmaTracker { self.current_epoch_is_valid = datapoint_denominator <= self.threshold; } + // If at least one epoch has been skipped if epoch_0 + 1 < epoch_1 { let one_point_average = datapoint_numerator / i128::from(datapoint_denominator); let mut i = 1; let mut current_bucket = (epoch_0 + 1) % NUM_ENTRIES; let bucket_0 = epoch_0 % NUM_ENTRIES; let bucket_1 = epoch_1 % NUM_ENTRIES; + // Number of times let number_of_full_wraparound = (epoch_1 - 1 - epoch_0) / NUM_ENTRIES; while current_bucket != bucket_1 { self.running_sum_of_price_averages[current_bucket] = self .running_sum_of_price_averages[bucket_0] + ((i + number_of_full_wraparound * NUM_ENTRIES) as i128) * one_point_average; - // // The running counter is always smaller than epoch_1, so it - // should never // overflow if self.current_epoch_is_valid { self.running_valid_epoch_counter[current_bucket] = self .running_valid_epoch_counter[bucket_0] @@ -171,15 +181,6 @@ impl SmaTracker { Ok(()) } - - // Counts the times bucket `bucket` was skipped when going from `epoch_0` to `epoch_1` - // pub fn get_times_bucket_skipped(&self, bucket: usize, epoch_0: usize, epoch_1: usize) -> - // usize { let bucket_0 = epoch_0 % NUM_ENTRIES; - // let bucket_1 = epoch_1 % NUM_ENTRIES; - // let is_between = (bucket_0 < bucket && bucket < bucket_1) - // || (bucket_1 <= bucket_0) && ((bucket_0 < bucket) || (bucket < bucket_1)); - // (epoch_1 - 1 - epoch_0) / NUM_ENTRIES + usize::from(is_between) - // } } #[cfg(target_endian = "little")] From 032f7b911d823de358b1c7eab674d32f1f1ef151 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 12:39:23 -0500 Subject: [PATCH 21/30] Comments --- program/rust/src/time_machine_types.rs | 40 ++++++++++++++------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index d50cea9bd..e083bb792 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -79,7 +79,7 @@ pub struct SmaTracker { pub running_valid_epoch_counter: [u64; NUM_BUCKETS], } -impl SmaTracker { +impl SmaTracker { pub fn time_to_epoch(&self, time: i64) -> Result { try_convert::(time / self.granularity) // Can never fail because usize is u64 // and time is positive @@ -104,12 +104,12 @@ impl SmaTracker { self.current_epoch_is_valid = self.current_epoch_is_valid && datapoint_denominator <= self.threshold; - // If epoch changed, + // If epoch changed if epoch_0 < epoch_1 { - let index = epoch_0.rem_euclid(NUM_ENTRIES); - // epoch <= time <= i64::MAX <= u64::MAX / 2, so this will only overflow if - // NUM_ENTRIES~u64::MAX / 2 - let prev_index = (epoch_0 + NUM_ENTRIES - 1).rem_euclid(NUM_ENTRIES); + let index = epoch_0.rem_euclid(NUM_BUCKETS); + + // This addition can only overflow if NUM_BUCKETS ~ u64::MAX / 2 + let prev_index = (epoch_0 + NUM_BUCKETS - 1).rem_euclid(NUM_BUCKETS); self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages [prev_index] @@ -135,46 +135,50 @@ impl SmaTracker { if epoch_0 + 1 < epoch_1 { let one_point_average = datapoint_numerator / i128::from(datapoint_denominator); let mut i = 1; - let mut current_bucket = (epoch_0 + 1) % NUM_ENTRIES; - let bucket_0 = epoch_0 % NUM_ENTRIES; - let bucket_1 = epoch_1 % NUM_ENTRIES; - // Number of times - let number_of_full_wraparound = (epoch_1 - 1 - epoch_0) / NUM_ENTRIES; + let mut current_bucket = (epoch_0 + 1) % NUM_BUCKETS; + let bucket_0 = epoch_0 % NUM_BUCKETS; + let bucket_1 = epoch_1 % NUM_BUCKETS; + + // Number of times we have wrapped around the buffer + let number_of_full_wraparound = (epoch_1 - 1 - epoch_0) / NUM_BUCKETS; + + // These buckets are "inside" (bucket_0, bucket_1) while current_bucket != bucket_1 { self.running_sum_of_price_averages[current_bucket] = self .running_sum_of_price_averages[bucket_0] - + ((i + number_of_full_wraparound * NUM_ENTRIES) as i128) * one_point_average; + + ((i + number_of_full_wraparound * NUM_BUCKETS) as i128) * one_point_average; if self.current_epoch_is_valid { self.running_valid_epoch_counter[current_bucket] = self .running_valid_epoch_counter[bucket_0] - + ((i + number_of_full_wraparound * NUM_ENTRIES) as u64); + + ((i + number_of_full_wraparound * NUM_BUCKETS) as u64); } else { self.running_valid_epoch_counter[current_bucket] = self.running_valid_epoch_counter[bucket_0]; } i += 1; - current_bucket = (current_bucket + 1) % NUM_ENTRIES; + current_bucket = (current_bucket + 1) % NUM_BUCKETS; } if number_of_full_wraparound > 0 { - while i != NUM_ENTRIES + 1 { + // These buckets are "outside" (bucket_0, bucket_1) + while i != NUM_BUCKETS + 1 { self.running_sum_of_price_averages[current_bucket] = self .running_sum_of_price_averages[bucket_0] - + ((i + (number_of_full_wraparound - 1) * NUM_ENTRIES) as i128) + + ((i + (number_of_full_wraparound - 1) * NUM_BUCKETS) as i128) * one_point_average; if self.current_epoch_is_valid { self.running_valid_epoch_counter[current_bucket] = self .running_valid_epoch_counter[bucket_0] - + ((i + (number_of_full_wraparound - 1) * NUM_ENTRIES) as u64); + + ((i + (number_of_full_wraparound - 1) * NUM_BUCKETS) as u64); } else { self.running_valid_epoch_counter[current_bucket] = self.running_valid_epoch_counter[bucket_0]; } i += 1; - current_bucket = (current_bucket + 1) % NUM_ENTRIES; + current_bucket = (current_bucket + 1) % NUM_BUCKETS; } } } From 9880fe37fc03fac7f40c8de7e6dc75b8cfc09615 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 12:51:29 -0500 Subject: [PATCH 22/30] Some cleanup --- program/rust/src/tests/test_sma.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index f0574d0ef..acf8dfccd 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -18,7 +18,8 @@ impl Arbitrary for DataEvent { fn arbitrary(g: &mut quickcheck::Gen) -> Self { DataEvent { timegap: i64::from(u8::arbitrary(g)), - slot_gap: u64::from(u8::arbitrary(g)) + 1, + slot_gap: u64::from(u8::arbitrary(g)) + 1, /* Slot gap is always > 1, because there + * has been a succesful aggregation */ price: i64::arbitrary(g), } } @@ -26,7 +27,7 @@ impl Arbitrary for DataEvent { #[quickcheck] -fn test_add_and_delete(input: Vec) -> bool { +fn test_sma(input: Vec) -> bool { // No gaps, no skipped epochs let mut tracker1 = SmaTracker::::zero(); tracker1.initialize(i64::from(u8::MAX), u64::from(u8::MAX)); @@ -114,7 +115,7 @@ impl SmaTracker { // Get running sums let running_sum_price_iter = values.iter().scan((0, 0), |res, &y| { - res.0 = res.0 + y.1.clone() / i128::from(y.0.clone()); + res.0 = res.0 + y.1 / i128::from(y.0); res.1 = res.1 + u64::from(y.2); Some(*res) }); @@ -151,6 +152,7 @@ impl SmaTracker { let result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { if !((left_bound > y.last_two_timestamps.1) || (right_bound <= y.last_two_timestamps.0)) + //Check interval intersection { let is_valid = y.slot_gap <= self.threshold; return ( From 0d718ce3371359cca69a6966bc55391753935227 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Wed, 7 Sep 2022 18:13:35 -0500 Subject: [PATCH 23/30] Gate everything by test flags --- program/rust/src/tests/test_resize_account.rs | 17 ++++------------- program/rust/src/time_machine_types.rs | 4 ++++ 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/program/rust/src/tests/test_resize_account.rs b/program/rust/src/tests/test_resize_account.rs index fca51370b..15c598173 100644 --- a/program/rust/src/tests/test_resize_account.rs +++ b/program/rust/src/tests/test_resize_account.rs @@ -1,15 +1,9 @@ use solana_sdk::signer::Signer; use std::mem::size_of; -use crate::c_oracle_header::{ - pc_price_t, - PC_MAX_SEND_LATENCY, -}; +use crate::c_oracle_header::pc_price_t; use crate::tests::pyth_simulator::PythSimulator; -use crate::time_machine_types::{ - PriceAccountWrapper, - THIRTY_MINUTES, -}; +use crate::time_machine_types::PriceAccountWrapper; /// Warning : This test will fail if you run cargo test instead of cargo test-bpf @@ -38,9 +32,6 @@ async fn test_resize_account() { .get_account_data_as::(price1.pubkey()) .await .unwrap(); - assert_eq!(price1_account_data.time_machine.granularity, THIRTY_MINUTES); - assert_eq!( - price1_account_data.time_machine.threshold, - PC_MAX_SEND_LATENCY as u64 - ); + assert_eq!(price1_account_data.time_machine.granularity, 0); + assert_eq!(price1_account_data.time_machine.threshold, 0); } diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index e083bb792..bf1429e33 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -1,3 +1,5 @@ +#![allow(unused_imports)] +#![allow(dead_code)] use crate::c_oracle_header::{ PriceAccount, PythAccount, @@ -36,12 +38,14 @@ pub struct DataPoint { impl PriceAccountWrapper { pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { + #[cfg(test)] self.time_machine .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY.into()); Ok(()) } pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { + #[cfg(test)] self.time_machine.add_datapoint( &DataPoint{ last_two_timestamps : (self.price_data.prev_timestamp_, self.price_data.timestamp_), slot_gap : (self.price_data.last_slot_ - self.price_data.prev_slot_), From bec400ee259f2d7c375c0c726d80dc6011a6e539 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 12:31:52 -0500 Subject: [PATCH 24/30] PR feedback --- program/rust/src/tests/test_sma.rs | 9 +++++---- program/rust/src/time_machine_types.rs | 22 ++++++++++++---------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index acf8dfccd..6364fab39 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -53,9 +53,10 @@ fn test_sma(input: Vec) -> bool { let mut current_time = 0i64; for data_event in input.clone() { let datapoint = DataPoint { - last_two_timestamps: (current_time, current_time + data_event.timegap), - slot_gap: data_event.slot_gap, - price: data_event.price, + previous_timestamp: current_time, + current_timestamp: current_time + data_event.timegap, + slot_gap: data_event.slot_gap, + price: data_event.price, }; tracker1.add_datapoint(&datapoint).unwrap(); @@ -151,7 +152,7 @@ impl SmaTracker { let result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { - if !((left_bound > y.last_two_timestamps.1) || (right_bound <= y.last_two_timestamps.0)) + if !((left_bound > y.current_timestamp) || (right_bound <= y.previous_timestamp)) //Check interval intersection { let is_valid = y.slot_gap <= self.threshold; diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index bf1429e33..da0c0f5e5 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -31,9 +31,10 @@ pub struct PriceAccountWrapper { #[derive(Debug)] pub struct DataPoint { - pub last_two_timestamps: (i64, i64), - pub slot_gap: u64, - pub price: i64, + pub previous_timestamp: i64, + pub current_timestamp: i64, + pub slot_gap: u64, + pub price: i64, } impl PriceAccountWrapper { @@ -47,9 +48,10 @@ impl PriceAccountWrapper { pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { #[cfg(test)] self.time_machine.add_datapoint( &DataPoint{ - last_two_timestamps : (self.price_data.prev_timestamp_, self.price_data.timestamp_), + previous_timestamp : self.price_data.prev_timestamp_, + current_timestamp: self.price_data.timestamp_, slot_gap : (self.price_data.last_slot_ - self.price_data.prev_slot_), - price: self.price_data.prev_price_ /2 + self.price_data.agg_.price_ / 2 + (self.price_data.prev_price_ % 2) * (self.price_data.agg_.price_ % 2), // Hack to avoid overflow? + price: self.price_data.prev_price_ /2 + self.price_data.agg_.price_ / 2 + (self.price_data.prev_price_ % 2) * (self.price_data.agg_.price_ % 2), // Hack to avoid overflow } )?; Ok(()) @@ -59,15 +61,15 @@ impl PriceAccountWrapper { #[derive(Debug, Copy, Clone)] #[repr(C)] pub struct SmaTracker { - /// The maximum gap in slots for an epoch's sma to be valid, we set it to PC_MAX_SEND_LATENCY + /// The maximum gap in slots for an epoch's sma to be valid pub threshold: u64, - /// The legth of one sma epoch. + /// The length of one sma epoch. pub granularity: i64, /// Numerator for the current epoch (ex : slot_gap1 * price_1 + slot_gap2 * price_2 + slot_gap3 /// * price_3) /// It can never overflow because : /// slot_gap1 * price_1 + slot_gap2 * price_2 + slot_gap3 * price_3 <= (slot_gap1 + slot_gap2 + - /// slot_gap3) * i64::MAX <= clock_slot * i128::MAX + /// slot_gap3) * i64::MAX <= clock_slot * i64::MAX <= i128::MAX pub current_epoch_numerator: i128, /// Denominator for the current epoch (ex : slot_gap1 + slot_gap2 + slot_gap3) /// It can never overflow because : (slot_gap1 + slot_gap2 + slot_gap3) <= clock_slot @@ -96,8 +98,8 @@ impl SmaTracker { } pub fn add_datapoint(&mut self, datapoint: &DataPoint) -> Result<(), OracleError> { - let epoch_0 = self.time_to_epoch(datapoint.last_two_timestamps.0)?; - let epoch_1 = self.time_to_epoch(datapoint.last_two_timestamps.1)?; + let epoch_0 = self.time_to_epoch(datapoint.previous_timestamp)?; + let epoch_1 = self.time_to_epoch(datapoint.current_timestamp)?; let datapoint_numerator = i128::from(datapoint.slot_gap) * i128::from(datapoint.price); let datapoint_denominator = datapoint.slot_gap; From 9515495d8e902dc404f12494990f792fb786413b Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 12:58:34 -0500 Subject: [PATCH 25/30] Fix comments --- program/rust/src/time_machine_types.rs | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index da0c0f5e5..9d5bfcf5e 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -77,11 +77,15 @@ pub struct SmaTracker { /// Whether the current epoch is valid (i.e. max slot_gap <= threshold) for all the epochs /// updates pub current_epoch_is_valid: bool, - /// Stores the running sum of individual epoch averages, we can support u64::MAX epochs. And - /// clock.unix_timestamp <= u64::MAX so the clock will break first. + /// Stores the running sum of individual epoch averages ( = current_epoch_numerator / + /// current_epoch_denominator). Each term of the running sum is an average price, at most + /// i64::MAX. If N is the number of epochs elapsed, as long as N <= u64::MAX we have + /// running_sum_of_price_averages[i] <= N * i64::MAX <= u64::MAX * i64::MAX <= i128::MAX. + /// Therefore we can support at least u64::MAX epochs. pub running_sum_of_price_averages: [i128; NUM_BUCKETS], - /// Stores the number of valid epochs since inception, we can support u64::MAX epochs. And - /// clock.unix_timestamp <= u64::MAX so the clock will break first. + /// Stores the number of valid epochs since inception. + /// Each time, at most 1 is added to the sum, therefore we can support at least u64::MAX epochs + /// without overflow. pub running_valid_epoch_counter: [u64; NUM_BUCKETS], } @@ -120,13 +124,10 @@ impl SmaTracker { self.running_sum_of_price_averages[index] = self.running_sum_of_price_averages [prev_index] + self.current_epoch_numerator / i128::from(self.current_epoch_denominator); - // The fraction here is smaller than i64::MAX , so we can support u64::MAX updates if self.current_epoch_is_valid { self.running_valid_epoch_counter[index] = - self.running_valid_epoch_counter[prev_index] + 1; // Likewise can support - // u64::MAX - // epochs + self.running_valid_epoch_counter[prev_index] + 1; } else { self.running_valid_epoch_counter[index] = self.running_valid_epoch_counter[prev_index] From 35057cc1d206fba512324b53ea3cf414264dc5e3 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 13:30:15 -0500 Subject: [PATCH 26/30] Feedback --- program/rust/src/tests/test_sma.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index 6364fab39..257874d60 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -9,7 +9,7 @@ use crate::time_machine_types::{ #[derive(Clone, Debug, Copy)] struct DataEvent { - timegap: i64, + time_gap: i64, slot_gap: u64, price: i64, } @@ -17,7 +17,7 @@ struct DataEvent { impl Arbitrary for DataEvent { fn arbitrary(g: &mut quickcheck::Gen) -> Self { DataEvent { - timegap: i64::from(u8::arbitrary(g)), + time_gap: i64::from(u8::arbitrary(g)), slot_gap: u64::from(u8::arbitrary(g)) + 1, /* Slot gap is always > 1, because there * has been a succesful aggregation */ price: i64::arbitrary(g), @@ -54,7 +54,7 @@ fn test_sma(input: Vec) -> bool { for data_event in input.clone() { let datapoint = DataPoint { previous_timestamp: current_time, - current_timestamp: current_time + data_event.timegap, + current_timestamp: current_time + data_event.time_gap, slot_gap: data_event.slot_gap, price: data_event.price, }; @@ -65,7 +65,7 @@ fn test_sma(input: Vec) -> bool { tracker4.add_datapoint(&datapoint).unwrap(); tracker5.add_datapoint(&datapoint).unwrap(); data.push(datapoint); - current_time += data_event.timegap; + current_time += data_event.time_gap; tracker1.check_current_epoch_fields(&data, current_time); tracker2.check_current_epoch_fields(&data, current_time); From cb129fe145f84413aaf34d75273718ef2e110f94 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 13:44:01 -0500 Subject: [PATCH 27/30] Add comment --- program/rust/bindings2.rs | 2033 ++++++++++++++++++++++++++++ program/rust/src/permissions.rs | 7 + program/rust/src/tests/test_sma.rs | 8 +- 3 files changed, 2047 insertions(+), 1 deletion(-) create mode 100644 program/rust/bindings2.rs create mode 100644 program/rust/src/permissions.rs diff --git a/program/rust/bindings2.rs b/program/rust/bindings2.rs new file mode 100644 index 000000000..b8528538a --- /dev/null +++ b/program/rust/bindings2.rs @@ -0,0 +1,2033 @@ +/* automatically generated by rust-bindgen 0.60.1 */ + +#[repr(C)] +#[derive(Default)] +pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); +impl __IncompleteArrayField { + #[inline] + pub const fn new() -> Self { + __IncompleteArrayField(::std::marker::PhantomData, []) + } + #[inline] + pub fn as_ptr(&self) -> *const T { + self as *const _ as *const T + } + #[inline] + pub fn as_mut_ptr(&mut self) -> *mut T { + self as *mut _ as *mut T + } + #[inline] + pub unsafe fn as_slice(&self, len: usize) -> &[T] { + ::std::slice::from_raw_parts(self.as_ptr(), len) + } + #[inline] + pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { + ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) + } +} +impl ::std::fmt::Debug for __IncompleteArrayField { + fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { + fmt.write_str("__IncompleteArrayField") + } +} +pub const true_: u32 = 1; +pub const false_: u32 = 0; +pub const __bool_true_false_are_defined: u32 = 1; +pub const PYTH_ORACLE_UTIL_COMPAT_STDINT_STYLE: u32 = 0; +pub const __WORDSIZE: u32 = 64; +pub const __DARWIN_ONLY_64_BIT_INO_T: u32 = 1; +pub const __DARWIN_ONLY_UNIX_CONFORMANCE: u32 = 1; +pub const __DARWIN_ONLY_VERS_1050: u32 = 1; +pub const __DARWIN_UNIX03: u32 = 1; +pub const __DARWIN_64_BIT_INO_T: u32 = 1; +pub const __DARWIN_VERS_1050: u32 = 1; +pub const __DARWIN_NON_CANCELABLE: u32 = 0; +pub const __DARWIN_SUF_EXTSN: &[u8; 14usize] = b"$DARWIN_EXTSN\0"; +pub const __DARWIN_C_ANSI: u32 = 4096; +pub const __DARWIN_C_FULL: u32 = 900000; +pub const __DARWIN_C_LEVEL: u32 = 900000; +pub const __STDC_WANT_LIB_EXT1__: u32 = 1; +pub const __DARWIN_NO_LONG_LONG: u32 = 0; +pub const _DARWIN_FEATURE_64_BIT_INODE: u32 = 1; +pub const _DARWIN_FEATURE_ONLY_64_BIT_INODE: u32 = 1; +pub const _DARWIN_FEATURE_ONLY_VERS_1050: u32 = 1; +pub const _DARWIN_FEATURE_ONLY_UNIX_CONFORMANCE: u32 = 1; +pub const _DARWIN_FEATURE_UNIX_CONFORMANCE: u32 = 3; +pub const __has_ptrcheck: u32 = 0; +pub const __PTHREAD_SIZE__: u32 = 8176; +pub const __PTHREAD_ATTR_SIZE__: u32 = 56; +pub const __PTHREAD_MUTEXATTR_SIZE__: u32 = 8; +pub const __PTHREAD_MUTEX_SIZE__: u32 = 56; +pub const __PTHREAD_CONDATTR_SIZE__: u32 = 8; +pub const __PTHREAD_COND_SIZE__: u32 = 40; +pub const __PTHREAD_ONCE_SIZE__: u32 = 8; +pub const __PTHREAD_RWLOCK_SIZE__: u32 = 192; +pub const __PTHREAD_RWLOCKATTR_SIZE__: u32 = 16; +pub const INT8_MAX: u32 = 127; +pub const INT16_MAX: u32 = 32767; +pub const INT32_MAX: u32 = 2147483647; +pub const INT64_MAX: u64 = 9223372036854775807; +pub const INT8_MIN: i32 = -128; +pub const INT16_MIN: i32 = -32768; +pub const INT32_MIN: i32 = -2147483648; +pub const INT64_MIN: i64 = -9223372036854775808; +pub const UINT8_MAX: u32 = 255; +pub const UINT16_MAX: u32 = 65535; +pub const UINT32_MAX: u32 = 4294967295; +pub const UINT64_MAX: i32 = -1; +pub const INT_LEAST8_MIN: i32 = -128; +pub const INT_LEAST16_MIN: i32 = -32768; +pub const INT_LEAST32_MIN: i32 = -2147483648; +pub const INT_LEAST64_MIN: i64 = -9223372036854775808; +pub const INT_LEAST8_MAX: u32 = 127; +pub const INT_LEAST16_MAX: u32 = 32767; +pub const INT_LEAST32_MAX: u32 = 2147483647; +pub const INT_LEAST64_MAX: u64 = 9223372036854775807; +pub const UINT_LEAST8_MAX: u32 = 255; +pub const UINT_LEAST16_MAX: u32 = 65535; +pub const UINT_LEAST32_MAX: u32 = 4294967295; +pub const UINT_LEAST64_MAX: i32 = -1; +pub const INT_FAST8_MIN: i32 = -128; +pub const INT_FAST16_MIN: i32 = -32768; +pub const INT_FAST32_MIN: i32 = -2147483648; +pub const INT_FAST64_MIN: i64 = -9223372036854775808; +pub const INT_FAST8_MAX: u32 = 127; +pub const INT_FAST16_MAX: u32 = 32767; +pub const INT_FAST32_MAX: u32 = 2147483647; +pub const INT_FAST64_MAX: u64 = 9223372036854775807; +pub const UINT_FAST8_MAX: u32 = 255; +pub const UINT_FAST16_MAX: u32 = 65535; +pub const UINT_FAST32_MAX: u32 = 4294967295; +pub const UINT_FAST64_MAX: i32 = -1; +pub const INTPTR_MAX: u64 = 9223372036854775807; +pub const INTPTR_MIN: i64 = -9223372036854775808; +pub const UINTPTR_MAX: i32 = -1; +pub const SIZE_MAX: i32 = -1; +pub const RSIZE_MAX: i32 = -1; +pub const WINT_MIN: i32 = -2147483648; +pub const WINT_MAX: u32 = 2147483647; +pub const SIG_ATOMIC_MIN: i32 = -2147483648; +pub const SIG_ATOMIC_MAX: u32 = 2147483647; +pub const PC_MAGIC: u32 = 2712847316; +pub const PC_VERSION: u32 = 2; +pub const PC_MAX_SEND_LATENCY: u32 = 25; +pub const PC_PUBKEY_SIZE: u32 = 32; +pub const PC_MAP_TABLE_SIZE: u32 = 640; +pub const PC_COMP_SIZE: u32 = 32; +pub const PC_MAX_NUM_DECIMALS: u32 = 8; +pub const PC_PROD_ACC_SIZE: u32 = 512; +pub const PC_EXP_DECAY: i32 = -9; +pub const PC_MAX_CI_DIVISOR: u32 = 20; +pub const PC_HEAP_START: u64 = 12884901888; +pub const PC_PTYPE_UNKNOWN: u32 = 0; +pub const PC_PTYPE_PRICE: u32 = 1; +pub const PC_STATUS_UNKNOWN: u32 = 0; +pub const PC_STATUS_TRADING: u32 = 1; +pub const PC_STATUS_HALTED: u32 = 2; +pub const PC_STATUS_AUCTION: u32 = 3; +pub const PC_ACCTYPE_MAPPING: u32 = 1; +pub const PC_ACCTYPE_PRODUCT: u32 = 2; +pub const PC_ACCTYPE_PRICE: u32 = 3; +pub const PC_ACCTYPE_TEST: u32 = 4; +pub type size_t = ::std::os::raw::c_ulong; +pub type wchar_t = ::std::os::raw::c_int; +pub type max_align_t = f64; +pub type int_least8_t = i8; +pub type int_least16_t = i16; +pub type int_least32_t = i32; +pub type int_least64_t = i64; +pub type uint_least8_t = u8; +pub type uint_least16_t = u16; +pub type uint_least32_t = u32; +pub type uint_least64_t = u64; +pub type int_fast8_t = i8; +pub type int_fast16_t = i16; +pub type int_fast32_t = i32; +pub type int_fast64_t = i64; +pub type uint_fast8_t = u8; +pub type uint_fast16_t = u16; +pub type uint_fast32_t = u32; +pub type uint_fast64_t = u64; +pub type __int8_t = ::std::os::raw::c_schar; +pub type __uint8_t = ::std::os::raw::c_uchar; +pub type __int16_t = ::std::os::raw::c_short; +pub type __uint16_t = ::std::os::raw::c_ushort; +pub type __int32_t = ::std::os::raw::c_int; +pub type __uint32_t = ::std::os::raw::c_uint; +pub type __int64_t = ::std::os::raw::c_longlong; +pub type __uint64_t = ::std::os::raw::c_ulonglong; +pub type __darwin_intptr_t = ::std::os::raw::c_long; +pub type __darwin_natural_t = ::std::os::raw::c_uint; +pub type __darwin_ct_rune_t = ::std::os::raw::c_int; +#[repr(C)] +#[derive(Copy, Clone)] +pub union __mbstate_t { + pub __mbstate8: [::std::os::raw::c_char; 128usize], + pub _mbstateL: ::std::os::raw::c_longlong, +} +#[test] +fn bindgen_test_layout___mbstate_t() { + assert_eq!( + ::std::mem::size_of::<__mbstate_t>(), + 128usize, + concat!("Size of: ", stringify!(__mbstate_t)) + ); + assert_eq!( + ::std::mem::align_of::<__mbstate_t>(), + 8usize, + concat!("Alignment of ", stringify!(__mbstate_t)) + ); + fn test_field___mbstate8() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<__mbstate_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__mbstate8) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__mbstate_t), + "::", + stringify!(__mbstate8) + ) + ); + } + test_field___mbstate8(); + fn test_field__mbstateL() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<__mbstate_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr)._mbstateL) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__mbstate_t), + "::", + stringify!(_mbstateL) + ) + ); + } + test_field__mbstateL(); +} +pub type __darwin_mbstate_t = __mbstate_t; +pub type __darwin_ptrdiff_t = ::std::os::raw::c_long; +pub type __darwin_size_t = ::std::os::raw::c_ulong; +pub type __darwin_va_list = __builtin_va_list; +pub type __darwin_wchar_t = ::std::os::raw::c_int; +pub type __darwin_rune_t = __darwin_wchar_t; +pub type __darwin_wint_t = ::std::os::raw::c_int; +pub type __darwin_clock_t = ::std::os::raw::c_ulong; +pub type __darwin_socklen_t = __uint32_t; +pub type __darwin_ssize_t = ::std::os::raw::c_long; +pub type __darwin_time_t = ::std::os::raw::c_long; +pub type __darwin_blkcnt_t = __int64_t; +pub type __darwin_blksize_t = __int32_t; +pub type __darwin_dev_t = __int32_t; +pub type __darwin_fsblkcnt_t = ::std::os::raw::c_uint; +pub type __darwin_fsfilcnt_t = ::std::os::raw::c_uint; +pub type __darwin_gid_t = __uint32_t; +pub type __darwin_id_t = __uint32_t; +pub type __darwin_ino64_t = __uint64_t; +pub type __darwin_ino_t = __darwin_ino64_t; +pub type __darwin_mach_port_name_t = __darwin_natural_t; +pub type __darwin_mach_port_t = __darwin_mach_port_name_t; +pub type __darwin_mode_t = __uint16_t; +pub type __darwin_off_t = __int64_t; +pub type __darwin_pid_t = __int32_t; +pub type __darwin_sigset_t = __uint32_t; +pub type __darwin_suseconds_t = __int32_t; +pub type __darwin_uid_t = __uint32_t; +pub type __darwin_useconds_t = __uint32_t; +pub type __darwin_uuid_t = [::std::os::raw::c_uchar; 16usize]; +pub type __darwin_uuid_string_t = [::std::os::raw::c_char; 37usize]; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct __darwin_pthread_handler_rec { + pub __routine: ::std::option::Option, + pub __arg: *mut ::std::os::raw::c_void, + pub __next: *mut __darwin_pthread_handler_rec, +} +#[test] +fn bindgen_test_layout___darwin_pthread_handler_rec() { + assert_eq!( + ::std::mem::size_of::<__darwin_pthread_handler_rec>(), + 24usize, + concat!("Size of: ", stringify!(__darwin_pthread_handler_rec)) + ); + assert_eq!( + ::std::mem::align_of::<__darwin_pthread_handler_rec>(), + 8usize, + concat!("Alignment of ", stringify!(__darwin_pthread_handler_rec)) + ); + fn test_field___routine() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<__darwin_pthread_handler_rec>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__routine) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(__darwin_pthread_handler_rec), + "::", + stringify!(__routine) + ) + ); + } + test_field___routine(); + fn test_field___arg() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<__darwin_pthread_handler_rec>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__arg) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(__darwin_pthread_handler_rec), + "::", + stringify!(__arg) + ) + ); + } + test_field___arg(); + fn test_field___next() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<__darwin_pthread_handler_rec>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__next) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(__darwin_pthread_handler_rec), + "::", + stringify!(__next) + ) + ); + } + test_field___next(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_attr_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 56usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_attr_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_attr_t>(), + 64usize, + concat!("Size of: ", stringify!(_opaque_pthread_attr_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_attr_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_attr_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_attr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_attr_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_attr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_attr_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_cond_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 40usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_cond_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_cond_t>(), + 48usize, + concat!("Size of: ", stringify!(_opaque_pthread_cond_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_cond_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_cond_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_cond_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_cond_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_cond_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_cond_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_condattr_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 8usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_condattr_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_condattr_t>(), + 16usize, + concat!("Size of: ", stringify!(_opaque_pthread_condattr_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_condattr_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_condattr_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_condattr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_condattr_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_condattr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_condattr_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_mutex_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 56usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_mutex_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_mutex_t>(), + 64usize, + concat!("Size of: ", stringify!(_opaque_pthread_mutex_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_mutex_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_mutex_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutex_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_mutex_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutex_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_mutex_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_mutexattr_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 8usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_mutexattr_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_mutexattr_t>(), + 16usize, + concat!("Size of: ", stringify!(_opaque_pthread_mutexattr_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_mutexattr_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_mutexattr_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutexattr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_mutexattr_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutexattr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_mutexattr_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_once_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 8usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_once_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_once_t>(), + 16usize, + concat!("Size of: ", stringify!(_opaque_pthread_once_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_once_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_once_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_once_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_once_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_once_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_once_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_rwlock_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 192usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_rwlock_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_rwlock_t>(), + 200usize, + concat!("Size of: ", stringify!(_opaque_pthread_rwlock_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_rwlock_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_rwlock_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlock_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_rwlock_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlock_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_rwlock_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_rwlockattr_t { + pub __sig: ::std::os::raw::c_long, + pub __opaque: [::std::os::raw::c_char; 16usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_rwlockattr_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_rwlockattr_t>(), + 24usize, + concat!("Size of: ", stringify!(_opaque_pthread_rwlockattr_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_rwlockattr_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_rwlockattr_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlockattr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_rwlockattr_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlockattr_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_rwlockattr_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct _opaque_pthread_t { + pub __sig: ::std::os::raw::c_long, + pub __cleanup_stack: *mut __darwin_pthread_handler_rec, + pub __opaque: [::std::os::raw::c_char; 8176usize], +} +#[test] +fn bindgen_test_layout__opaque_pthread_t() { + assert_eq!( + ::std::mem::size_of::<_opaque_pthread_t>(), + 8192usize, + concat!("Size of: ", stringify!(_opaque_pthread_t)) + ); + assert_eq!( + ::std::mem::align_of::<_opaque_pthread_t>(), + 8usize, + concat!("Alignment of ", stringify!(_opaque_pthread_t)) + ); + fn test_field___sig() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_t), + "::", + stringify!(__sig) + ) + ); + } + test_field___sig(); + fn test_field___cleanup_stack() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__cleanup_stack) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_t), + "::", + stringify!(__cleanup_stack) + ) + ); + } + test_field___cleanup_stack(); + fn test_field___opaque() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_t>::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(_opaque_pthread_t), + "::", + stringify!(__opaque) + ) + ); + } + test_field___opaque(); +} +pub type __darwin_pthread_attr_t = _opaque_pthread_attr_t; +pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; +pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; +pub type __darwin_pthread_key_t = ::std::os::raw::c_ulong; +pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; +pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; +pub type __darwin_pthread_once_t = _opaque_pthread_once_t; +pub type __darwin_pthread_rwlock_t = _opaque_pthread_rwlock_t; +pub type __darwin_pthread_rwlockattr_t = _opaque_pthread_rwlockattr_t; +pub type __darwin_pthread_t = *mut _opaque_pthread_t; +pub type u_int8_t = ::std::os::raw::c_uchar; +pub type u_int16_t = ::std::os::raw::c_ushort; +pub type u_int32_t = ::std::os::raw::c_uint; +pub type u_int64_t = ::std::os::raw::c_ulonglong; +pub type register_t = i64; +pub type user_addr_t = u_int64_t; +pub type user_size_t = u_int64_t; +pub type user_ssize_t = i64; +pub type user_long_t = i64; +pub type user_ulong_t = u_int64_t; +pub type user_time_t = i64; +pub type user_off_t = i64; +pub type syscall_arg_t = u_int64_t; +pub type intmax_t = ::std::os::raw::c_long; +pub type uintmax_t = ::std::os::raw::c_ulong; +pub const TIME_MACHINE_STRUCT_SIZE: u64 = 1864; +pub const EXTRA_PUBLISHER_SPACE: u64 = 1000; +extern "C" { + pub static sysvar_clock: [u64; 4usize]; +} +#[repr(C)] +#[derive(Copy, Clone)] +pub union pc_pub_key { + pub k1_: [u8; 32usize], + pub k8_: [u64; 4usize], +} +#[test] +fn bindgen_test_layout_pc_pub_key() { + assert_eq!( + ::std::mem::size_of::(), + 32usize, + concat!("Size of: ", stringify!(pc_pub_key)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_pub_key)) + ); + fn test_field_k1_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).k1_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_pub_key), + "::", + stringify!(k1_) + ) + ); + } + test_field_k1_(); + fn test_field_k8_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).k8_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_pub_key), + "::", + stringify!(k8_) + ) + ); + } + test_field_k8_(); +} +pub type pc_pub_key_t = pc_pub_key; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct pc_acc { + pub magic_: u32, + pub ver_: u32, + pub type_: u32, + pub size_: u32, +} +#[test] +fn bindgen_test_layout_pc_acc() { + assert_eq!( + ::std::mem::size_of::(), + 16usize, + concat!("Size of: ", stringify!(pc_acc)) + ); + assert_eq!( + ::std::mem::align_of::(), + 4usize, + concat!("Alignment of ", stringify!(pc_acc)) + ); + fn test_field_magic_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_acc), + "::", + stringify!(magic_) + ) + ); + } + test_field_magic_(); + fn test_field_ver_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(pc_acc), + "::", + stringify!(ver_) + ) + ); + } + test_field_ver_(); + fn test_field_type_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(pc_acc), + "::", + stringify!(type_) + ) + ); + } + test_field_type_(); + fn test_field_size_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(pc_acc), + "::", + stringify!(size_) + ) + ); + } + test_field_size_(); +} +pub type pc_acc_t = pc_acc; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pc_map_table { + pub magic_: u32, + pub ver_: u32, + pub type_: u32, + pub size_: u32, + pub num_: u32, + pub unused_: u32, + pub next_: pc_pub_key_t, + pub prod_: [pc_pub_key_t; 640usize], +} +#[test] +fn bindgen_test_layout_pc_map_table() { + assert_eq!( + ::std::mem::size_of::(), + 20536usize, + concat!("Size of: ", stringify!(pc_map_table)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_map_table)) + ); + fn test_field_magic_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(magic_) + ) + ); + } + test_field_magic_(); + fn test_field_ver_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(ver_) + ) + ); + } + test_field_ver_(); + fn test_field_type_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(type_) + ) + ); + } + test_field_type_(); + fn test_field_size_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(size_) + ) + ); + } + test_field_size_(); + fn test_field_num_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).num_) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(num_) + ) + ); + } + test_field_num_(); + fn test_field_unused_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).unused_) as usize - ptr as usize + }, + 20usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(unused_) + ) + ); + } + test_field_unused_(); + fn test_field_next_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).next_) as usize - ptr as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(next_) + ) + ); + } + test_field_next_(); + fn test_field_prod_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).prod_) as usize - ptr as usize + }, + 56usize, + concat!( + "Offset of field: ", + stringify!(pc_map_table), + "::", + stringify!(prod_) + ) + ); + } + test_field_prod_(); +} +pub type pc_map_table_t = pc_map_table; +#[repr(C)] +#[derive(Debug)] +pub struct pc_str { + pub len_: u8, + pub data_: __IncompleteArrayField<::std::os::raw::c_char>, +} +#[test] +fn bindgen_test_layout_pc_str() { + assert_eq!( + ::std::mem::size_of::(), + 1usize, + concat!("Size of: ", stringify!(pc_str)) + ); + assert_eq!( + ::std::mem::align_of::(), + 1usize, + concat!("Alignment of ", stringify!(pc_str)) + ); + fn test_field_len_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).len_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_str), + "::", + stringify!(len_) + ) + ); + } + test_field_len_(); + fn test_field_data_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).data_) as usize - ptr as usize + }, + 1usize, + concat!( + "Offset of field: ", + stringify!(pc_str), + "::", + stringify!(data_) + ) + ); + } + test_field_data_(); +} +pub type pc_str_t = pc_str; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pc_prod { + pub magic_: u32, + pub ver_: u32, + pub type_: u32, + pub size_: u32, + pub px_acc_: pc_pub_key_t, +} +#[test] +fn bindgen_test_layout_pc_prod() { + assert_eq!( + ::std::mem::size_of::(), + 48usize, + concat!("Size of: ", stringify!(pc_prod)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_prod)) + ); + fn test_field_magic_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_prod), + "::", + stringify!(magic_) + ) + ); + } + test_field_magic_(); + fn test_field_ver_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(pc_prod), + "::", + stringify!(ver_) + ) + ); + } + test_field_ver_(); + fn test_field_type_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(pc_prod), + "::", + stringify!(type_) + ) + ); + } + test_field_type_(); + fn test_field_size_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(pc_prod), + "::", + stringify!(size_) + ) + ); + } + test_field_size_(); + fn test_field_px_acc_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).px_acc_) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(pc_prod), + "::", + stringify!(px_acc_) + ) + ); + } + test_field_px_acc_(); +} +pub type pc_prod_t = pc_prod; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct pc_price_info { + pub price_: i64, + pub conf_: u64, + pub status_: u32, + pub corp_act_status_: u32, + pub pub_slot_: u64, +} +#[test] +fn bindgen_test_layout_pc_price_info() { + assert_eq!( + ::std::mem::size_of::(), + 32usize, + concat!("Size of: ", stringify!(pc_price_info)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_price_info)) + ); + fn test_field_price_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).price_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_price_info), + "::", + stringify!(price_) + ) + ); + } + test_field_price_(); + fn test_field_conf_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).conf_) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(pc_price_info), + "::", + stringify!(conf_) + ) + ); + } + test_field_conf_(); + fn test_field_status_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).status_) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(pc_price_info), + "::", + stringify!(status_) + ) + ); + } + test_field_status_(); + fn test_field_corp_act_status_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).corp_act_status_) as usize - ptr as usize + }, + 20usize, + concat!( + "Offset of field: ", + stringify!(pc_price_info), + "::", + stringify!(corp_act_status_) + ) + ); + } + test_field_corp_act_status_(); + fn test_field_pub_slot_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).pub_slot_) as usize - ptr as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(pc_price_info), + "::", + stringify!(pub_slot_) + ) + ); + } + test_field_pub_slot_(); +} +pub type pc_price_info_t = pc_price_info; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pc_price_comp { + pub pub_: pc_pub_key_t, + pub agg_: pc_price_info_t, + pub latest_: pc_price_info_t, +} +#[test] +fn bindgen_test_layout_pc_price_comp() { + assert_eq!( + ::std::mem::size_of::(), + 96usize, + concat!("Size of: ", stringify!(pc_price_comp)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_price_comp)) + ); + fn test_field_pub_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).pub_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_price_comp), + "::", + stringify!(pub_) + ) + ); + } + test_field_pub_(); + fn test_field_agg_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).agg_) as usize - ptr as usize + }, + 32usize, + concat!( + "Offset of field: ", + stringify!(pc_price_comp), + "::", + stringify!(agg_) + ) + ); + } + test_field_agg_(); + fn test_field_latest_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).latest_) as usize - ptr as usize + }, + 64usize, + concat!( + "Offset of field: ", + stringify!(pc_price_comp), + "::", + stringify!(latest_) + ) + ); + } + test_field_latest_(); +} +pub type pc_price_comp_t = pc_price_comp; +#[repr(C)] +#[derive(Debug, Copy, Clone)] +pub struct pc_ema { + pub val_: i64, + pub numer_: i64, + pub denom_: i64, +} +#[test] +fn bindgen_test_layout_pc_ema() { + assert_eq!( + ::std::mem::size_of::(), + 24usize, + concat!("Size of: ", stringify!(pc_ema)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_ema)) + ); + fn test_field_val_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).val_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_ema), + "::", + stringify!(val_) + ) + ); + } + test_field_val_(); + fn test_field_numer_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).numer_) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(pc_ema), + "::", + stringify!(numer_) + ) + ); + } + test_field_numer_(); + fn test_field_denom_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).denom_) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(pc_ema), + "::", + stringify!(denom_) + ) + ); + } + test_field_denom_(); +} +pub type pc_ema_t = pc_ema; +#[repr(C)] +#[derive(Copy, Clone)] +pub struct pc_price { + pub magic_: u32, + pub ver_: u32, + pub type_: u32, + pub size_: u32, + pub ptype_: u32, + pub expo_: i32, + pub num_: u32, + pub num_qt_: u32, + pub last_slot_: u64, + pub valid_slot_: u64, + pub twap_: pc_ema_t, + pub twac_: pc_ema_t, + pub timestamp_: i64, + pub min_pub_: u8, + pub drv2_: i8, + pub drv3_: i16, + pub drv4_: i32, + pub prod_: pc_pub_key_t, + pub next_: pc_pub_key_t, + pub prev_slot_: u64, + pub prev_price_: i64, + pub prev_conf_: u64, + pub prev_timestamp_: i64, + pub agg_: pc_price_info_t, + pub comp_: [pc_price_comp_t; 32usize], +} +#[test] +fn bindgen_test_layout_pc_price() { + assert_eq!( + ::std::mem::size_of::(), + 3312usize, + concat!("Size of: ", stringify!(pc_price)) + ); + assert_eq!( + ::std::mem::align_of::(), + 8usize, + concat!("Alignment of ", stringify!(pc_price)) + ); + fn test_field_magic_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize + }, + 0usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(magic_) + ) + ); + } + test_field_magic_(); + fn test_field_ver_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize + }, + 4usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(ver_) + ) + ); + } + test_field_ver_(); + fn test_field_type_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize + }, + 8usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(type_) + ) + ); + } + test_field_type_(); + fn test_field_size_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize + }, + 12usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(size_) + ) + ); + } + test_field_size_(); + fn test_field_ptype_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).ptype_) as usize - ptr as usize + }, + 16usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(ptype_) + ) + ); + } + test_field_ptype_(); + fn test_field_expo_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).expo_) as usize - ptr as usize + }, + 20usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(expo_) + ) + ); + } + test_field_expo_(); + fn test_field_num_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).num_) as usize - ptr as usize + }, + 24usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(num_) + ) + ); + } + test_field_num_(); + fn test_field_num_qt_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).num_qt_) as usize - ptr as usize + }, + 28usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(num_qt_) + ) + ); + } + test_field_num_qt_(); + fn test_field_last_slot_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).last_slot_) as usize - ptr as usize + }, + 32usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(last_slot_) + ) + ); + } + test_field_last_slot_(); + fn test_field_valid_slot_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).valid_slot_) as usize - ptr as usize + }, + 40usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(valid_slot_) + ) + ); + } + test_field_valid_slot_(); + fn test_field_twap_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).twap_) as usize - ptr as usize + }, + 48usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(twap_) + ) + ); + } + test_field_twap_(); + fn test_field_twac_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).twac_) as usize - ptr as usize + }, + 72usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(twac_) + ) + ); + } + test_field_twac_(); + fn test_field_timestamp_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).timestamp_) as usize - ptr as usize + }, + 96usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(timestamp_) + ) + ); + } + test_field_timestamp_(); + fn test_field_min_pub_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).min_pub_) as usize - ptr as usize + }, + 104usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(min_pub_) + ) + ); + } + test_field_min_pub_(); + fn test_field_drv2_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).drv2_) as usize - ptr as usize + }, + 105usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(drv2_) + ) + ); + } + test_field_drv2_(); + fn test_field_drv3_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).drv3_) as usize - ptr as usize + }, + 106usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(drv3_) + ) + ); + } + test_field_drv3_(); + fn test_field_drv4_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).drv4_) as usize - ptr as usize + }, + 108usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(drv4_) + ) + ); + } + test_field_drv4_(); + fn test_field_prod_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).prod_) as usize - ptr as usize + }, + 112usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(prod_) + ) + ); + } + test_field_prod_(); + fn test_field_next_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).next_) as usize - ptr as usize + }, + 144usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(next_) + ) + ); + } + test_field_next_(); + fn test_field_prev_slot_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).prev_slot_) as usize - ptr as usize + }, + 176usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(prev_slot_) + ) + ); + } + test_field_prev_slot_(); + fn test_field_prev_price_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).prev_price_) as usize - ptr as usize + }, + 184usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(prev_price_) + ) + ); + } + test_field_prev_price_(); + fn test_field_prev_conf_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).prev_conf_) as usize - ptr as usize + }, + 192usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(prev_conf_) + ) + ); + } + test_field_prev_conf_(); + fn test_field_prev_timestamp_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).prev_timestamp_) as usize - ptr as usize + }, + 200usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(prev_timestamp_) + ) + ); + } + test_field_prev_timestamp_(); + fn test_field_agg_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).agg_) as usize - ptr as usize + }, + 208usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(agg_) + ) + ); + } + test_field_agg_(); + fn test_field_comp_() { + assert_eq!( + unsafe { + let uninit = ::std::mem::MaybeUninit::::uninit(); + let ptr = uninit.as_ptr(); + ::std::ptr::addr_of!((*ptr).comp_) as usize - ptr as usize + }, + 240usize, + concat!( + "Offset of field: ", + stringify!(pc_price), + "::", + stringify!(comp_) + ) + ); + } + test_field_comp_(); +} +pub type pc_price_t = pc_price; +pub const PRICE_ACCOUNT_SIZE: u64 = 6176; +pub const PC_PRICE_T_COMP_OFFSET: size_t = 240; +pub const PC_MAP_TABLE_T_PROD_OFFSET: size_t = 56; +pub type __builtin_va_list = *mut ::std::os::raw::c_char; diff --git a/program/rust/src/permissions.rs b/program/rust/src/permissions.rs new file mode 100644 index 000000000..211188598 --- /dev/null +++ b/program/rust/src/permissions.rs @@ -0,0 +1,7 @@ +pub trait Authority { + pub fn can_do(command : OracleCommand) -> bool; +} + +impl Authority for MasterAuthority { + +} diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index 257874d60..3a616524d 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -25,7 +25,13 @@ impl Arbitrary for DataEvent { } } - +/// This is a generative test for the sma struct. quickcheck will generate a series of +/// vectors of DataEvents of different length. The generation is based on the arbitrary trait +/// above. +/// For each DataEvent : +/// - time_gap is a random number between 0 and u8::MAX (255) +/// - slot_gap is a random number between 1 and u8::MAX + 1 (256) +/// - price is a random i64 #[quickcheck] fn test_sma(input: Vec) -> bool { // No gaps, no skipped epochs From 486725c8979bd4a181508985a378005b8b6b6171 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 14:10:53 -0500 Subject: [PATCH 28/30] First epoch is invalid always --- program/rust/src/tests/test_sma.rs | 6 +++- .../src/tests/test_sma_epoch_transition.rs | 34 +++++++++---------- program/rust/src/tests/test_upd_sma.rs | 16 ++++----- program/rust/src/time_machine_types.rs | 2 +- 4 files changed, 31 insertions(+), 27 deletions(-) diff --git a/program/rust/src/tests/test_sma.rs b/program/rust/src/tests/test_sma.rs index 3a616524d..2019fd441 100644 --- a/program/rust/src/tests/test_sma.rs +++ b/program/rust/src/tests/test_sma.rs @@ -157,7 +157,7 @@ impl SmaTracker { .unwrap(); - let result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { + let mut result = data.iter().fold((0, 0, true), |x: (u64, i128, bool), y| { if !((left_bound > y.current_timestamp) || (right_bound <= y.previous_timestamp)) //Check interval intersection { @@ -170,6 +170,10 @@ impl SmaTracker { } return x; }); + + if epoch_number == 0 { + result.2 = false; + } return result; } } diff --git a/program/rust/src/tests/test_sma_epoch_transition.rs b/program/rust/src/tests/test_sma_epoch_transition.rs index 02c5b938f..fc022c61c 100644 --- a/program/rust/src/tests/test_sma_epoch_transition.rs +++ b/program/rust/src/tests/test_sma_epoch_transition.rs @@ -85,7 +85,7 @@ fn test_sma_epoch_transition() { ); assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); assert_eq!(price_data.time_machine.current_epoch_numerator, 0); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 0); for i in 0..NUM_BUCKETS_THIRTY_MIN { assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); @@ -118,7 +118,7 @@ fn test_sma_epoch_transition() { ); assert_eq!(price_data.time_machine.granularity, THIRTY_MINUTES); assert_eq!(price_data.time_machine.current_epoch_numerator, 42 / 2 * 2); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 2); for i in 0..NUM_BUCKETS_THIRTY_MIN { assert_eq!(price_data.time_machine.running_sum_of_price_averages[i], 0); @@ -167,7 +167,7 @@ fn test_sma_epoch_transition() { price_data.time_machine.running_sum_of_price_averages[0], ((42 + (80 + 42) / 2) / 3) ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 0); } // Same epoch, invalid slot gap @@ -211,7 +211,7 @@ fn test_sma_epoch_transition() { price_data.time_machine.running_sum_of_price_averages[0], ((42 + (80 + 42) / 2) / 3) ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 0); } // Next epoch, valid slot gap @@ -256,13 +256,13 @@ fn test_sma_epoch_transition() { price_data.time_machine.running_sum_of_price_averages[0], ((42 + (80 + 42) / 2) / 3) ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[1], price_data.time_machine.running_sum_of_price_averages[0] + 60 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 0); } // A big gap in time (more than 1 epoch) but not in slots, all skipped epochs are "valid" @@ -306,31 +306,31 @@ fn test_sma_epoch_transition() { price_data.time_machine.running_sum_of_price_averages[0], ((42 + (80 + 42) / 2) / 3) ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[1], price_data.time_machine.running_sum_of_price_averages[0] + 60 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[2], price_data.time_machine.running_sum_of_price_averages[1] + (60 * 28 + 1 * 41) / 29 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[2], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[2], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[3], price_data.time_machine.running_sum_of_price_averages[2] + 40 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[3], 2); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[3], 1); assert_eq!( price_data.time_machine.running_sum_of_price_averages[4], price_data.time_machine.running_sum_of_price_averages[3] + 40 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[4], 3); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[4], 2); } // Really big gap both in slots and epochs (the entire buffers gets rewritten) @@ -375,31 +375,31 @@ fn test_sma_epoch_transition() { price_data.time_machine.running_sum_of_price_averages[0], ((42 + (80 + 42) / 2) / 3) ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[0], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[1], price_data.time_machine.running_sum_of_price_averages[0] + 60 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[1], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[2], price_data.time_machine.running_sum_of_price_averages[1] + (60 * 28 + 1 * 41) / 29 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[2], 1); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[2], 0); assert_eq!( price_data.time_machine.running_sum_of_price_averages[3], price_data.time_machine.running_sum_of_price_averages[2] + 40 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[3], 2); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[3], 1); assert_eq!( price_data.time_machine.running_sum_of_price_averages[4], price_data.time_machine.running_sum_of_price_averages[3] + 40 ); - assert_eq!(price_data.time_machine.running_valid_epoch_counter[4], 3); + assert_eq!(price_data.time_machine.running_valid_epoch_counter[4], 2); } update_clock_slot(&mut clock_account, 101); @@ -441,7 +441,7 @@ fn test_sma_epoch_transition() { assert_eq!( price_data.time_machine.running_valid_epoch_counter [(i + 4) % NUM_BUCKETS_THIRTY_MIN], - 3 + 2 ); } } diff --git a/program/rust/src/tests/test_upd_sma.rs b/program/rust/src/tests/test_upd_sma.rs index 503d9f538..044d4b62f 100644 --- a/program/rust/src/tests/test_upd_sma.rs +++ b/program/rust/src/tests/test_upd_sma.rs @@ -90,7 +90,7 @@ fn test_upd_sma() { assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_UNKNOWN); assert_eq!(price_data.time_machine.current_epoch_numerator, 0); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 0); } @@ -125,7 +125,7 @@ fn test_upd_sma() { assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_UNKNOWN); assert_eq!(price_data.time_machine.current_epoch_numerator, 0); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 0); } @@ -159,7 +159,7 @@ fn test_upd_sma() { assert_eq!(price_data.price_data.agg_.status_, PC_STATUS_TRADING); assert_eq!(price_data.time_machine.current_epoch_numerator, 42 / 2 * 3); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 3); } @@ -195,7 +195,7 @@ fn test_upd_sma() { price_data.time_machine.current_epoch_numerator, 42 / 2 * 3 + (81 + 42) / 2 ); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 3 + 1); } @@ -231,7 +231,7 @@ fn test_upd_sma() { price_data.time_machine.current_epoch_numerator, 42 / 2 * 3 + (81 + 42) / 2 + 81 ); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 3 + 1 + 1); } @@ -269,7 +269,7 @@ fn test_upd_sma() { price_data.time_machine.current_epoch_numerator, 42 / 2 * 3 + (81 + 42) / 2 + 81 ); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!(price_data.time_machine.current_epoch_denominator, 3 + 1 + 1); } @@ -316,7 +316,7 @@ fn test_upd_sma() { price_data.time_machine.current_epoch_numerator, 42 / 2 * 3 + (81 + 42) / 2 + 81 + 81 ); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!( price_data.time_machine.current_epoch_denominator, 3 + 1 + 1 + 1 @@ -356,7 +356,7 @@ fn test_upd_sma() { price_data.time_machine.current_epoch_numerator, 42 / 2 * 3 + (81 + 42) / 2 + 81 + 81 ); - assert_eq!(price_data.time_machine.current_epoch_is_valid, true); + assert_eq!(price_data.time_machine.current_epoch_is_valid, false); assert_eq!( price_data.time_machine.current_epoch_denominator, 3 + 1 + 1 + 1 diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 9d5bfcf5e..f8b1c1314 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -98,7 +98,7 @@ impl SmaTracker { pub fn initialize(&mut self, granularity: i64, threshold: u64) { self.threshold = threshold; self.granularity = granularity; - self.current_epoch_is_valid = true; + self.current_epoch_is_valid = false; } pub fn add_datapoint(&mut self, datapoint: &DataPoint) -> Result<(), OracleError> { From fa6e697d9bd33f5e9f66d7fef4533058c1598e6a Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 14:12:41 -0500 Subject: [PATCH 29/30] Remove files --- program/rust/bindings2.rs | 2033 ------------------------------- program/rust/src/permissions.rs | 7 - 2 files changed, 2040 deletions(-) delete mode 100644 program/rust/bindings2.rs delete mode 100644 program/rust/src/permissions.rs diff --git a/program/rust/bindings2.rs b/program/rust/bindings2.rs deleted file mode 100644 index b8528538a..000000000 --- a/program/rust/bindings2.rs +++ /dev/null @@ -1,2033 +0,0 @@ -/* automatically generated by rust-bindgen 0.60.1 */ - -#[repr(C)] -#[derive(Default)] -pub struct __IncompleteArrayField(::std::marker::PhantomData, [T; 0]); -impl __IncompleteArrayField { - #[inline] - pub const fn new() -> Self { - __IncompleteArrayField(::std::marker::PhantomData, []) - } - #[inline] - pub fn as_ptr(&self) -> *const T { - self as *const _ as *const T - } - #[inline] - pub fn as_mut_ptr(&mut self) -> *mut T { - self as *mut _ as *mut T - } - #[inline] - pub unsafe fn as_slice(&self, len: usize) -> &[T] { - ::std::slice::from_raw_parts(self.as_ptr(), len) - } - #[inline] - pub unsafe fn as_mut_slice(&mut self, len: usize) -> &mut [T] { - ::std::slice::from_raw_parts_mut(self.as_mut_ptr(), len) - } -} -impl ::std::fmt::Debug for __IncompleteArrayField { - fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result { - fmt.write_str("__IncompleteArrayField") - } -} -pub const true_: u32 = 1; -pub const false_: u32 = 0; -pub const __bool_true_false_are_defined: u32 = 1; -pub const PYTH_ORACLE_UTIL_COMPAT_STDINT_STYLE: u32 = 0; -pub const __WORDSIZE: u32 = 64; -pub const __DARWIN_ONLY_64_BIT_INO_T: u32 = 1; -pub const __DARWIN_ONLY_UNIX_CONFORMANCE: u32 = 1; -pub const __DARWIN_ONLY_VERS_1050: u32 = 1; -pub const __DARWIN_UNIX03: u32 = 1; -pub const __DARWIN_64_BIT_INO_T: u32 = 1; -pub const __DARWIN_VERS_1050: u32 = 1; -pub const __DARWIN_NON_CANCELABLE: u32 = 0; -pub const __DARWIN_SUF_EXTSN: &[u8; 14usize] = b"$DARWIN_EXTSN\0"; -pub const __DARWIN_C_ANSI: u32 = 4096; -pub const __DARWIN_C_FULL: u32 = 900000; -pub const __DARWIN_C_LEVEL: u32 = 900000; -pub const __STDC_WANT_LIB_EXT1__: u32 = 1; -pub const __DARWIN_NO_LONG_LONG: u32 = 0; -pub const _DARWIN_FEATURE_64_BIT_INODE: u32 = 1; -pub const _DARWIN_FEATURE_ONLY_64_BIT_INODE: u32 = 1; -pub const _DARWIN_FEATURE_ONLY_VERS_1050: u32 = 1; -pub const _DARWIN_FEATURE_ONLY_UNIX_CONFORMANCE: u32 = 1; -pub const _DARWIN_FEATURE_UNIX_CONFORMANCE: u32 = 3; -pub const __has_ptrcheck: u32 = 0; -pub const __PTHREAD_SIZE__: u32 = 8176; -pub const __PTHREAD_ATTR_SIZE__: u32 = 56; -pub const __PTHREAD_MUTEXATTR_SIZE__: u32 = 8; -pub const __PTHREAD_MUTEX_SIZE__: u32 = 56; -pub const __PTHREAD_CONDATTR_SIZE__: u32 = 8; -pub const __PTHREAD_COND_SIZE__: u32 = 40; -pub const __PTHREAD_ONCE_SIZE__: u32 = 8; -pub const __PTHREAD_RWLOCK_SIZE__: u32 = 192; -pub const __PTHREAD_RWLOCKATTR_SIZE__: u32 = 16; -pub const INT8_MAX: u32 = 127; -pub const INT16_MAX: u32 = 32767; -pub const INT32_MAX: u32 = 2147483647; -pub const INT64_MAX: u64 = 9223372036854775807; -pub const INT8_MIN: i32 = -128; -pub const INT16_MIN: i32 = -32768; -pub const INT32_MIN: i32 = -2147483648; -pub const INT64_MIN: i64 = -9223372036854775808; -pub const UINT8_MAX: u32 = 255; -pub const UINT16_MAX: u32 = 65535; -pub const UINT32_MAX: u32 = 4294967295; -pub const UINT64_MAX: i32 = -1; -pub const INT_LEAST8_MIN: i32 = -128; -pub const INT_LEAST16_MIN: i32 = -32768; -pub const INT_LEAST32_MIN: i32 = -2147483648; -pub const INT_LEAST64_MIN: i64 = -9223372036854775808; -pub const INT_LEAST8_MAX: u32 = 127; -pub const INT_LEAST16_MAX: u32 = 32767; -pub const INT_LEAST32_MAX: u32 = 2147483647; -pub const INT_LEAST64_MAX: u64 = 9223372036854775807; -pub const UINT_LEAST8_MAX: u32 = 255; -pub const UINT_LEAST16_MAX: u32 = 65535; -pub const UINT_LEAST32_MAX: u32 = 4294967295; -pub const UINT_LEAST64_MAX: i32 = -1; -pub const INT_FAST8_MIN: i32 = -128; -pub const INT_FAST16_MIN: i32 = -32768; -pub const INT_FAST32_MIN: i32 = -2147483648; -pub const INT_FAST64_MIN: i64 = -9223372036854775808; -pub const INT_FAST8_MAX: u32 = 127; -pub const INT_FAST16_MAX: u32 = 32767; -pub const INT_FAST32_MAX: u32 = 2147483647; -pub const INT_FAST64_MAX: u64 = 9223372036854775807; -pub const UINT_FAST8_MAX: u32 = 255; -pub const UINT_FAST16_MAX: u32 = 65535; -pub const UINT_FAST32_MAX: u32 = 4294967295; -pub const UINT_FAST64_MAX: i32 = -1; -pub const INTPTR_MAX: u64 = 9223372036854775807; -pub const INTPTR_MIN: i64 = -9223372036854775808; -pub const UINTPTR_MAX: i32 = -1; -pub const SIZE_MAX: i32 = -1; -pub const RSIZE_MAX: i32 = -1; -pub const WINT_MIN: i32 = -2147483648; -pub const WINT_MAX: u32 = 2147483647; -pub const SIG_ATOMIC_MIN: i32 = -2147483648; -pub const SIG_ATOMIC_MAX: u32 = 2147483647; -pub const PC_MAGIC: u32 = 2712847316; -pub const PC_VERSION: u32 = 2; -pub const PC_MAX_SEND_LATENCY: u32 = 25; -pub const PC_PUBKEY_SIZE: u32 = 32; -pub const PC_MAP_TABLE_SIZE: u32 = 640; -pub const PC_COMP_SIZE: u32 = 32; -pub const PC_MAX_NUM_DECIMALS: u32 = 8; -pub const PC_PROD_ACC_SIZE: u32 = 512; -pub const PC_EXP_DECAY: i32 = -9; -pub const PC_MAX_CI_DIVISOR: u32 = 20; -pub const PC_HEAP_START: u64 = 12884901888; -pub const PC_PTYPE_UNKNOWN: u32 = 0; -pub const PC_PTYPE_PRICE: u32 = 1; -pub const PC_STATUS_UNKNOWN: u32 = 0; -pub const PC_STATUS_TRADING: u32 = 1; -pub const PC_STATUS_HALTED: u32 = 2; -pub const PC_STATUS_AUCTION: u32 = 3; -pub const PC_ACCTYPE_MAPPING: u32 = 1; -pub const PC_ACCTYPE_PRODUCT: u32 = 2; -pub const PC_ACCTYPE_PRICE: u32 = 3; -pub const PC_ACCTYPE_TEST: u32 = 4; -pub type size_t = ::std::os::raw::c_ulong; -pub type wchar_t = ::std::os::raw::c_int; -pub type max_align_t = f64; -pub type int_least8_t = i8; -pub type int_least16_t = i16; -pub type int_least32_t = i32; -pub type int_least64_t = i64; -pub type uint_least8_t = u8; -pub type uint_least16_t = u16; -pub type uint_least32_t = u32; -pub type uint_least64_t = u64; -pub type int_fast8_t = i8; -pub type int_fast16_t = i16; -pub type int_fast32_t = i32; -pub type int_fast64_t = i64; -pub type uint_fast8_t = u8; -pub type uint_fast16_t = u16; -pub type uint_fast32_t = u32; -pub type uint_fast64_t = u64; -pub type __int8_t = ::std::os::raw::c_schar; -pub type __uint8_t = ::std::os::raw::c_uchar; -pub type __int16_t = ::std::os::raw::c_short; -pub type __uint16_t = ::std::os::raw::c_ushort; -pub type __int32_t = ::std::os::raw::c_int; -pub type __uint32_t = ::std::os::raw::c_uint; -pub type __int64_t = ::std::os::raw::c_longlong; -pub type __uint64_t = ::std::os::raw::c_ulonglong; -pub type __darwin_intptr_t = ::std::os::raw::c_long; -pub type __darwin_natural_t = ::std::os::raw::c_uint; -pub type __darwin_ct_rune_t = ::std::os::raw::c_int; -#[repr(C)] -#[derive(Copy, Clone)] -pub union __mbstate_t { - pub __mbstate8: [::std::os::raw::c_char; 128usize], - pub _mbstateL: ::std::os::raw::c_longlong, -} -#[test] -fn bindgen_test_layout___mbstate_t() { - assert_eq!( - ::std::mem::size_of::<__mbstate_t>(), - 128usize, - concat!("Size of: ", stringify!(__mbstate_t)) - ); - assert_eq!( - ::std::mem::align_of::<__mbstate_t>(), - 8usize, - concat!("Alignment of ", stringify!(__mbstate_t)) - ); - fn test_field___mbstate8() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<__mbstate_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__mbstate8) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__mbstate_t), - "::", - stringify!(__mbstate8) - ) - ); - } - test_field___mbstate8(); - fn test_field__mbstateL() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<__mbstate_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr)._mbstateL) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__mbstate_t), - "::", - stringify!(_mbstateL) - ) - ); - } - test_field__mbstateL(); -} -pub type __darwin_mbstate_t = __mbstate_t; -pub type __darwin_ptrdiff_t = ::std::os::raw::c_long; -pub type __darwin_size_t = ::std::os::raw::c_ulong; -pub type __darwin_va_list = __builtin_va_list; -pub type __darwin_wchar_t = ::std::os::raw::c_int; -pub type __darwin_rune_t = __darwin_wchar_t; -pub type __darwin_wint_t = ::std::os::raw::c_int; -pub type __darwin_clock_t = ::std::os::raw::c_ulong; -pub type __darwin_socklen_t = __uint32_t; -pub type __darwin_ssize_t = ::std::os::raw::c_long; -pub type __darwin_time_t = ::std::os::raw::c_long; -pub type __darwin_blkcnt_t = __int64_t; -pub type __darwin_blksize_t = __int32_t; -pub type __darwin_dev_t = __int32_t; -pub type __darwin_fsblkcnt_t = ::std::os::raw::c_uint; -pub type __darwin_fsfilcnt_t = ::std::os::raw::c_uint; -pub type __darwin_gid_t = __uint32_t; -pub type __darwin_id_t = __uint32_t; -pub type __darwin_ino64_t = __uint64_t; -pub type __darwin_ino_t = __darwin_ino64_t; -pub type __darwin_mach_port_name_t = __darwin_natural_t; -pub type __darwin_mach_port_t = __darwin_mach_port_name_t; -pub type __darwin_mode_t = __uint16_t; -pub type __darwin_off_t = __int64_t; -pub type __darwin_pid_t = __int32_t; -pub type __darwin_sigset_t = __uint32_t; -pub type __darwin_suseconds_t = __int32_t; -pub type __darwin_uid_t = __uint32_t; -pub type __darwin_useconds_t = __uint32_t; -pub type __darwin_uuid_t = [::std::os::raw::c_uchar; 16usize]; -pub type __darwin_uuid_string_t = [::std::os::raw::c_char; 37usize]; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct __darwin_pthread_handler_rec { - pub __routine: ::std::option::Option, - pub __arg: *mut ::std::os::raw::c_void, - pub __next: *mut __darwin_pthread_handler_rec, -} -#[test] -fn bindgen_test_layout___darwin_pthread_handler_rec() { - assert_eq!( - ::std::mem::size_of::<__darwin_pthread_handler_rec>(), - 24usize, - concat!("Size of: ", stringify!(__darwin_pthread_handler_rec)) - ); - assert_eq!( - ::std::mem::align_of::<__darwin_pthread_handler_rec>(), - 8usize, - concat!("Alignment of ", stringify!(__darwin_pthread_handler_rec)) - ); - fn test_field___routine() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<__darwin_pthread_handler_rec>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__routine) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(__darwin_pthread_handler_rec), - "::", - stringify!(__routine) - ) - ); - } - test_field___routine(); - fn test_field___arg() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<__darwin_pthread_handler_rec>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__arg) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(__darwin_pthread_handler_rec), - "::", - stringify!(__arg) - ) - ); - } - test_field___arg(); - fn test_field___next() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<__darwin_pthread_handler_rec>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__next) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(__darwin_pthread_handler_rec), - "::", - stringify!(__next) - ) - ); - } - test_field___next(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_attr_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 56usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_attr_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_attr_t>(), - 64usize, - concat!("Size of: ", stringify!(_opaque_pthread_attr_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_attr_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_attr_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_attr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_attr_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_attr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_attr_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_cond_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 40usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_cond_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_cond_t>(), - 48usize, - concat!("Size of: ", stringify!(_opaque_pthread_cond_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_cond_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_cond_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_cond_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_cond_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_cond_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_cond_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_condattr_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 8usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_condattr_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_condattr_t>(), - 16usize, - concat!("Size of: ", stringify!(_opaque_pthread_condattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_condattr_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_condattr_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_condattr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_condattr_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_condattr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_condattr_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_mutex_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 56usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_mutex_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_mutex_t>(), - 64usize, - concat!("Size of: ", stringify!(_opaque_pthread_mutex_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_mutex_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_mutex_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutex_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_mutex_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutex_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_mutex_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_mutexattr_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 8usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_mutexattr_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_mutexattr_t>(), - 16usize, - concat!("Size of: ", stringify!(_opaque_pthread_mutexattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_mutexattr_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_mutexattr_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutexattr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_mutexattr_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_mutexattr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_mutexattr_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_once_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 8usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_once_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_once_t>(), - 16usize, - concat!("Size of: ", stringify!(_opaque_pthread_once_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_once_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_once_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_once_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_once_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_once_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_once_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_rwlock_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 192usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_rwlock_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_rwlock_t>(), - 200usize, - concat!("Size of: ", stringify!(_opaque_pthread_rwlock_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_rwlock_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_rwlock_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlock_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_rwlock_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlock_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_rwlock_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_rwlockattr_t { - pub __sig: ::std::os::raw::c_long, - pub __opaque: [::std::os::raw::c_char; 16usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_rwlockattr_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_rwlockattr_t>(), - 24usize, - concat!("Size of: ", stringify!(_opaque_pthread_rwlockattr_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_rwlockattr_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_rwlockattr_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlockattr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_rwlockattr_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_rwlockattr_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_rwlockattr_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct _opaque_pthread_t { - pub __sig: ::std::os::raw::c_long, - pub __cleanup_stack: *mut __darwin_pthread_handler_rec, - pub __opaque: [::std::os::raw::c_char; 8176usize], -} -#[test] -fn bindgen_test_layout__opaque_pthread_t() { - assert_eq!( - ::std::mem::size_of::<_opaque_pthread_t>(), - 8192usize, - concat!("Size of: ", stringify!(_opaque_pthread_t)) - ); - assert_eq!( - ::std::mem::align_of::<_opaque_pthread_t>(), - 8usize, - concat!("Alignment of ", stringify!(_opaque_pthread_t)) - ); - fn test_field___sig() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__sig) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_t), - "::", - stringify!(__sig) - ) - ); - } - test_field___sig(); - fn test_field___cleanup_stack() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__cleanup_stack) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_t), - "::", - stringify!(__cleanup_stack) - ) - ); - } - test_field___cleanup_stack(); - fn test_field___opaque() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::<_opaque_pthread_t>::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).__opaque) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(_opaque_pthread_t), - "::", - stringify!(__opaque) - ) - ); - } - test_field___opaque(); -} -pub type __darwin_pthread_attr_t = _opaque_pthread_attr_t; -pub type __darwin_pthread_cond_t = _opaque_pthread_cond_t; -pub type __darwin_pthread_condattr_t = _opaque_pthread_condattr_t; -pub type __darwin_pthread_key_t = ::std::os::raw::c_ulong; -pub type __darwin_pthread_mutex_t = _opaque_pthread_mutex_t; -pub type __darwin_pthread_mutexattr_t = _opaque_pthread_mutexattr_t; -pub type __darwin_pthread_once_t = _opaque_pthread_once_t; -pub type __darwin_pthread_rwlock_t = _opaque_pthread_rwlock_t; -pub type __darwin_pthread_rwlockattr_t = _opaque_pthread_rwlockattr_t; -pub type __darwin_pthread_t = *mut _opaque_pthread_t; -pub type u_int8_t = ::std::os::raw::c_uchar; -pub type u_int16_t = ::std::os::raw::c_ushort; -pub type u_int32_t = ::std::os::raw::c_uint; -pub type u_int64_t = ::std::os::raw::c_ulonglong; -pub type register_t = i64; -pub type user_addr_t = u_int64_t; -pub type user_size_t = u_int64_t; -pub type user_ssize_t = i64; -pub type user_long_t = i64; -pub type user_ulong_t = u_int64_t; -pub type user_time_t = i64; -pub type user_off_t = i64; -pub type syscall_arg_t = u_int64_t; -pub type intmax_t = ::std::os::raw::c_long; -pub type uintmax_t = ::std::os::raw::c_ulong; -pub const TIME_MACHINE_STRUCT_SIZE: u64 = 1864; -pub const EXTRA_PUBLISHER_SPACE: u64 = 1000; -extern "C" { - pub static sysvar_clock: [u64; 4usize]; -} -#[repr(C)] -#[derive(Copy, Clone)] -pub union pc_pub_key { - pub k1_: [u8; 32usize], - pub k8_: [u64; 4usize], -} -#[test] -fn bindgen_test_layout_pc_pub_key() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(pc_pub_key)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_pub_key)) - ); - fn test_field_k1_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).k1_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_pub_key), - "::", - stringify!(k1_) - ) - ); - } - test_field_k1_(); - fn test_field_k8_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).k8_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_pub_key), - "::", - stringify!(k8_) - ) - ); - } - test_field_k8_(); -} -pub type pc_pub_key_t = pc_pub_key; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct pc_acc { - pub magic_: u32, - pub ver_: u32, - pub type_: u32, - pub size_: u32, -} -#[test] -fn bindgen_test_layout_pc_acc() { - assert_eq!( - ::std::mem::size_of::(), - 16usize, - concat!("Size of: ", stringify!(pc_acc)) - ); - assert_eq!( - ::std::mem::align_of::(), - 4usize, - concat!("Alignment of ", stringify!(pc_acc)) - ); - fn test_field_magic_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_acc), - "::", - stringify!(magic_) - ) - ); - } - test_field_magic_(); - fn test_field_ver_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pc_acc), - "::", - stringify!(ver_) - ) - ); - } - test_field_ver_(); - fn test_field_type_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pc_acc), - "::", - stringify!(type_) - ) - ); - } - test_field_type_(); - fn test_field_size_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(pc_acc), - "::", - stringify!(size_) - ) - ); - } - test_field_size_(); -} -pub type pc_acc_t = pc_acc; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct pc_map_table { - pub magic_: u32, - pub ver_: u32, - pub type_: u32, - pub size_: u32, - pub num_: u32, - pub unused_: u32, - pub next_: pc_pub_key_t, - pub prod_: [pc_pub_key_t; 640usize], -} -#[test] -fn bindgen_test_layout_pc_map_table() { - assert_eq!( - ::std::mem::size_of::(), - 20536usize, - concat!("Size of: ", stringify!(pc_map_table)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_map_table)) - ); - fn test_field_magic_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(magic_) - ) - ); - } - test_field_magic_(); - fn test_field_ver_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(ver_) - ) - ); - } - test_field_ver_(); - fn test_field_type_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(type_) - ) - ); - } - test_field_type_(); - fn test_field_size_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(size_) - ) - ); - } - test_field_size_(); - fn test_field_num_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).num_) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(num_) - ) - ); - } - test_field_num_(); - fn test_field_unused_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).unused_) as usize - ptr as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(unused_) - ) - ); - } - test_field_unused_(); - fn test_field_next_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).next_) as usize - ptr as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(next_) - ) - ); - } - test_field_next_(); - fn test_field_prod_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).prod_) as usize - ptr as usize - }, - 56usize, - concat!( - "Offset of field: ", - stringify!(pc_map_table), - "::", - stringify!(prod_) - ) - ); - } - test_field_prod_(); -} -pub type pc_map_table_t = pc_map_table; -#[repr(C)] -#[derive(Debug)] -pub struct pc_str { - pub len_: u8, - pub data_: __IncompleteArrayField<::std::os::raw::c_char>, -} -#[test] -fn bindgen_test_layout_pc_str() { - assert_eq!( - ::std::mem::size_of::(), - 1usize, - concat!("Size of: ", stringify!(pc_str)) - ); - assert_eq!( - ::std::mem::align_of::(), - 1usize, - concat!("Alignment of ", stringify!(pc_str)) - ); - fn test_field_len_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).len_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_str), - "::", - stringify!(len_) - ) - ); - } - test_field_len_(); - fn test_field_data_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).data_) as usize - ptr as usize - }, - 1usize, - concat!( - "Offset of field: ", - stringify!(pc_str), - "::", - stringify!(data_) - ) - ); - } - test_field_data_(); -} -pub type pc_str_t = pc_str; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct pc_prod { - pub magic_: u32, - pub ver_: u32, - pub type_: u32, - pub size_: u32, - pub px_acc_: pc_pub_key_t, -} -#[test] -fn bindgen_test_layout_pc_prod() { - assert_eq!( - ::std::mem::size_of::(), - 48usize, - concat!("Size of: ", stringify!(pc_prod)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_prod)) - ); - fn test_field_magic_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_prod), - "::", - stringify!(magic_) - ) - ); - } - test_field_magic_(); - fn test_field_ver_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pc_prod), - "::", - stringify!(ver_) - ) - ); - } - test_field_ver_(); - fn test_field_type_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pc_prod), - "::", - stringify!(type_) - ) - ); - } - test_field_type_(); - fn test_field_size_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(pc_prod), - "::", - stringify!(size_) - ) - ); - } - test_field_size_(); - fn test_field_px_acc_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).px_acc_) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pc_prod), - "::", - stringify!(px_acc_) - ) - ); - } - test_field_px_acc_(); -} -pub type pc_prod_t = pc_prod; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct pc_price_info { - pub price_: i64, - pub conf_: u64, - pub status_: u32, - pub corp_act_status_: u32, - pub pub_slot_: u64, -} -#[test] -fn bindgen_test_layout_pc_price_info() { - assert_eq!( - ::std::mem::size_of::(), - 32usize, - concat!("Size of: ", stringify!(pc_price_info)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_price_info)) - ); - fn test_field_price_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).price_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_price_info), - "::", - stringify!(price_) - ) - ); - } - test_field_price_(); - fn test_field_conf_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).conf_) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pc_price_info), - "::", - stringify!(conf_) - ) - ); - } - test_field_conf_(); - fn test_field_status_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).status_) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pc_price_info), - "::", - stringify!(status_) - ) - ); - } - test_field_status_(); - fn test_field_corp_act_status_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).corp_act_status_) as usize - ptr as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(pc_price_info), - "::", - stringify!(corp_act_status_) - ) - ); - } - test_field_corp_act_status_(); - fn test_field_pub_slot_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).pub_slot_) as usize - ptr as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(pc_price_info), - "::", - stringify!(pub_slot_) - ) - ); - } - test_field_pub_slot_(); -} -pub type pc_price_info_t = pc_price_info; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct pc_price_comp { - pub pub_: pc_pub_key_t, - pub agg_: pc_price_info_t, - pub latest_: pc_price_info_t, -} -#[test] -fn bindgen_test_layout_pc_price_comp() { - assert_eq!( - ::std::mem::size_of::(), - 96usize, - concat!("Size of: ", stringify!(pc_price_comp)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_price_comp)) - ); - fn test_field_pub_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).pub_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_price_comp), - "::", - stringify!(pub_) - ) - ); - } - test_field_pub_(); - fn test_field_agg_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).agg_) as usize - ptr as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(pc_price_comp), - "::", - stringify!(agg_) - ) - ); - } - test_field_agg_(); - fn test_field_latest_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).latest_) as usize - ptr as usize - }, - 64usize, - concat!( - "Offset of field: ", - stringify!(pc_price_comp), - "::", - stringify!(latest_) - ) - ); - } - test_field_latest_(); -} -pub type pc_price_comp_t = pc_price_comp; -#[repr(C)] -#[derive(Debug, Copy, Clone)] -pub struct pc_ema { - pub val_: i64, - pub numer_: i64, - pub denom_: i64, -} -#[test] -fn bindgen_test_layout_pc_ema() { - assert_eq!( - ::std::mem::size_of::(), - 24usize, - concat!("Size of: ", stringify!(pc_ema)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_ema)) - ); - fn test_field_val_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).val_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_ema), - "::", - stringify!(val_) - ) - ); - } - test_field_val_(); - fn test_field_numer_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).numer_) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pc_ema), - "::", - stringify!(numer_) - ) - ); - } - test_field_numer_(); - fn test_field_denom_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).denom_) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pc_ema), - "::", - stringify!(denom_) - ) - ); - } - test_field_denom_(); -} -pub type pc_ema_t = pc_ema; -#[repr(C)] -#[derive(Copy, Clone)] -pub struct pc_price { - pub magic_: u32, - pub ver_: u32, - pub type_: u32, - pub size_: u32, - pub ptype_: u32, - pub expo_: i32, - pub num_: u32, - pub num_qt_: u32, - pub last_slot_: u64, - pub valid_slot_: u64, - pub twap_: pc_ema_t, - pub twac_: pc_ema_t, - pub timestamp_: i64, - pub min_pub_: u8, - pub drv2_: i8, - pub drv3_: i16, - pub drv4_: i32, - pub prod_: pc_pub_key_t, - pub next_: pc_pub_key_t, - pub prev_slot_: u64, - pub prev_price_: i64, - pub prev_conf_: u64, - pub prev_timestamp_: i64, - pub agg_: pc_price_info_t, - pub comp_: [pc_price_comp_t; 32usize], -} -#[test] -fn bindgen_test_layout_pc_price() { - assert_eq!( - ::std::mem::size_of::(), - 3312usize, - concat!("Size of: ", stringify!(pc_price)) - ); - assert_eq!( - ::std::mem::align_of::(), - 8usize, - concat!("Alignment of ", stringify!(pc_price)) - ); - fn test_field_magic_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).magic_) as usize - ptr as usize - }, - 0usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(magic_) - ) - ); - } - test_field_magic_(); - fn test_field_ver_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).ver_) as usize - ptr as usize - }, - 4usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(ver_) - ) - ); - } - test_field_ver_(); - fn test_field_type_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).type_) as usize - ptr as usize - }, - 8usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(type_) - ) - ); - } - test_field_type_(); - fn test_field_size_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).size_) as usize - ptr as usize - }, - 12usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(size_) - ) - ); - } - test_field_size_(); - fn test_field_ptype_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).ptype_) as usize - ptr as usize - }, - 16usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(ptype_) - ) - ); - } - test_field_ptype_(); - fn test_field_expo_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).expo_) as usize - ptr as usize - }, - 20usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(expo_) - ) - ); - } - test_field_expo_(); - fn test_field_num_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).num_) as usize - ptr as usize - }, - 24usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(num_) - ) - ); - } - test_field_num_(); - fn test_field_num_qt_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).num_qt_) as usize - ptr as usize - }, - 28usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(num_qt_) - ) - ); - } - test_field_num_qt_(); - fn test_field_last_slot_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).last_slot_) as usize - ptr as usize - }, - 32usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(last_slot_) - ) - ); - } - test_field_last_slot_(); - fn test_field_valid_slot_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).valid_slot_) as usize - ptr as usize - }, - 40usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(valid_slot_) - ) - ); - } - test_field_valid_slot_(); - fn test_field_twap_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).twap_) as usize - ptr as usize - }, - 48usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(twap_) - ) - ); - } - test_field_twap_(); - fn test_field_twac_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).twac_) as usize - ptr as usize - }, - 72usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(twac_) - ) - ); - } - test_field_twac_(); - fn test_field_timestamp_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).timestamp_) as usize - ptr as usize - }, - 96usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(timestamp_) - ) - ); - } - test_field_timestamp_(); - fn test_field_min_pub_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).min_pub_) as usize - ptr as usize - }, - 104usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(min_pub_) - ) - ); - } - test_field_min_pub_(); - fn test_field_drv2_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).drv2_) as usize - ptr as usize - }, - 105usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(drv2_) - ) - ); - } - test_field_drv2_(); - fn test_field_drv3_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).drv3_) as usize - ptr as usize - }, - 106usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(drv3_) - ) - ); - } - test_field_drv3_(); - fn test_field_drv4_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).drv4_) as usize - ptr as usize - }, - 108usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(drv4_) - ) - ); - } - test_field_drv4_(); - fn test_field_prod_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).prod_) as usize - ptr as usize - }, - 112usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(prod_) - ) - ); - } - test_field_prod_(); - fn test_field_next_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).next_) as usize - ptr as usize - }, - 144usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(next_) - ) - ); - } - test_field_next_(); - fn test_field_prev_slot_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).prev_slot_) as usize - ptr as usize - }, - 176usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(prev_slot_) - ) - ); - } - test_field_prev_slot_(); - fn test_field_prev_price_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).prev_price_) as usize - ptr as usize - }, - 184usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(prev_price_) - ) - ); - } - test_field_prev_price_(); - fn test_field_prev_conf_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).prev_conf_) as usize - ptr as usize - }, - 192usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(prev_conf_) - ) - ); - } - test_field_prev_conf_(); - fn test_field_prev_timestamp_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).prev_timestamp_) as usize - ptr as usize - }, - 200usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(prev_timestamp_) - ) - ); - } - test_field_prev_timestamp_(); - fn test_field_agg_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).agg_) as usize - ptr as usize - }, - 208usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(agg_) - ) - ); - } - test_field_agg_(); - fn test_field_comp_() { - assert_eq!( - unsafe { - let uninit = ::std::mem::MaybeUninit::::uninit(); - let ptr = uninit.as_ptr(); - ::std::ptr::addr_of!((*ptr).comp_) as usize - ptr as usize - }, - 240usize, - concat!( - "Offset of field: ", - stringify!(pc_price), - "::", - stringify!(comp_) - ) - ); - } - test_field_comp_(); -} -pub type pc_price_t = pc_price; -pub const PRICE_ACCOUNT_SIZE: u64 = 6176; -pub const PC_PRICE_T_COMP_OFFSET: size_t = 240; -pub const PC_MAP_TABLE_T_PROD_OFFSET: size_t = 56; -pub type __builtin_va_list = *mut ::std::os::raw::c_char; diff --git a/program/rust/src/permissions.rs b/program/rust/src/permissions.rs deleted file mode 100644 index 211188598..000000000 --- a/program/rust/src/permissions.rs +++ /dev/null @@ -1,7 +0,0 @@ -pub trait Authority { - pub fn can_do(command : OracleCommand) -> bool; -} - -impl Authority for MasterAuthority { - -} From f5301290f7da480ec9d7dca342fbc7daee0f9d36 Mon Sep 17 00:00:00 2001 From: Guillermo Bescos Alapont Date: Mon, 12 Sep 2022 14:19:37 -0500 Subject: [PATCH 30/30] Comment test flags --- program/rust/src/time_machine_types.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index f8b1c1314..a186cd1a6 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -39,6 +39,7 @@ pub struct DataPoint { impl PriceAccountWrapper { pub fn initialize_time_machine(&mut self) -> Result<(), OracleError> { + // This is only enabled in tests while in development #[cfg(test)] self.time_machine .initialize(THIRTY_MINUTES, PC_MAX_SEND_LATENCY.into()); @@ -46,6 +47,7 @@ impl PriceAccountWrapper { } pub fn add_price_to_time_machine(&mut self) -> Result<(), OracleError> { + // This is only enabled in tests while in development #[cfg(test)] self.time_machine.add_datapoint( &DataPoint{ previous_timestamp : self.price_data.prev_timestamp_,