sq: optimize
This commit is contained in:
parent
834fae684b
commit
482c027d3b
|
@ -8,11 +8,10 @@ use crate::cuda_runtime::PinnedVec;
|
||||||
use crate::packet::{Packet, Packets};
|
use crate::packet::{Packet, Packets};
|
||||||
use crate::perf_libs;
|
use crate::perf_libs;
|
||||||
use crate::recycler::Recycler;
|
use crate::recycler::Recycler;
|
||||||
use bincode::serialized_size;
|
|
||||||
use rayon::ThreadPool;
|
use rayon::ThreadPool;
|
||||||
use solana_metrics::inc_new_counter_debug;
|
use solana_metrics::inc_new_counter_debug;
|
||||||
use solana_rayon_threadlimit::get_thread_count;
|
use solana_rayon_threadlimit::get_thread_count;
|
||||||
use solana_sdk::message::MessageHeader;
|
use solana_sdk::message::MESSAGE_HEADER_LENGTH;
|
||||||
use solana_sdk::pubkey::Pubkey;
|
use solana_sdk::pubkey::Pubkey;
|
||||||
use solana_sdk::short_vec::decode_len;
|
use solana_sdk::short_vec::decode_len;
|
||||||
use solana_sdk::signature::Signature;
|
use solana_sdk::signature::Signature;
|
||||||
|
@ -75,6 +74,12 @@ impl std::convert::From<std::boxed::Box<bincode::ErrorKind>> for PacketError {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl std::convert::From<std::num::TryFromIntError> for PacketError {
|
||||||
|
fn from(_e: std::num::TryFromIntError) -> Self {
|
||||||
|
Self::InvalidLen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
if let Some(api) = perf_libs::api() {
|
if let Some(api) = perf_libs::api() {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -147,17 +152,14 @@ pub fn batch_size(batches: &[Packets]) -> usize {
|
||||||
// internal function to be unit-tested; should be used only by get_packet_offsets
|
// internal function to be unit-tested; should be used only by get_packet_offsets
|
||||||
fn do_get_packet_offsets(
|
fn do_get_packet_offsets(
|
||||||
packet: &Packet,
|
packet: &Packet,
|
||||||
current_offset: u32,
|
current_offset: usize,
|
||||||
) -> Result<PacketOffsets, PacketError> {
|
) -> Result<PacketOffsets, PacketError> {
|
||||||
let message_header_size = serialized_size(&MessageHeader::default()).unwrap() as usize;
|
|
||||||
// should have at least 1 signature, sig lengths and the message header
|
// should have at least 1 signature, sig lengths and the message header
|
||||||
let min_packet_size = 1usize
|
let _ = 1usize
|
||||||
.checked_add(size_of::<Signature>())
|
.checked_add(size_of::<Signature>())
|
||||||
.and_then(|v| v.checked_add(message_header_size))
|
.and_then(|v| v.checked_add(MESSAGE_HEADER_LENGTH))
|
||||||
|
.filter(|v| *v <= packet.meta.size)
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
if min_packet_size > packet.meta.size {
|
|
||||||
return Err(PacketError::InvalidLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// read the length of Transaction.signatures (serialized with short_vec)
|
// read the length of Transaction.signatures (serialized with short_vec)
|
||||||
let (sig_len_untrusted, sig_size) =
|
let (sig_len_untrusted, sig_size) =
|
||||||
|
@ -170,76 +172,69 @@ fn do_get_packet_offsets(
|
||||||
.and_then(|v| v.checked_add(sig_size))
|
.and_then(|v| v.checked_add(sig_size))
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
|
|
||||||
|
let msg_start_offset_plus_one = msg_start_offset
|
||||||
|
.checked_add(1)
|
||||||
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
|
|
||||||
// Packet should have data at least for signatures, MessageHeader, 1 byte for Message.account_keys.len
|
// Packet should have data at least for signatures, MessageHeader, 1 byte for Message.account_keys.len
|
||||||
let min_message_end_offset = msg_start_offset
|
let _ = msg_start_offset_plus_one
|
||||||
.checked_add(message_header_size)
|
.checked_add(MESSAGE_HEADER_LENGTH)
|
||||||
.and_then(|v| v.checked_add(1))
|
.filter(|v| *v <= packet.meta.size)
|
||||||
.ok_or(PacketError::InvalidSignatureLen)?;
|
.ok_or(PacketError::InvalidSignatureLen)?;
|
||||||
if min_message_end_offset > packet.meta.size {
|
|
||||||
return Err(PacketError::InvalidSignatureLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
// read MessageHeader.num_required_signatures (serialized with u8)
|
// read MessageHeader.num_required_signatures (serialized with u8)
|
||||||
let sig_len_maybe_trusted = packet.data[msg_start_offset] as usize;
|
let sig_len_maybe_trusted = packet.data[msg_start_offset];
|
||||||
|
|
||||||
let message_account_keys_len_offset = msg_start_offset
|
let message_account_keys_len_offset = msg_start_offset
|
||||||
.checked_add(message_header_size)
|
.checked_add(MESSAGE_HEADER_LENGTH)
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
|
|
||||||
// This reads and compares the MessageHeader num_required_signatures and
|
// This reads and compares the MessageHeader num_required_signatures and
|
||||||
// num_readonly_signed_accounts bytes. If num_required_signatures is not larger than
|
// num_readonly_signed_accounts bytes. If num_required_signatures is not larger than
|
||||||
// num_readonly_signed_accounts, the first account is not debitable, and cannot be charged
|
// num_readonly_signed_accounts, the first account is not debitable, and cannot be charged
|
||||||
// required transaction fees.
|
// required transaction fees.
|
||||||
let readonly_signer_offset = msg_start_offset
|
let readonly_signer_offset = msg_start_offset_plus_one;
|
||||||
.checked_add(1)
|
if sig_len_maybe_trusted <= packet.data[readonly_signer_offset] {
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
|
||||||
if packet.data[msg_start_offset] <= packet.data[readonly_signer_offset] {
|
|
||||||
return Err(PacketError::PayerNotWritable);
|
return Err(PacketError::PayerNotWritable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if usize::from(sig_len_maybe_trusted) != sig_len_untrusted {
|
||||||
|
return Err(PacketError::MismatchSignatureLen);
|
||||||
|
}
|
||||||
|
|
||||||
// read the length of Message.account_keys (serialized with short_vec)
|
// read the length of Message.account_keys (serialized with short_vec)
|
||||||
let (pubkey_len, pubkey_len_size) = decode_len(&packet.data[message_account_keys_len_offset..])
|
let (pubkey_len, pubkey_len_size) = decode_len(&packet.data[message_account_keys_len_offset..])
|
||||||
.map_err(|_| PacketError::InvalidShortVec)?;
|
.map_err(|_| PacketError::InvalidShortVec)?;
|
||||||
|
|
||||||
let min_account_keys_end_offset = pubkey_len
|
let pubkey_start = message_account_keys_len_offset
|
||||||
.checked_mul(size_of::<Pubkey>())
|
.checked_add(pubkey_len_size)
|
||||||
.and_then(|v| v.checked_add(message_account_keys_len_offset))
|
|
||||||
.and_then(|v| v.checked_add(pubkey_len_size))
|
|
||||||
.ok_or(PacketError::InvalidPubkeyLen)?;
|
.ok_or(PacketError::InvalidPubkeyLen)?;
|
||||||
if min_account_keys_end_offset > packet.meta.size {
|
|
||||||
return Err(PacketError::InvalidPubkeyLen);
|
|
||||||
}
|
|
||||||
|
|
||||||
let sig_start = usize::try_from(current_offset)
|
let _ = pubkey_len
|
||||||
.ok()
|
.checked_mul(size_of::<Pubkey>())
|
||||||
.and_then(|v| v.checked_add(sig_size))
|
.and_then(|v| v.checked_add(pubkey_start))
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
.filter(|v| *v <= packet.meta.size)
|
||||||
let msg_start = usize::try_from(current_offset)
|
.ok_or(PacketError::InvalidPubkeyLen)?;
|
||||||
.ok()
|
|
||||||
.and_then(|v| v.checked_add(msg_start_offset))
|
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
|
||||||
let pubkey_start = msg_start
|
|
||||||
.checked_add(message_header_size)
|
|
||||||
.and_then(|v| v.checked_add(pubkey_len_size))
|
|
||||||
.ok_or(PacketError::InvalidLen)?;
|
|
||||||
|
|
||||||
if sig_len_maybe_trusted != sig_len_untrusted {
|
let sig_start = current_offset
|
||||||
return Err(PacketError::MismatchSignatureLen);
|
.checked_add(sig_size)
|
||||||
}
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
|
let msg_start = current_offset
|
||||||
fn to_u32(value: usize) -> Result<u32, PacketError> {
|
.checked_add(msg_start_offset)
|
||||||
u32::try_from(value).map_err(|_| PacketError::InvalidLen)
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
}
|
let pubkey_start = current_offset
|
||||||
|
.checked_add(pubkey_start)
|
||||||
|
.ok_or(PacketError::InvalidLen)?;
|
||||||
|
|
||||||
Ok(PacketOffsets::new(
|
Ok(PacketOffsets::new(
|
||||||
to_u32(sig_len_untrusted)?,
|
u32::try_from(sig_len_untrusted)?,
|
||||||
to_u32(sig_start)?,
|
u32::try_from(sig_start)?,
|
||||||
to_u32(msg_start)?,
|
u32::try_from(msg_start)?,
|
||||||
to_u32(pubkey_start)?,
|
u32::try_from(pubkey_start)?,
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_packet_offsets(packet: &Packet, current_offset: u32) -> PacketOffsets {
|
fn get_packet_offsets(packet: &Packet, current_offset: usize) -> PacketOffsets {
|
||||||
let unsanitized_packet_offsets = do_get_packet_offsets(packet, current_offset);
|
let unsanitized_packet_offsets = do_get_packet_offsets(packet, current_offset);
|
||||||
if let Ok(offsets) = unsanitized_packet_offsets {
|
if let Ok(offsets) = unsanitized_packet_offsets {
|
||||||
offsets
|
offsets
|
||||||
|
@ -259,13 +254,11 @@ pub fn generate_offsets(batches: &[Packets], recycler: &Recycler<TxOffset>) -> T
|
||||||
msg_start_offsets.set_pinnable();
|
msg_start_offsets.set_pinnable();
|
||||||
let mut msg_sizes: PinnedVec<_> = recycler.allocate().unwrap();
|
let mut msg_sizes: PinnedVec<_> = recycler.allocate().unwrap();
|
||||||
msg_sizes.set_pinnable();
|
msg_sizes.set_pinnable();
|
||||||
let mut current_packet: u32 = 0;
|
let mut current_offset: usize = 0;
|
||||||
let mut v_sig_lens = Vec::new();
|
let mut v_sig_lens = Vec::new();
|
||||||
batches.iter().for_each(|p| {
|
batches.iter().for_each(|p| {
|
||||||
let mut sig_lens = Vec::new();
|
let mut sig_lens = Vec::new();
|
||||||
p.packets.iter().for_each(|packet| {
|
p.packets.iter().for_each(|packet| {
|
||||||
let current_offset = current_packet.saturating_mul(size_of::<Packet>() as u32);
|
|
||||||
|
|
||||||
let packet_offsets = get_packet_offsets(packet, current_offset);
|
let packet_offsets = get_packet_offsets(packet, current_offset);
|
||||||
|
|
||||||
sig_lens.push(packet_offsets.sig_len);
|
sig_lens.push(packet_offsets.sig_len);
|
||||||
|
@ -274,6 +267,7 @@ pub fn generate_offsets(batches: &[Packets], recycler: &Recycler<TxOffset>) -> T
|
||||||
|
|
||||||
let mut pubkey_offset = packet_offsets.pubkey_start;
|
let mut pubkey_offset = packet_offsets.pubkey_start;
|
||||||
let mut sig_offset = packet_offsets.sig_start;
|
let mut sig_offset = packet_offsets.sig_start;
|
||||||
|
let msg_size = current_offset.saturating_add(packet.meta.size) as u32;
|
||||||
for _ in 0..packet_offsets.sig_len {
|
for _ in 0..packet_offsets.sig_len {
|
||||||
signature_offsets.push(sig_offset);
|
signature_offsets.push(sig_offset);
|
||||||
sig_offset = sig_offset.saturating_add(size_of::<Signature>() as u32);
|
sig_offset = sig_offset.saturating_add(size_of::<Signature>() as u32);
|
||||||
|
@ -283,12 +277,10 @@ pub fn generate_offsets(batches: &[Packets], recycler: &Recycler<TxOffset>) -> T
|
||||||
|
|
||||||
msg_start_offsets.push(packet_offsets.msg_start);
|
msg_start_offsets.push(packet_offsets.msg_start);
|
||||||
|
|
||||||
let msg_size = current_offset
|
let msg_size = msg_size.saturating_sub(packet_offsets.msg_start);
|
||||||
.saturating_add(packet.meta.size as u32)
|
|
||||||
.saturating_sub(packet_offsets.msg_start);
|
|
||||||
msg_sizes.push(msg_size);
|
msg_sizes.push(msg_size);
|
||||||
}
|
}
|
||||||
current_packet = current_packet.saturating_add(1);
|
current_offset = current_offset.saturating_add(size_of::<Packet>());
|
||||||
});
|
});
|
||||||
v_sig_lens.push(sig_lens);
|
v_sig_lens.push(sig_lens);
|
||||||
});
|
});
|
||||||
|
@ -689,7 +681,7 @@ mod tests {
|
||||||
// Just like get_packet_offsets, but not returning redundant information.
|
// Just like get_packet_offsets, but not returning redundant information.
|
||||||
fn get_packet_offsets_from_tx(tx: Transaction, current_offset: u32) -> PacketOffsets {
|
fn get_packet_offsets_from_tx(tx: Transaction, current_offset: u32) -> PacketOffsets {
|
||||||
let packet = sigverify::make_packet_from_transaction(tx);
|
let packet = sigverify::make_packet_from_transaction(tx);
|
||||||
let packet_offsets = sigverify::get_packet_offsets(&packet, current_offset);
|
let packet_offsets = sigverify::get_packet_offsets(&packet, current_offset as usize);
|
||||||
PacketOffsets::new(
|
PacketOffsets::new(
|
||||||
packet_offsets.sig_len,
|
packet_offsets.sig_len,
|
||||||
packet_offsets.sig_start - current_offset,
|
packet_offsets.sig_start - current_offset,
|
||||||
|
|
|
@ -142,6 +142,8 @@ fn get_program_ids(instructions: &[Instruction]) -> Vec<Pubkey> {
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub const MESSAGE_HEADER_LENGTH: usize = 3;
|
||||||
|
|
||||||
#[frozen_abi(digest = "BVC5RhetsNpheGipt5rUrkR6RDDUHtD5sCLK1UjymL4S")]
|
#[frozen_abi(digest = "BVC5RhetsNpheGipt5rUrkR6RDDUHtD5sCLK1UjymL4S")]
|
||||||
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, AbiExample)]
|
#[derive(Serialize, Deserialize, Default, Debug, PartialEq, Eq, Clone, AbiExample)]
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
|
@ -941,4 +943,12 @@ mod tests {
|
||||||
assert!(message.is_non_loader_key(&key1, 1));
|
assert!(message.is_non_loader_key(&key1, 1));
|
||||||
assert!(!message.is_non_loader_key(&loader2, 2));
|
assert!(!message.is_non_loader_key(&loader2, 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_message_header_len_constant() {
|
||||||
|
assert_eq!(
|
||||||
|
bincode::serialized_size(&MessageHeader::default()).unwrap() as usize,
|
||||||
|
MESSAGE_HEADER_LENGTH
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue