From c86cbcb5d0ccea6d74a4faf2eccee6ae992fd4bb Mon Sep 17 00:00:00 2001 From: m30m Date: Mon, 12 Jun 2023 10:36:15 +0200 Subject: [PATCH 1/4] Use message structures defined in pythnet sdk Since the custom serialization implementations are solana specific and mainly for reducing the binary size, they are kept in this package via a custom trait. Deserialization functions were removed since they were not used and the default serde provided by pythnet sdk should work identically. Serialization tests are now repurposed to test our custom serialization and the general deserialization lead to the same original structure. --- Cargo.lock | 55 +++- program/rust/Cargo.toml | 2 + program/rust/src/accounts.rs | 4 +- program/rust/src/accounts/price.rs | 368 +++++------------------- program/rust/src/lib.rs | 3 - program/rust/src/processor/upd_price.rs | 12 +- program/rust/src/tests/test_message.rs | 90 +----- 7 files changed, 144 insertions(+), 390 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3b5053b2b..4f7a88af9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1177,6 +1177,15 @@ version = "2.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" +[[package]] +name = "fast-math" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2465292146cdfc2011350fe3b1c616ac83cf0faeedb33463ba1c332ed8948d66" +dependencies = [ + "ieee754", +] + [[package]] name = "fastrand" version = "1.9.0" @@ -1471,6 +1480,15 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "805026a5d0141ffc30abb3be3173848ad46a1b1664fe632428479619a3644d77" +[[package]] +name = "hex" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +dependencies = [ + "serde", +] + [[package]] name = "histogram" version = "0.6.9" @@ -1618,6 +1636,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "ieee754" +version = "0.2.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9007da9cacbd3e6343da136e98b0d2df013f553d35bdec8b518f07bea768e19c" + [[package]] name = "im" version = "15.1.0" @@ -2489,9 +2513,10 @@ dependencies = [ "bytemuck", "byteorder", "csv", - "hex", + "hex 0.3.2", "num-derive", "num-traits", + "pythnet-sdk", "quickcheck", "quickcheck_macros", "rand 0.8.5", @@ -2506,6 +2531,25 @@ dependencies = [ "tokio", ] +[[package]] +name = "pythnet-sdk" +version = "1.13.6" +source = "git+https://github.com/pyth-network/pyth-crosschain?rev=9f950c694be5e9e6996dca217c2c3e29aac1df48#9f950c694be5e9e6996dca217c2c3e29aac1df48" +dependencies = [ + "bincode", + "borsh", + "bytemuck", + "byteorder", + "fast-math", + "hex 0.4.3", + "quickcheck", + "rustc_version", + "serde", + "sha3 0.10.7", + "slow_primes", + "thiserror", +] + [[package]] name = "qstring" version = "0.7.2" @@ -3209,6 +3253,15 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slow_primes" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58267dd2fbaa6dceecba9e3e106d2d90a2b02497c0e8b01b8759beccf5113938" +dependencies = [ + "num", +] + [[package]] name = "smallvec" version = "1.10.0" diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index 6de448fb9..0541b4e69 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -17,6 +17,7 @@ num-traits = "0.2" byteorder = "1.4.3" serde = { version = "1.0", features = ["derive"], optional = true } strum = { version = "0.24.1", features = ["derive"], optional = true } +pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="9f950c694be5e9e6996dca217c2c3e29aac1df48"} [dev-dependencies] solana-program-test = "=1.13.3" @@ -28,6 +29,7 @@ rand = "0.8.5" quickcheck_macros = "1" bincode = "1.3.3" serde = { version = "1.0", features = ["derive"] } +pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="9f950c694be5e9e6996dca217c2c3e29aac1df48", features = ["quickcheck"]} serde_json = "1.0" test-generator = "0.3.1" csv = "1.1" diff --git a/program/rust/src/accounts.rs b/program/rust/src/accounts.rs index d8c449908..fdb9f7c37 100644 --- a/program/rust/src/accounts.rs +++ b/program/rust/src/accounts.rs @@ -52,15 +52,13 @@ pub use { mapping::MappingAccount, permission::PermissionAccount, price::{ - Message, PriceAccount, PriceAccountV2, PriceComponent, PriceCumulative, PriceEma, - PriceFeedMessage, PriceInfo, - TwapMessage, + PythOracleSerialize, }, product::{ read_pc_str_t, diff --git a/program/rust/src/accounts/price.rs b/program/rust/src/accounts/price.rs index 0c18131ee..c838e06da 100644 --- a/program/rust/src/accounts/price.rs +++ b/program/rust/src/accounts/price.rs @@ -17,18 +17,12 @@ use { Pod, Zeroable, }, - byteorder::{ - BigEndian, - ReadBytesExt, + pythnet_sdk::messages::{ + PriceFeedMessage, + TwapMessage, }, solana_program::pubkey::Pubkey, - std::{ - io::{ - Cursor, - Read, - }, - mem::size_of, - }, + std::mem::size_of, }; #[repr(C)] @@ -78,6 +72,28 @@ pub struct PriceAccount { pub comp_: [PriceComponent; PC_COMP_SIZE as usize], } +impl PriceAccount { + #[allow(dead_code)] + pub fn as_price_feed_message(&self, key: &Pubkey) -> PriceFeedMessage { + let (price, conf, publish_time) = if self.agg_.status_ == PC_STATUS_TRADING { + (self.agg_.price_, self.agg_.conf_, self.timestamp_) + } else { + (self.prev_price_, self.prev_conf_, self.prev_timestamp_) + }; + + PriceFeedMessage { + id: key.to_bytes(), + price, + conf, + exponent: self.exponent, + publish_time, + prev_publish_time: self.prev_timestamp_, + ema_price: self.twap_.val_, + ema_conf: self.twac_.val_ as u64, + } + } +} + /// We are currently out of space in our price accounts. We plan to resize them /// using the resize_price_account function. Until all the accounts have been resized, all instructions MUST work with either of the two versions. /// Operations may check the account size to determine whether the old or the new version has been passed. @@ -145,6 +161,26 @@ impl PriceAccountV2 { Err(OracleError::NeedsSuccesfulAggregation) } } + + #[allow(dead_code)] + pub fn as_twap_message(&self, key: &Pubkey) -> TwapMessage { + let publish_time = if self.agg_.status_ == PC_STATUS_TRADING { + self.timestamp_ + } else { + self.prev_timestamp_ + }; + + TwapMessage { + id: key.to_bytes(), + cumulative_price: self.price_cumulative.price, + cumulative_conf: self.price_cumulative.conf, + num_down_slots: self.price_cumulative.num_down_slots, + exponent: self.exponent, + publish_time, + prev_publish_time: self.prev_timestamp_, + publish_slot: self.last_slot_, + } + } } // This struct can't overflow since : @@ -216,146 +252,23 @@ impl PythAccount for PriceAccountV2 { const INITIAL_SIZE: u32 = size_of::() as u32; } -/// Message format for sending data to other chains via the accumulator program -/// When serialized, each message starts with a unique 1-byte discriminator, followed by the -/// serialized struct data in the definition(s) below. -/// -/// Messages are forward-compatible. You may add new fields to messages after all previously -/// defined fields. All code for parsing messages must ignore any extraneous bytes at the end of -/// the message (which could be fields that the code does not yet understand). -/// -/// The oracle is not using the Message enum due to the contract size limit and -/// some of the methods for PriceFeedMessage and TwapMessage are not used by the oracle -/// for the same reason. Rust compiler doesn't include the unused methods in the contract. -/// Once we start using the unused structs and methods, the contract size will increase. - -#[derive(Debug, Copy, Clone, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -#[cfg_attr( - feature = "strum", - derive(strum::EnumDiscriminants), - strum_discriminants(name(MessageType)), - strum_discriminants(vis(pub)), - strum_discriminants(derive( - Hash, - strum::EnumIter, - strum::EnumString, - strum::IntoStaticStr, - strum::ToString, - )), - cfg_attr( - feature = "serde", - strum_discriminants(derive(serde::Serialize, serde::Deserialize)) - ) -)] -pub enum Message { - PriceFeedMessage(PriceFeedMessage), - TwapMessage(TwapMessage), -} - -#[allow(dead_code)] -impl Message { - pub fn try_from_bytes(bytes: &[u8]) -> Result { - match bytes[0] { - PriceFeedMessage::DISCRIMINATOR => Ok(Self::PriceFeedMessage( - PriceFeedMessage::try_from_bytes(bytes)?, - )), - TwapMessage::DISCRIMINATOR => { - Ok(Self::TwapMessage(TwapMessage::try_from_bytes(bytes)?)) - } - _ => Err(OracleError::DeserializationError), - } - } - - pub fn to_bytes(self) -> Vec { - match self { - Self::PriceFeedMessage(msg) => msg.to_bytes().to_vec(), - Self::TwapMessage(msg) => msg.to_bytes().to_vec(), - } - } - - pub fn publish_time(&self) -> i64 { - match self { - Self::PriceFeedMessage(msg) => msg.publish_time, - Self::TwapMessage(msg) => msg.publish_time, - } - } - - pub fn id(&self) -> [u8; 32] { - match self { - Self::PriceFeedMessage(msg) => msg.id, - Self::TwapMessage(msg) => msg.id, - } - } -} - -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct PriceFeedMessage { - pub id: [u8; 32], - pub price: i64, - pub conf: u64, - pub exponent: i32, - /// The timestamp of this price update in seconds - pub publish_time: i64, - /// The timestamp of the previous price update. This field is intended to allow users to - /// identify the single unique price update for any moment in time: - /// for any time t, the unique update is the one such that prev_publish_time < t <= publish_time. - /// - /// Note that there may not be such an update while we are migrating to the new message-sending logic, - /// as some price updates on pythnet may not be sent to other chains (because the message-sending - /// logic may not have triggered). We can solve this problem by making the message-sending mandatory - /// (which we can do once publishers have migrated over). - /// - /// Additionally, this field may be equal to publish_time if the message is sent on a slot where - /// where the aggregation was unsuccesful. This problem will go away once all publishers have - /// migrated over to a recent version of pyth-agent. - pub prev_publish_time: i64, - pub ema_price: i64, - pub ema_conf: u64, +pub trait PythOracleSerialize { + fn to_bytes(self) -> Vec; } -#[allow(dead_code)] -impl PriceFeedMessage { - // The size of the serialized message. Note that this is not the same as the size of the struct - // (because of the discriminator & struct padding/alignment). - pub const MESSAGE_SIZE: usize = 1 + 32 + 8 + 8 + 4 + 8 + 8 + 8 + 8; - pub const DISCRIMINATOR: u8 = 0; - - pub fn from_price_account(key: &Pubkey, account: &PriceAccount) -> Self { - let (price, conf, publish_time) = if account.agg_.status_ == PC_STATUS_TRADING { - (account.agg_.price_, account.agg_.conf_, account.timestamp_) - } else { - ( - account.prev_price_, - account.prev_conf_, - account.prev_timestamp_, - ) - }; - - Self { - id: key.to_bytes(), - price, - conf, - exponent: account.exponent, - publish_time, - prev_publish_time: account.prev_timestamp_, - ema_price: account.twap_.val_, - ema_conf: account.twac_.val_ as u64, - } - } - - /// Serialize this message as an array of bytes (including the discriminator) - /// Note that it would be more idiomatic to return a `Vec`, but that approach adds - /// to the size of the compiled binary (which is already close to the size limit). +impl PythOracleSerialize for PriceFeedMessage { + /// Ideally, this structure should not be aware of the discrminator and the Message enum + /// should handle serializing the discriminator. However, this method is kept as is in order + /// to avoid any further increase in the program binary size since we are close to the limit. #[allow(unused_assignments)] - pub fn to_bytes(self) -> [u8; Self::MESSAGE_SIZE] { - let mut bytes = [0u8; Self::MESSAGE_SIZE]; + fn to_bytes(self) -> Vec { + const MESSAGE_SIZE: usize = 1 + 32 + 8 + 8 + 4 + 8 + 8 + 8 + 8; + const DISCRIMINATOR: u8 = 0; + let mut bytes = [0u8; MESSAGE_SIZE]; let mut i: usize = 0; - bytes[i..i + 1].clone_from_slice(&[Self::DISCRIMINATOR]); + bytes[i..i + 1].clone_from_slice(&[DISCRIMINATOR]); i += 1; bytes[i..i + 32].clone_from_slice(&self.id[..]); @@ -382,115 +295,23 @@ impl PriceFeedMessage { bytes[i..i + 8].clone_from_slice(&self.ema_conf.to_be_bytes()); i += 8; - bytes - } - - /// Try to deserialize a message from an array of bytes (including the discriminator). - /// This method is forward-compatible and allows the size to be larger than the - /// size of the struct. As a side-effect, it will ignore newer fields that are - /// not yet present in the struct. - pub fn try_from_bytes(bytes: &[u8]) -> Result { - let mut cursor = Cursor::new(bytes); - - let discriminator = cursor - .read_u8() - .map_err(|_| OracleError::DeserializationError)?; - if discriminator != 0 { - return Err(OracleError::DeserializationError); - } - - let mut id = [0u8; 32]; - cursor - .read_exact(&mut id) - .map_err(|_| OracleError::DeserializationError)?; - - let price = cursor - .read_i64::() - .map_err(|_| OracleError::DeserializationError)?; - let conf = cursor - .read_u64::() - .map_err(|_| OracleError::DeserializationError)?; - let exponent = cursor - .read_i32::() - .map_err(|_| OracleError::DeserializationError)?; - let publish_time = cursor - .read_i64::() - .map_err(|_| OracleError::DeserializationError)?; - let prev_publish_time = cursor - .read_i64::() - .map_err(|_| OracleError::DeserializationError)?; - let ema_price = cursor - .read_i64::() - .map_err(|_| OracleError::DeserializationError)?; - let ema_conf = cursor - .read_u64::() - .map_err(|_| OracleError::DeserializationError)?; - - - Ok(Self { - id, - price, - conf, - exponent, - publish_time, - prev_publish_time, - ema_price, - ema_conf, - }) + bytes.to_vec() } } -/// Message format for sending Twap data via the accumulator program -#[repr(C)] -#[derive(Debug, Copy, Clone, PartialEq)] -#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] -pub struct TwapMessage { - pub id: [u8; 32], - pub cumulative_price: i128, - pub cumulative_conf: u128, - pub num_down_slots: u64, - pub exponent: i32, - pub publish_time: i64, - pub prev_publish_time: i64, - pub publish_slot: u64, -} - -#[allow(dead_code)] -impl TwapMessage { - // The size of the serialized message. Note that this is not the same as the size of the struct - // (because of the discriminator & struct padding/alignment). - pub const MESSAGE_SIZE: usize = 1 + 32 + 16 + 16 + 8 + 4 + 8 + 8 + 8; - pub const DISCRIMINATOR: u8 = 1; - - pub fn from_price_account(key: &Pubkey, account: &PriceAccountV2) -> Self { - let publish_time = if account.agg_.status_ == PC_STATUS_TRADING { - account.timestamp_ - } else { - account.prev_timestamp_ - }; - - Self { - id: key.to_bytes(), - cumulative_price: account.price_cumulative.price, - cumulative_conf: account.price_cumulative.conf, - num_down_slots: account.price_cumulative.num_down_slots, - exponent: account.exponent, - publish_time, - prev_publish_time: account.prev_timestamp_, - publish_slot: account.last_slot_, - } - } - - /// Serialize this message as an array of bytes (including the discriminator) - /// Note that it would be more idiomatic to return a `Vec`, but that approach adds - /// to the size of the compiled binary (which is already close to the size limit). +impl PythOracleSerialize for TwapMessage { + /// Ideally, this structure should not be aware of the discrminator and the Message enum + /// should handle serializing the discriminator. However, this method is kept as is in order + /// to avoid any further increase in the program binary size since we are close to the limit. #[allow(unused_assignments)] - pub fn to_bytes(self) -> [u8; Self::MESSAGE_SIZE] { - let mut bytes = [0u8; Self::MESSAGE_SIZE]; + fn to_bytes(self) -> Vec { + const MESSAGE_SIZE: usize = 1 + 32 + 16 + 16 + 8 + 4 + 8 + 8 + 8; + const DISCRIMINATOR: u8 = 1; + let mut bytes = [0u8; MESSAGE_SIZE]; let mut i: usize = 0; - bytes[i..i + 1].clone_from_slice(&[Self::DISCRIMINATOR]); + bytes[i..i + 1].clone_from_slice(&[DISCRIMINATOR]); i += 1; bytes[i..i + 32].clone_from_slice(&self.id[..]); @@ -517,59 +338,6 @@ impl TwapMessage { bytes[i..i + 8].clone_from_slice(&self.publish_slot.to_be_bytes()); i += 8; - bytes - } - - /// Try to deserialize a message from an array of bytes (including the discriminator). - /// This method is forward-compatible and allows the size to be larger than the - /// size of the struct. As a side-effect, it will ignore newer fields that are - /// not yet present in the struct. - pub fn try_from_bytes(bytes: &[u8]) -> Result { - let mut cursor = Cursor::new(bytes); - - let discriminator = cursor - .read_u8() - .map_err(|_| OracleError::DeserializationError)?; - if discriminator != 1 { - return Err(OracleError::DeserializationError); - } - - let mut id = [0u8; 32]; - cursor - .read_exact(&mut id) - .map_err(|_| OracleError::DeserializationError)?; - - let cumulative_price = cursor - .read_i128::() - .map_err(|_| OracleError::DeserializationError)?; - let cumulative_conf = cursor - .read_u128::() - .map_err(|_| OracleError::DeserializationError)?; - let num_down_slots = cursor - .read_u64::() - .map_err(|_| OracleError::DeserializationError)?; - let exponent = cursor - .read_i32::() - .map_err(|_| OracleError::DeserializationError)?; - let publish_time = cursor - .read_i64::() - .map_err(|_| OracleError::DeserializationError)?; - let prev_publish_time = cursor - .read_i64::() - .map_err(|_| OracleError::DeserializationError)?; - let publish_slot = cursor - .read_u64::() - .map_err(|_| OracleError::DeserializationError)?; - - Ok(Self { - id, - cumulative_price, - cumulative_conf, - num_down_slots, - exponent, - publish_time, - prev_publish_time, - publish_slot, - }) + bytes.to_vec() } } diff --git a/program/rust/src/lib.rs b/program/rust/src/lib.rs index c5a39805f..b0e3b8775 100644 --- a/program/rust/src/lib.rs +++ b/program/rust/src/lib.rs @@ -29,16 +29,13 @@ pub use accounts::MessageType; pub use accounts::{ AccountHeader, MappingAccount, - Message, PermissionAccount, PriceAccount, PriceComponent, PriceEma, - PriceFeedMessage, PriceInfo, ProductAccount, PythAccount, - TwapMessage, }; use { crate::error::OracleError, diff --git a/program/rust/src/processor/upd_price.rs b/program/rust/src/processor/upd_price.rs index 408576b5c..1c3580859 100644 --- a/program/rust/src/processor/upd_price.rs +++ b/program/rust/src/processor/upd_price.rs @@ -1,7 +1,7 @@ #[cfg(feature = "pythnet")] use { crate::accounts::{ - PriceFeedMessage, + PythOracleSerialize, UPD_PRICE_WRITE_SEED, }, solana_program::instruction::{ @@ -225,13 +225,9 @@ pub fn upd_price( is_writable: true, }, ]; - - let message = - vec![ - PriceFeedMessage::from_price_account(price_account.key, &price_data) - .to_bytes() - .to_vec(), - ]; + let message = vec![price_data + .as_price_feed_message(price_account.key) + .to_bytes()]; // anchor discriminator for "global:put_all" let discriminator: [u8; 8] = [212, 225, 193, 91, 151, 238, 20, 93]; diff --git a/program/rust/src/tests/test_message.rs b/program/rust/src/tests/test_message.rs index ffdc4705f..bd58c16d1 100644 --- a/program/rust/src/tests/test_message.rs +++ b/program/rust/src/tests/test_message.rs @@ -1,97 +1,37 @@ use { - crate::accounts::{ - Message, - PriceFeedMessage, - TwapMessage, + crate::accounts::PythOracleSerialize, + byteorder::BigEndian, + pythnet_sdk::{ + messages::{ + Message, + PriceFeedMessage, + TwapMessage, + }, + wire::from_slice, }, - quickcheck::Arbitrary, quickcheck_macros::quickcheck, }; -impl Arbitrary for PriceFeedMessage { - fn arbitrary(g: &mut quickcheck::Gen) -> Self { - let mut id = [0u8; 32]; - for item in &mut id { - *item = u8::arbitrary(g); - } - - let publish_time = i64::arbitrary(g); - - PriceFeedMessage { - id, - price: i64::arbitrary(g), - conf: u64::arbitrary(g), - exponent: i32::arbitrary(g), - publish_time, - prev_publish_time: publish_time.saturating_sub(i64::arbitrary(g)), - ema_price: i64::arbitrary(g), - ema_conf: u64::arbitrary(g), - } - } -} - #[quickcheck] fn test_price_feed_message_roundtrip(input: PriceFeedMessage) -> bool { - let reconstructed = PriceFeedMessage::try_from_bytes(&input.to_bytes()); + let reconstructed = from_slice::(&input.to_bytes()).unwrap(); println!("Failed test case:"); println!("{:?}", input); println!("{:?}", reconstructed); - - reconstructed == Ok(input) -} - - -impl Arbitrary for TwapMessage { - fn arbitrary(g: &mut quickcheck::Gen) -> Self { - let mut id = [0u8; 32]; - for item in &mut id { - *item = u8::arbitrary(g); - } - - let publish_time = i64::arbitrary(g); - - TwapMessage { - id, - cumulative_price: i128::arbitrary(g), - cumulative_conf: u128::arbitrary(g), - num_down_slots: u64::arbitrary(g), - exponent: i32::arbitrary(g), - publish_time, - prev_publish_time: publish_time.saturating_sub(i64::arbitrary(g)), - publish_slot: u64::arbitrary(g), - } + match reconstructed { + Message::PriceFeedMessage(reconstructed) => reconstructed == input, + _ => false, } } #[quickcheck] fn test_twap_message_roundtrip(input: TwapMessage) -> bool { - let reconstructed = TwapMessage::try_from_bytes(&input.to_bytes()); - - println!("Failed test case:"); - println!("{:?}", input); - println!("{:?}", reconstructed); - - reconstructed == Ok(input) -} - - -impl Arbitrary for Message { - fn arbitrary(g: &mut quickcheck::Gen) -> Self { - match u8::arbitrary(g) % 2 { - 0 => Message::PriceFeedMessage(Arbitrary::arbitrary(g)), - _ => Message::TwapMessage(Arbitrary::arbitrary(g)), - } - } -} - -#[quickcheck] -fn test_message_roundtrip(input: Message) -> bool { - let reconstructed = Message::try_from_bytes(&input.to_bytes()); + let reconstructed = from_slice::(&input.to_bytes()).unwrap(); println!("Failed test case:"); println!("{:?}", input); println!("{:?}", reconstructed); - reconstructed == Ok(input) + reconstructed == input } From 349d2c656b51e594e37cc7d7efcf001947be4b2f Mon Sep 17 00:00:00 2001 From: m30m Date: Mon, 12 Jun 2023 12:25:40 +0200 Subject: [PATCH 2/4] Update pyth-crosschain version and fix twap test --- Cargo.lock | 2 +- program/rust/Cargo.toml | 4 ++-- program/rust/src/tests/test_message.rs | 7 +++++-- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 4f7a88af9..e538868e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2534,7 +2534,7 @@ dependencies = [ [[package]] name = "pythnet-sdk" version = "1.13.6" -source = "git+https://github.com/pyth-network/pyth-crosschain?rev=9f950c694be5e9e6996dca217c2c3e29aac1df48#9f950c694be5e9e6996dca217c2c3e29aac1df48" +source = "git+https://github.com/pyth-network/pyth-crosschain?rev=e7a3a98ac957782075615936fd689aa9283dfb09#e7a3a98ac957782075615936fd689aa9283dfb09" dependencies = [ "bincode", "borsh", diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index 0541b4e69..9fe0cd034 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -17,7 +17,7 @@ num-traits = "0.2" byteorder = "1.4.3" serde = { version = "1.0", features = ["derive"], optional = true } strum = { version = "0.24.1", features = ["derive"], optional = true } -pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="9f950c694be5e9e6996dca217c2c3e29aac1df48"} +pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="e7a3a98ac957782075615936fd689aa9283dfb09"} [dev-dependencies] solana-program-test = "=1.13.3" @@ -29,7 +29,7 @@ rand = "0.8.5" quickcheck_macros = "1" bincode = "1.3.3" serde = { version = "1.0", features = ["derive"] } -pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="9f950c694be5e9e6996dca217c2c3e29aac1df48", features = ["quickcheck"]} +pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="e7a3a98ac957782075615936fd689aa9283dfb09", features = ["quickcheck"]} serde_json = "1.0" test-generator = "0.3.1" csv = "1.1" diff --git a/program/rust/src/tests/test_message.rs b/program/rust/src/tests/test_message.rs index bd58c16d1..9e09d98d0 100644 --- a/program/rust/src/tests/test_message.rs +++ b/program/rust/src/tests/test_message.rs @@ -27,11 +27,14 @@ fn test_price_feed_message_roundtrip(input: PriceFeedMessage) -> bool { #[quickcheck] fn test_twap_message_roundtrip(input: TwapMessage) -> bool { - let reconstructed = from_slice::(&input.to_bytes()).unwrap(); + let reconstructed = from_slice::(&input.to_bytes()).unwrap(); println!("Failed test case:"); println!("{:?}", input); println!("{:?}", reconstructed); - reconstructed == input + match reconstructed { + Message::TwapMessage(reconstructed) => reconstructed == input, + _ => false, + } } From 3befd7ad5eeffc6784ac19d121932d1b287de7ef Mon Sep 17 00:00:00 2001 From: m30m Date: Mon, 12 Jun 2023 16:05:02 +0200 Subject: [PATCH 3/4] Set resolver version to 2 to avoid some feature unifications The old resolver adds the quickcheck feature on the pythnet-sdk dependency for non-dev builds as well which leads to compile errors. --- Cargo.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/Cargo.toml b/Cargo.toml index d4ea0da0e..7d8bf6e99 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,4 +1,5 @@ [workspace] +resolver = "2" members = [ "program/rust" ] From ce44ef5e0962f4fdc6487086e9093c526229c44c Mon Sep 17 00:00:00 2001 From: m30m Date: Mon, 12 Jun 2023 19:41:29 +0200 Subject: [PATCH 4/4] Update revision for pythnet-sdk dependency to reflect the main branch commit --- Cargo.lock | 2 +- program/rust/Cargo.toml | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e538868e1..d52198b72 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2534,7 +2534,7 @@ dependencies = [ [[package]] name = "pythnet-sdk" version = "1.13.6" -source = "git+https://github.com/pyth-network/pyth-crosschain?rev=e7a3a98ac957782075615936fd689aa9283dfb09#e7a3a98ac957782075615936fd689aa9283dfb09" +source = "git+https://github.com/pyth-network/pyth-crosschain?rev=60144002053a93f424be70decd8a8ccb8d618d81#60144002053a93f424be70decd8a8ccb8d618d81" dependencies = [ "bincode", "borsh", diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index 9fe0cd034..bb8f075ca 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -17,7 +17,7 @@ num-traits = "0.2" byteorder = "1.4.3" serde = { version = "1.0", features = ["derive"], optional = true } strum = { version = "0.24.1", features = ["derive"], optional = true } -pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="e7a3a98ac957782075615936fd689aa9283dfb09"} +pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="60144002053a93f424be70decd8a8ccb8d618d81"} [dev-dependencies] solana-program-test = "=1.13.3" @@ -29,7 +29,7 @@ rand = "0.8.5" quickcheck_macros = "1" bincode = "1.3.3" serde = { version = "1.0", features = ["derive"] } -pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="e7a3a98ac957782075615936fd689aa9283dfb09", features = ["quickcheck"]} +pythnet-sdk = { git = "https://github.com/pyth-network/pyth-crosschain", rev="60144002053a93f424be70decd8a8ccb8d618d81", features = ["quickcheck"]} serde_json = "1.0" test-generator = "0.3.1" csv = "1.1"