Sdk: remove integer arithmetic (#15962)
* Fix timing * Fix secp256k1_instruction * Fix secp256k1 tests
This commit is contained in:
parent
04c99cf7ea
commit
5b2b824a53
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue