Sdk: remove integer arithmetic (#15962)

* Fix timing

* Fix secp256k1_instruction

* Fix secp256k1 tests
This commit is contained in:
Tyera Eulberg 2021-03-17 19:33:50 -06:00 committed by GitHub
parent 04c99cf7ea
commit 5b2b824a53
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 22 deletions

View File

@ -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(&eth_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..]);

View File

@ -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
}