Sdk: remove integer arithmetic (#15962)
* Fix timing * Fix secp256k1_instruction * Fix secp256k1 tests
This commit is contained in:
		| @@ -1,4 +1,3 @@ | ||||
| #![allow(clippy::integer_arithmetic)] | ||||
| #![cfg(feature = "full")] | ||||
|  | ||||
| use crate::instruction::Instruction; | ||||
| @@ -16,6 +15,7 @@ pub enum Secp256k1Error { | ||||
| pub const HASHED_PUBKEY_SERIALIZED_SIZE: usize = 20; | ||||
| pub const SIGNATURE_SERIALIZED_SIZE: usize = 64; | ||||
| pub const SIGNATURE_OFFSETS_SERIALIZED_SIZE: usize = 11; | ||||
| pub const DATA_START: usize = SIGNATURE_OFFSETS_SERIALIZED_SIZE + 1; | ||||
|  | ||||
| #[derive(Default, Serialize, Deserialize, Debug)] | ||||
| pub struct SecpSignatureOffsets { | ||||
| @@ -45,22 +45,28 @@ pub fn new_secp256k1_instruction( | ||||
|     assert_eq!(signature_arr.len(), SIGNATURE_SERIALIZED_SIZE); | ||||
|  | ||||
|     let mut instruction_data = vec![]; | ||||
|     let data_start = 1 + SIGNATURE_OFFSETS_SERIALIZED_SIZE; | ||||
|     instruction_data.resize( | ||||
|         data_start + eth_pubkey.len() + signature_arr.len() + message_arr.len() + 1, | ||||
|         DATA_START | ||||
|             .saturating_add(eth_pubkey.len()) | ||||
|             .saturating_add(signature_arr.len()) | ||||
|             .saturating_add(message_arr.len()) | ||||
|             .saturating_add(1), | ||||
|         0, | ||||
|     ); | ||||
|     let eth_address_offset = data_start; | ||||
|     instruction_data[eth_address_offset..eth_address_offset + eth_pubkey.len()] | ||||
|     let eth_address_offset = DATA_START; | ||||
|     instruction_data[eth_address_offset..eth_address_offset.saturating_add(eth_pubkey.len())] | ||||
|         .copy_from_slice(ð_pubkey); | ||||
|  | ||||
|     let signature_offset = data_start + eth_pubkey.len(); | ||||
|     instruction_data[signature_offset..signature_offset + signature_arr.len()] | ||||
|     let signature_offset = DATA_START.saturating_add(eth_pubkey.len()); | ||||
|     instruction_data[signature_offset..signature_offset.saturating_add(signature_arr.len())] | ||||
|         .copy_from_slice(&signature_arr); | ||||
|  | ||||
|     instruction_data[signature_offset + signature_arr.len()] = recovery_id.serialize(); | ||||
|     instruction_data[signature_offset.saturating_add(signature_arr.len())] = | ||||
|         recovery_id.serialize(); | ||||
|  | ||||
|     let message_data_offset = signature_offset + signature_arr.len() + 1; | ||||
|     let message_data_offset = signature_offset | ||||
|         .saturating_add(signature_arr.len()) | ||||
|         .saturating_add(1); | ||||
|     instruction_data[message_data_offset..].copy_from_slice(message_arr); | ||||
|  | ||||
|     let num_signatures = 1; | ||||
| @@ -74,7 +80,7 @@ pub fn new_secp256k1_instruction( | ||||
|         message_data_size: message_arr.len() as u16, | ||||
|         message_instruction_index: 0, | ||||
|     }; | ||||
|     let writer = std::io::Cursor::new(&mut instruction_data[1..data_start]); | ||||
|     let writer = std::io::Cursor::new(&mut instruction_data[1..DATA_START]); | ||||
|     bincode::serialize_into(writer, &offsets).unwrap(); | ||||
|  | ||||
|     Instruction { | ||||
| @@ -99,13 +105,17 @@ pub fn verify_eth_addresses( | ||||
|         return Err(Secp256k1Error::InvalidInstructionDataSize); | ||||
|     } | ||||
|     let count = data[0] as usize; | ||||
|     let expected_data_size = 1 + count * SIGNATURE_OFFSETS_SERIALIZED_SIZE; | ||||
|     let expected_data_size = count | ||||
|         .saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE) | ||||
|         .saturating_add(1); | ||||
|     if data.len() < expected_data_size { | ||||
|         return Err(Secp256k1Error::InvalidInstructionDataSize); | ||||
|     } | ||||
|     for i in 0..count { | ||||
|         let start = 1 + i * SIGNATURE_OFFSETS_SERIALIZED_SIZE; | ||||
|         let end = start + SIGNATURE_OFFSETS_SERIALIZED_SIZE; | ||||
|         let start = i | ||||
|             .saturating_mul(SIGNATURE_OFFSETS_SERIALIZED_SIZE) | ||||
|             .saturating_add(1); | ||||
|         let end = start.saturating_add(SIGNATURE_OFFSETS_SERIALIZED_SIZE); | ||||
|  | ||||
|         let offsets: SecpSignatureOffsets = bincode::deserialize(&data[start..end]) | ||||
|             .map_err(|_| Secp256k1Error::InvalidSignature)?; | ||||
| @@ -117,7 +127,7 @@ pub fn verify_eth_addresses( | ||||
|         } | ||||
|         let signature_instruction = instruction_datas[signature_index]; | ||||
|         let sig_start = offsets.signature_offset as usize; | ||||
|         let sig_end = sig_start + SIGNATURE_SERIALIZED_SIZE; | ||||
|         let sig_end = sig_start.saturating_add(SIGNATURE_SERIALIZED_SIZE); | ||||
|         if sig_end >= signature_instruction.len() { | ||||
|             return Err(Secp256k1Error::InvalidSignature); | ||||
|         } | ||||
| @@ -175,7 +185,7 @@ fn get_data_slice<'a>( | ||||
|     } | ||||
|     let signature_instruction = &instruction_datas[signature_index]; | ||||
|     let start = offset_start as usize; | ||||
|     let end = start + size; | ||||
|     let end = start.saturating_add(size); | ||||
|     if end > signature_instruction.len() { | ||||
|         return Err(Secp256k1Error::InvalidSignature); | ||||
|     } | ||||
| @@ -188,7 +198,7 @@ pub mod test { | ||||
|     use super::*; | ||||
|  | ||||
|     fn test_case(num_signatures: u8, offsets: &SecpSignatureOffsets) -> Result<(), Secp256k1Error> { | ||||
|         let mut instruction_data = vec![0u8; 1 + SIGNATURE_OFFSETS_SERIALIZED_SIZE]; | ||||
|         let mut instruction_data = vec![0u8; DATA_START]; | ||||
|         instruction_data[0] = num_signatures; | ||||
|         let writer = std::io::Cursor::new(&mut instruction_data[1..]); | ||||
|         bincode::serialize_into(writer, &offsets).unwrap(); | ||||
| @@ -200,7 +210,7 @@ pub mod test { | ||||
|     fn test_invalid_offsets() { | ||||
|         solana_logger::setup(); | ||||
|  | ||||
|         let mut instruction_data = vec![0u8; 1 + SIGNATURE_OFFSETS_SERIALIZED_SIZE]; | ||||
|         let mut instruction_data = vec![0u8; DATA_START]; | ||||
|         let offsets = SecpSignatureOffsets::default(); | ||||
|         instruction_data[0] = 1; | ||||
|         let writer = std::io::Cursor::new(&mut instruction_data[1..]); | ||||
|   | ||||
| @@ -1,17 +1,26 @@ | ||||
| #![allow(clippy::integer_arithmetic)] | ||||
| //! The `timing` module provides std::time utility functions. | ||||
| use crate::unchecked_div_by_const; | ||||
| use std::time::{Duration, SystemTime, UNIX_EPOCH}; | ||||
|  | ||||
| pub fn duration_as_ns(d: &Duration) -> u64 { | ||||
|     d.as_secs() * 1_000_000_000 + u64::from(d.subsec_nanos()) | ||||
|     d.as_secs() | ||||
|         .saturating_mul(1_000_000_000) | ||||
|         .saturating_add(u64::from(d.subsec_nanos())) | ||||
| } | ||||
|  | ||||
| pub fn duration_as_us(d: &Duration) -> u64 { | ||||
|     (d.as_secs() * 1000 * 1000) + (u64::from(d.subsec_nanos()) / 1_000) | ||||
|     d.as_secs() | ||||
|         .saturating_mul(1_000_000) | ||||
|         .saturating_add(unchecked_div_by_const!(u64::from(d.subsec_nanos()), 1_000)) | ||||
| } | ||||
|  | ||||
| pub fn duration_as_ms(d: &Duration) -> u64 { | ||||
|     (d.as_secs() * 1000) + (u64::from(d.subsec_nanos()) / 1_000_000) | ||||
|     d.as_secs() | ||||
|         .saturating_mul(1000) | ||||
|         .saturating_add(unchecked_div_by_const!( | ||||
|             u64::from(d.subsec_nanos()), | ||||
|             1_000_000 | ||||
|         )) | ||||
| } | ||||
|  | ||||
| pub fn duration_as_s(d: &Duration) -> f32 { | ||||
| @@ -34,7 +43,7 @@ pub fn years_as_slots(years: f64, tick_duration: &Duration, ticks_per_slot: u64) | ||||
|     //  slots/year  is  seconds/year ... | ||||
|         SECONDS_PER_YEAR | ||||
|     //  * (ns/s)/(ns/tick) / ticks/slot = 1/s/1/tick = ticks/s | ||||
|         *(1_000_000_000.0 / duration_as_ns(tick_duration) as f64) | ||||
|         * (1_000_000_000.0 / duration_as_ns(tick_duration) as f64) | ||||
|     //  / ticks/slot | ||||
|         / ticks_per_slot as f64 | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user