diff --git a/.github/workflows/check-fomatting.yml b/.github/workflows/check-fomatting.yml index 7ae5af5aa..edf734f05 100644 --- a/.github/workflows/check-fomatting.yml +++ b/.github/workflows/check-fomatting.yml @@ -15,5 +15,5 @@ jobs: with: profile: minimal toolchain: nightly - components: rustfmt + components: rustfmt, clippy - uses: pre-commit/action@v2.0.3 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 88f24ce08..466e630e5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -14,3 +14,8 @@ repos: language: "rust" entry: cargo +nightly fmt pass_filenames: false + - id: cargo-clippy + name: Cargo clippy + language: "rust" + entry : cargo +nightly clippy -- -D warnings + pass_filenames : false diff --git a/program/rust/Cargo.toml b/program/rust/Cargo.toml index c3e881ac5..f3e4492bd 100644 --- a/program/rust/Cargo.toml +++ b/program/rust/Cargo.toml @@ -1,5 +1,3 @@ -cargo-features = ["edition2021"] - [package] name = "pyth-oracle" version = "2.13.1" diff --git a/program/rust/build_utils.rs b/program/rust/build_utils.rs index 6c3cfcd85..0be568b66 100644 --- a/program/rust/build_utils.rs +++ b/program/rust/build_utils.rs @@ -19,7 +19,7 @@ impl<'a> DeriveAdderParserCallback<'a> { } //add pairs of types and their desired traits pub fn register_traits(&mut self, type_name: &'a str, traits: Vec) { - self.types_to_traits.insert(&type_name, traits); + self.types_to_traits.insert(type_name, traits); } } diff --git a/program/rust/src/c_oracle_header.rs b/program/rust/src/c_oracle_header.rs index 5f2f8399f..55bd17be2 100644 --- a/program/rust/src/c_oracle_header.rs +++ b/program/rust/src/c_oracle_header.rs @@ -1,8 +1,6 @@ -#![allow(non_upper_case_globals)] #![allow(non_camel_case_types)] #![allow(non_snake_case)] //we do not use all the variables in oracle.h, so this helps with the warnings -#![allow(unused_variables)] #![allow(dead_code)] //All the custom trait imports should go here use borsh::{ diff --git a/program/rust/src/deserialize.rs b/program/rust/src/deserialize.rs index 12565e6f3..04fae794e 100644 --- a/program/rust/src/deserialize.rs +++ b/program/rust/src/deserialize.rs @@ -26,11 +26,11 @@ pub fn deserialize_single_field_from_account( i: usize, offset: Option, ) -> Result { - Ok(deserialize_single_field_from_buffer::( + deserialize_single_field_from_buffer::( &accounts .get(i) .ok_or(ProgramError::NotEnoughAccountKeys)? .try_borrow_data()?, offset, - )?) + ) } diff --git a/program/rust/src/lib.rs b/program/rust/src/lib.rs index 05938cc95..e397a0506 100644 --- a/program/rust/src/lib.rs +++ b/program/rust/src/lib.rs @@ -1,3 +1,9 @@ +#![deny(warnings)] +// Allow non upper case globals from C +#![allow(non_upper_case_globals)] +// Allow using the solana_program::entrypoint::deserialize function +#![allow(clippy::not_unsafe_ptr_arg_deref)] + mod c_oracle_header; mod deserialize; mod error; @@ -16,6 +22,7 @@ use crate::log::{ pre_log, }; use processor::process_instruction; + use solana_program::entrypoint::deserialize; use solana_program::program_error::ProgramError; use solana_program::{ @@ -48,8 +55,10 @@ extern "C" { } //make the C entrypoint a no-op when running cargo test +// Missing safety doc OK because this is just a no-op #[cfg(not(target_arch = "bpf"))] -pub extern "C" fn c_entrypoint(input: *mut u8) -> u64 { +#[allow(clippy::missing_safety_doc)] +pub unsafe extern "C" fn c_entrypoint(_input: *mut u8) -> u64 { 0 //SUCCESS value } @@ -68,9 +77,8 @@ pub fn c_entrypoint_wrapper(input: *mut u8) -> OracleResult { pub extern "C" fn entrypoint(input: *mut u8) -> u64 { let (program_id, accounts, instruction_data) = unsafe { deserialize(input) }; - match pre_log(&accounts, instruction_data) { - Err(error) => return error.into(), - _ => {} + if let Err(error) = pre_log(&accounts, instruction_data) { + return error.into(); } let c_ret_val = match process_instruction(program_id, &accounts, instruction_data, input) { @@ -78,16 +86,15 @@ pub extern "C" fn entrypoint(input: *mut u8) -> u64 { Ok(success_status) => success_status, }; - match post_log(c_ret_val, &accounts) { - Err(error) => return error.into(), - _ => {} + if let Err(error) = post_log(c_ret_val, &accounts) { + return error.into(); } if c_ret_val == SUCCESSFULLY_UPDATED_AGGREGATE { //0 is the SUCCESS value for solana - return 0; + 0 } else { - return c_ret_val; + c_ret_val } } diff --git a/program/rust/src/log.rs b/program/rust/src/log.rs index a9485b9b1..bc7e3dac5 100644 --- a/program/rust/src/log.rs +++ b/program/rust/src/log.rs @@ -16,7 +16,7 @@ pub fn pre_log(accounts: &[AccountInfo], instruction_data: &[u8]) -> ProgramResu msg!("Pyth oracle contract"); let instruction_header: cmd_hdr = - deserialize_single_field_from_buffer::(&instruction_data, None)?; + deserialize_single_field_from_buffer::(instruction_data, None)?; let instruction_id: u32 = instruction_header .cmd_ .try_into() diff --git a/program/rust/src/processor.rs b/program/rust/src/processor.rs index 6397674c3..79e831024 100644 --- a/program/rust/src/processor.rs +++ b/program/rust/src/processor.rs @@ -22,7 +22,7 @@ use solana_program::sysvar::slot_history::AccountInfo; ///dispatch to the right instruction in the oracle pub fn process_instruction( program_id: &Pubkey, - accounts: &Vec, + accounts: &[AccountInfo], instruction_data: &[u8], input: *mut u8, ) -> OracleResult { @@ -43,11 +43,9 @@ pub fn process_instruction( { command_t_e_cmd_upd_price | command_t_e_cmd_upd_price_no_fail_on_error - | command_t_e_cmd_agg_price => { - update_price(program_id, &accounts, &instruction_data, input) - } + | command_t_e_cmd_agg_price => update_price(program_id, accounts, instruction_data, input), command_t_e_cmd_upd_account_version => { - update_version(program_id, &accounts, &instruction_data) + update_version(program_id, accounts, instruction_data) } _ => c_entrypoint_wrapper(input), } diff --git a/program/rust/src/rust_oracle.rs b/program/rust/src/rust_oracle.rs index a17970e9f..141814409 100644 --- a/program/rust/src/rust_oracle.rs +++ b/program/rust/src/rust_oracle.rs @@ -5,9 +5,9 @@ use solana_program::sysvar::slot_history::AccountInfo; ///Calls the c oracle update_price, and updates the Time Machine if needed pub fn update_price( - program_id: &Pubkey, - accounts: &Vec, - instruction_data: &[u8], + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], input: *mut u8, ) -> OracleResult { //For now, we did not change the behavior of this. this is just to show the proposed structure @@ -18,10 +18,9 @@ pub fn update_price( /// with the current version /// updates the version number for all accounts, and resizes price accounts pub fn update_version( - program_id: &Pubkey, - accounts: &Vec, - instruction_data: &[u8], + _program_id: &Pubkey, + _accounts: &[AccountInfo], + _instruction_data: &[u8], ) -> OracleResult { panic!("Need to merge fix to pythd in order to implement this"); - Ok(0) //SUCCESS } diff --git a/program/rust/src/time_machine_types.rs b/program/rust/src/time_machine_types.rs index 935ab2de0..8298f6baa 100644 --- a/program/rust/src/time_machine_types.rs +++ b/program/rust/src/time_machine_types.rs @@ -1,5 +1,3 @@ -use super::c_oracle_header::TIME_MACHINE_STRUCT_SIZE; -use ::std::mem::size_of; #[derive(Debug, Clone)] #[repr(C)] /// this wraps multiple SMA and tick trackers, and includes all the state @@ -9,15 +7,21 @@ pub struct TimeMachineWrapper { place_holder: [u8; 1864], } -#[test] -///test that the size defined in C matches that -///defined in Rust -fn c_time_machine_size_is_correct() { - assert_eq!( +#[cfg(test)] +pub mod tests { + use crate::c_oracle_header::TIME_MACHINE_STRUCT_SIZE; + use crate::time_machine_types::TimeMachineWrapper; + 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.try_into().unwrap(), "expected TIME_MACHINE_STRUCT_SIZE ({}) in oracle.h to the same as the size of TimeMachineWrapper ({})", TIME_MACHINE_STRUCT_SIZE, size_of::() ); + } }