diff --git a/Cargo.lock b/Cargo.lock index 13971285787586..3e486143854263 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -393,7 +393,7 @@ dependencies = [ "solana-instruction", "solana-keypair", "solana-message", - "solana-packet", + "solana-perf", "solana-pubkey", "solana-sdk-ids", "solana-short-vec", @@ -8029,7 +8029,7 @@ dependencies = [ "solana-instruction", "solana-keypair", "solana-message", - "solana-packet", + "solana-perf", "solana-pubkey", "solana-sdk-ids", "solana-signer", @@ -8306,6 +8306,7 @@ dependencies = [ "solana-message", "solana-metrics", "solana-packet", + "solana-perf", "solana-pubkey", "solana-runtime-transaction", "solana-sdk-ids", @@ -9228,6 +9229,7 @@ dependencies = [ "solana-loader-v3-interface", "solana-loader-v4-interface", "solana-packet", + "solana-perf", "solana-program-runtime", "solana-pubkey", "solana-sbpf", @@ -11084,6 +11086,7 @@ dependencies = [ "solana-nonce", "solana-nonce-account", "solana-packet", + "solana-perf", "solana-program-runtime", "solana-pubkey", "solana-rent", diff --git a/compute-budget-instruction/Cargo.toml b/compute-budget-instruction/Cargo.toml index 993cf1de0918e6..e77d2e580047aa 100644 --- a/compute-budget-instruction/Cargo.toml +++ b/compute-budget-instruction/Cargo.toml @@ -28,7 +28,7 @@ solana-builtins-default-costs = { workspace = true } solana-compute-budget = { workspace = true } solana-compute-budget-interface = { workspace = true, features = ["borsh"] } solana-instruction = { workspace = true } -solana-packet = { workspace = true } +solana-perf = { workspace = true } solana-pubkey = { workspace = true } solana-sdk-ids = { workspace = true } solana-svm-transaction = { workspace = true } diff --git a/compute-budget-instruction/src/builtin_programs_filter.rs b/compute-budget-instruction/src/builtin_programs_filter.rs index ed2024719c8771..83f6d21b9e7a7f 100644 --- a/compute-budget-instruction/src/builtin_programs_filter.rs +++ b/compute-budget-instruction/src/builtin_programs_filter.rs @@ -2,12 +2,12 @@ use { solana_builtins_default_costs::{ get_builtin_migration_feature_index, BuiltinMigrationFeatureIndex, MAYBE_BUILTIN_KEY, }, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_pubkey::Pubkey, }; // The maximum number of pubkeys that a packet can contain. -pub(crate) const FILTER_SIZE: u8 = (PACKET_DATA_SIZE / core::mem::size_of::()) as u8; +pub(crate) const FILTER_SIZE: u8 = (QUIC_MAX_STREAM_SIZE / core::mem::size_of::()) as u8; #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) enum ProgramKind { diff --git a/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs b/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs index cfd69f81ee1799..522b3fbcefb096 100644 --- a/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs +++ b/core/src/banking_stage/transaction_scheduler/receive_and_buffer.rs @@ -575,15 +575,17 @@ mod tests { use { super::*, crate::banking_stage::tests::create_slow_genesis_config, + bytes::BytesMut, crossbeam_channel::{unbounded, Receiver}, solana_hash::Hash, solana_keypair::Keypair, solana_ledger::genesis_utils::GenesisConfigInfo, - solana_message::{ - v0, AccountMeta, AddressLookupTableAccount, Instruction, VersionedMessage, + solana_message::{v0, AddressLookupTableAccount, Instruction, VersionedMessage}, + solana_packet::Meta, + solana_perf::packet::{ + to_packet_batches, BytesPacket, BytesPacketBatch, PacketBatch, RecycledPacketBatch, + QUIC_MAX_STREAM_SIZE, }, - solana_packet::{Meta, PACKET_DATA_SIZE}, - solana_perf::packet::{to_packet_batches, Packet, PacketBatch, RecycledPacketBatch}, solana_pubkey::Pubkey, solana_signer::Signer, solana_system_interface::instruction as system_instruction, @@ -786,7 +788,7 @@ mod tests { setup_transaction_view_receive_and_buffer(receiver, bank_forks.clone()); let packet_batches = Arc::new(vec![PacketBatch::from(RecycledPacketBatch::new(vec![ - Packet::new([1u8; PACKET_DATA_SIZE], Meta::default()), + Packet::new([1u8; QUIC_MAX_STREAM_SIZE], Meta::default()), ]))]); sender.send(packet_batches).unwrap(); diff --git a/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs b/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs index fe2fbd8cb20fcb..f1e8657012c094 100644 --- a/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs +++ b/core/src/banking_stage/transaction_scheduler/transaction_state_container.rs @@ -1,5 +1,6 @@ #[cfg(feature = "dev-context-only-utils")] use qualifier_attr::qualifiers; +use solana_perf::packet::QUIC_MAX_STREAM_SIZE; use { super::{transaction_priority_id::TransactionPriorityId, transaction_state::TransactionState}, crate::banking_stage::scheduler_messages::TransactionId, @@ -7,7 +8,6 @@ use { itertools::MinMaxResult, min_max_heap::MinMaxHeap, slab::{Slab, VacantEntry}, - solana_packet::PACKET_DATA_SIZE, solana_runtime_transaction::{ runtime_transaction::RuntimeTransaction, transaction_with_meta::TransactionWithMeta, }, @@ -300,7 +300,7 @@ impl StateContainer for TransactionViewStateContainer { fn with_capacity(capacity: usize) -> Self { let inner = TransactionStateContainer::with_capacity(capacity); let bytes_buffer = (0..inner.id_to_transaction_state.capacity()) - .map(|_| Arc::new(Vec::with_capacity(PACKET_DATA_SIZE))) + .map(|_| Arc::new(Vec::with_capacity(QUIC_MAX_STREAM_SIZE))) .collect::>() .into_boxed_slice(); Self { diff --git a/core/src/repair/ancestor_hashes_service.rs b/core/src/repair/ancestor_hashes_service.rs index cf486a7856b2c4..e2ac05de9b166e 100644 --- a/core/src/repair/ancestor_hashes_service.rs +++ b/core/src/repair/ancestor_hashes_service.rs @@ -24,6 +24,7 @@ use { solana_gossip::{cluster_info::ClusterInfo, contact_info::Protocol, ping_pong::Pong}, solana_keypair::{signable::Signable, Keypair, Signer}, solana_ledger::blockstore::Blockstore, + solana_packet::PACKET_DATA_SIZE, solana_perf::{ packet::{deserialize_from_with_limit, PacketBatch, PacketFlags, PacketRef}, recycler::Recycler, @@ -388,7 +389,7 @@ impl AncestorHashesService { return None; }; let mut cursor = Cursor::new(packet_data); - let Ok(response) = deserialize_from_with_limit(&mut cursor) else { + let Ok(response) = deserialize_from_with_limit(&mut cursor, PACKET_DATA_SIZE) else { stats.invalid_packets += 1; return None; }; @@ -396,7 +397,7 @@ impl AncestorHashesService { match response { AncestorHashesResponse::Hashes(ref hashes) => { // deserialize trailing nonce - let Ok(nonce) = deserialize_from_with_limit(&mut cursor) else { + let Ok(nonce) = deserialize_from_with_limit(&mut cursor, PACKET_DATA_SIZE) else { stats.invalid_packets += 1; return None; }; diff --git a/core/src/repair/serve_repair.rs b/core/src/repair/serve_repair.rs index 5bab0261f0af5d..43aba68b735633 100644 --- a/core/src/repair/serve_repair.rs +++ b/core/src/repair/serve_repair.rs @@ -1509,7 +1509,7 @@ mod tests { let mut cursor = Cursor::new(&rsp[..]); let deserialized_request: RepairProtocol = - deserialize_from_with_limit(&mut cursor).unwrap(); + deserialize_from_with_limit(&mut cursor, PACKET_DATA_SIZE).unwrap(); assert_eq!(cursor.position(), rsp.len() as u64); if let RepairProtocol::Orphan { header, slot } = deserialized_request { assert_eq!(slot, 123); @@ -1548,7 +1548,7 @@ mod tests { .unwrap(); let mut cursor = Cursor::new(&request_bytes[..]); let deserialized_request: RepairProtocol = - deserialize_from_with_limit(&mut cursor).unwrap(); + deserialize_from_with_limit(&mut cursor, PACKET_DATA_SIZE).unwrap(); assert_eq!(cursor.position(), request_bytes.len() as u64); if let RepairProtocol::AncestorHashes { header, @@ -1599,7 +1599,7 @@ mod tests { let mut cursor = Cursor::new(&request_bytes[..]); let deserialized_request: RepairProtocol = - deserialize_from_with_limit(&mut cursor).unwrap(); + deserialize_from_with_limit(&mut cursor, PACKET_DATA_SIZE).unwrap(); assert_eq!(cursor.position(), request_bytes.len() as u64); if let RepairProtocol::WindowIndex { header, @@ -1633,7 +1633,7 @@ mod tests { let mut cursor = Cursor::new(&request_bytes[..]); let deserialized_request: RepairProtocol = - deserialize_from_with_limit(&mut cursor).unwrap(); + deserialize_from_with_limit(&mut cursor, PACKET_DATA_SIZE).unwrap(); assert_eq!(cursor.position(), request_bytes.len() as u64); if let RepairProtocol::HighestWindowIndex { header, diff --git a/core/src/sigverify_stage.rs b/core/src/sigverify_stage.rs index 07bf1d12951858..7ce1646bb5bfda 100644 --- a/core/src/sigverify_stage.rs +++ b/core/src/sigverify_stage.rs @@ -391,6 +391,7 @@ impl SigVerifyStage { let mut last_print = Instant::now(); const MAX_DEDUPER_AGE: Duration = Duration::from_secs(2); const DEDUPER_FALSE_POSITIVE_RATE: f64 = 0.001; + // TODO(klykov): don't we need to increase this constant when we increase the max tx size? const DEDUPER_NUM_BITS: u64 = 63_999_979; Builder::new() .name(thread_name.to_string()) diff --git a/cost-model/Cargo.toml b/cost-model/Cargo.toml index 79925a127e1c39..e58389c08d3093 100644 --- a/cost-model/Cargo.toml +++ b/cost-model/Cargo.toml @@ -55,6 +55,7 @@ solana-hash = { workspace = true, optional = true } solana-message = { workspace = true, optional = true } solana-metrics = { workspace = true } solana-packet = { workspace = true } +solana-perf = { workspace = true } solana-pubkey = { workspace = true } solana-runtime-transaction = { workspace = true } solana-sdk-ids = { workspace = true } diff --git a/cost-model/src/cost_model.rs b/cost-model/src/cost_model.rs index 17b34d1dae2637..8f286173210532 100644 --- a/cost-model/src/cost_model.rs +++ b/cost-model/src/cost_model.rs @@ -11,6 +11,7 @@ use { solana_bincode::limited_deserialize, solana_compute_budget::compute_budget_limits::DEFAULT_HEAP_COST, solana_fee_structure::FeeStructure, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_pubkey::Pubkey, solana_runtime_transaction::transaction_meta::StaticMeta, solana_sdk_ids::system_program, @@ -241,7 +242,7 @@ impl CostModel { ) -> SystemProgramAccountAllocation { if program_id == &system_program::id() { if let Ok(instruction) = - limited_deserialize(instruction.data, solana_packet::PACKET_DATA_SIZE as u64) + limited_deserialize(instruction.data, QUIC_MAX_STREAM_SIZE as u64) { Self::calculate_account_data_size_on_deserialized_system_instruction(instruction) } else { diff --git a/gossip/src/protocol.rs b/gossip/src/protocol.rs index 3be4d08a4abeda..77656ef15da965 100644 --- a/gossip/src/protocol.rs +++ b/gossip/src/protocol.rs @@ -9,7 +9,7 @@ use { bincode::serialize, serde::{Deserialize, Serialize}, solana_keypair::signable::Signable, - solana_perf::packet::PACKET_DATA_SIZE, + solana_packet::PACKET_DATA_SIZE, solana_pubkey::Pubkey, solana_sanitize::{Sanitize, SanitizeError}, solana_signature::Signature, diff --git a/gossip/src/wire_format_tests.rs b/gossip/src/wire_format_tests.rs index 440dbbe44daf0c..973221d12d40c1 100644 --- a/gossip/src/wire_format_tests.rs +++ b/gossip/src/wire_format_tests.rs @@ -7,12 +7,14 @@ mod tests { crate::protocol::Protocol, serde::Serialize, solana_net_utils::tooling_for_tests::{hexdump, validate_packet_format}, + solana_packet::PACKET_DATA_SIZE, solana_sanitize::Sanitize, std::path::PathBuf, }; fn parse_gossip(bytes: &[u8]) -> anyhow::Result { - let pkt: Protocol = solana_perf::packet::deserialize_from_with_limit(bytes)?; + let pkt: Protocol = + solana_perf::packet::deserialize_from_with_limit(bytes, PACKET_DATA_SIZE)?; pkt.sanitize()?; Ok(pkt) } diff --git a/ledger/src/shred/merkle.rs b/ledger/src/shred/merkle.rs index ea7c6bc04a5946..414214555bdbf3 100644 --- a/ledger/src/shred/merkle.rs +++ b/ledger/src/shred/merkle.rs @@ -454,7 +454,7 @@ macro_rules! impl_merkle_shred { }; } -use impl_merkle_shred; +use {impl_merkle_shred, solana_packet::PACKET_DATA_SIZE}; impl<'a> ShredTrait<'a> for ShredData { type SignedData = Hash; @@ -482,7 +482,7 @@ impl<'a> ShredTrait<'a> for ShredData { } payload.truncate(Self::SIZE_OF_PAYLOAD); let (common_header, data_header): (ShredCommonHeader, _) = - deserialize_from_with_limit(&payload[..])?; + deserialize_from_with_limit(&payload[..], PACKET_DATA_SIZE)?; if !matches!(common_header.shred_variant, ShredVariant::MerkleData { .. }) { return Err(Error::InvalidShredVariant); } @@ -533,7 +533,7 @@ impl<'a> ShredTrait<'a> for ShredCode { { let mut payload = Payload::from(payload); let (common_header, coding_header): (ShredCommonHeader, _) = - deserialize_from_with_limit(&payload[..])?; + deserialize_from_with_limit(&payload[..], PACKET_DATA_SIZE)?; if !matches!(common_header.shred_variant, ShredVariant::MerkleCode { .. }) { return Err(Error::InvalidShredVariant); } @@ -776,7 +776,7 @@ pub(super) fn recover( return Err(Error::InvalidRecoveredShred); }; let (common_header, data_header) = - deserialize_from_with_limit(&shred.payload[..])?; + deserialize_from_with_limit(&shred.payload[..], PACKET_DATA_SIZE)?; if shred.common_header != common_header { return Err(Error::InvalidRecoveredShred); } diff --git a/perf/src/deduper.rs b/perf/src/deduper.rs index fcfc01b00747ca..3a8ed650d3bf59 100644 --- a/perf/src/deduper.rs +++ b/perf/src/deduper.rs @@ -118,6 +118,7 @@ mod tests { }, rand::SeedableRng, rand_chacha::ChaChaRng, + //TODO(klykov): deduper is used for shreds as well, so use here PACKET_DATA_SIZE for now. solana_packet::{Meta, PACKET_DATA_SIZE}, test_case::test_case, }; diff --git a/perf/src/packet.rs b/perf/src/packet.rs index c5bcb832baa9a6..74889452a66b02 100644 --- a/perf/src/packet.rs +++ b/perf/src/packet.rs @@ -20,9 +20,11 @@ use { }; pub use { bytes, - solana_packet::{self, Meta, Packet, PacketFlags, PACKET_DATA_SIZE}, + solana_packet::{self, Meta, Packet, PacketFlags}, }; +pub const QUIC_MAX_STREAM_SIZE: usize = 4096; + pub const NUM_PACKETS: usize = 1024 * 8; pub const PACKETS_PER_BATCH: usize = 64; @@ -68,7 +70,7 @@ impl BytesPacket { where T: solana_packet::Encode, { - let buffer = BytesMut::with_capacity(PACKET_DATA_SIZE); + let buffer = BytesMut::with_capacity(QUIC_MAX_STREAM_SIZE); let mut writer = buffer.writer(); data.encode(&mut writer)?; let buffer = writer.into_inner(); @@ -887,7 +889,10 @@ impl<'a> IntoParallelIterator for &'a mut BytesPacketBatch { } } -pub fn deserialize_from_with_limit(reader: R) -> bincode::Result +pub fn deserialize_from_with_limit( + reader: R, + max_packet_data_size: usize, +) -> bincode::Result where R: Read, T: DeserializeOwned, @@ -895,7 +900,7 @@ where // with_limit causes pre-allocation size to be limited // to prevent against memory exhaustion attacks. bincode::options() - .with_limit(PACKET_DATA_SIZE as u64) + .with_limit(max_packet_data_size as u64) .with_fixint_encoding() .allow_trailing_bytes() .deserialize_from(reader) diff --git a/perf/src/sigverify.rs b/perf/src/sigverify.rs index 1d3ae363837f00..5246dce78f083d 100644 --- a/perf/src/sigverify.rs +++ b/perf/src/sigverify.rs @@ -563,6 +563,92 @@ pub fn mark_disabled(batches: &mut [PacketBatch], r: &[Vec]) { } } +// pub fn ed25519_verify( +// batches: &mut [PacketBatch], +// recycler: &Recycler, +// recycler_out: &Recycler>, +// reject_non_vote: bool, +// valid_packet_count: usize, +// ) { +// let Some(api) = perf_libs::api() else { +// return ed25519_verify_cpu(batches, reject_non_vote, valid_packet_count); +// }; +// let total_packet_count = count_packets_in_batches(batches); +// // micro-benchmarks show GPU time for smallest batch around 15-20ms +// // and CPU speed for 64-128 sigverifies around 10-20ms. 64 is a nice +// // power-of-two number around that accounting for the fact that the CPU +// // may be busy doing other things while being a real validator +// // TODO: dynamically adjust this crossover +// let maybe_valid_percentage = 100usize +// .wrapping_mul(valid_packet_count) +// .checked_div(total_packet_count); +// let Some(valid_percentage) = maybe_valid_percentage else { +// return; +// }; +// if valid_percentage < 90 || valid_packet_count < 64 { +// ed25519_verify_cpu(batches, reject_non_vote, valid_packet_count); +// return; +// } + +// let (signature_offsets, pubkey_offsets, msg_start_offsets, msg_sizes, sig_lens) = +// generate_offsets(batches, recycler, reject_non_vote); + +// debug!("CUDA ECDSA for {valid_packet_count}"); +// debug!("allocating out.."); +// let mut out = recycler_out.allocate("out_buffer"); +// out.set_pinnable(); +// let mut elems = Vec::new(); +// let mut rvs = Vec::new(); + +// let mut num_packets: usize = 0; +// // `BytesPacketBatch` cannot be directly used in CUDA. We have to retrieve +// // and convert byte batches to pinned batches. We must collect here so that +// // we keep the batches created by `BytesPacketBatch::to_pinned_packet_batch()` +// // alive. +// let pinned_batches = batches +// .iter_mut() +// .map(|batch| match batch { +// PacketBatch::Pinned(batch) => Cow::Borrowed(batch), +// PacketBatch::Bytes(batch) => Cow::Owned(batch.to_pinned_packet_batch()), +// }) +// .collect::>(); +// for batch in pinned_batches.iter() { +// elems.push(perf_libs::Elems { +// elems: batch.as_ptr().cast::(), +// num: batch.len() as u32, +// }); +// let v = vec![0u8; batch.len()]; +// rvs.push(v); +// num_packets = num_packets.saturating_add(batch.len()); +// } +// out.resize(signature_offsets.len(), 0); +// trace!("Starting verify num packets: {num_packets}"); +// trace!("elem len: {}", elems.len() as u32); +// trace!("packet sizeof: {}", size_of::() as u32); +// const USE_NON_DEFAULT_STREAM: u8 = 1; +// unsafe { +// let res = (api.ed25519_verify_many)( +// elems.as_ptr(), +// elems.len() as u32, +// size_of::() as u32, +// num_packets as u32, +// signature_offsets.len() as u32, +// msg_sizes.as_ptr(), +// pubkey_offsets.as_ptr(), +// signature_offsets.as_ptr(), +// msg_start_offsets.as_ptr(), +// out.as_mut_ptr(), +// USE_NON_DEFAULT_STREAM, +// ); +// if res != 0 { +// trace!("RETURN!!!: {res}"); +// } +// } +// trace!("done verify"); +// copy_return_values(sig_lens, &out, &mut rvs); +// mark_disabled(batches, &rvs); +// } + #[cfg(test)] #[allow(clippy::arithmetic_side_effects)] mod tests { @@ -571,7 +657,7 @@ mod tests { crate::{ packet::{ to_packet_batches, BytesPacket, BytesPacketBatch, Packet, RecycledPacketBatch, - PACKETS_PER_BATCH, + PACKETS_PER_BATCH, QUIC_MAX_STREAM_SIZE, }, sigverify::{self, PacketOffsets}, test_tx::{ @@ -903,7 +989,7 @@ mod tests { tx0.message.instructions[0].data = vec![1, 2, 3]; let message0a = tx0.message_data(); let tx_bytes = serialize(&tx0).unwrap(); - assert!(tx_bytes.len() <= PACKET_DATA_SIZE); + assert!(tx_bytes.len() <= QUIC_MAX_STREAM_SIZE); assert_eq!( memfind(&tx_bytes, tx0.signatures[0].as_ref()), Some(SIG_OFFSET) diff --git a/programs/loader-v4/Cargo.toml b/programs/loader-v4/Cargo.toml index 4c5a29af666145..df21cb408a3d1c 100644 --- a/programs/loader-v4/Cargo.toml +++ b/programs/loader-v4/Cargo.toml @@ -33,6 +33,7 @@ solana-instruction = { workspace = true } solana-loader-v3-interface = { workspace = true } solana-loader-v4-interface = { workspace = true, features = ["serde"] } solana-packet = { workspace = true } +solana-perf = { workspace = true } solana-program-runtime = { workspace = true } solana-pubkey = { workspace = true } solana-sbpf = { workspace = true, features = ["jit"] } diff --git a/programs/loader-v4/src/lib.rs b/programs/loader-v4/src/lib.rs index 6f79e77755192c..6faccd667debb1 100644 --- a/programs/loader-v4/src/lib.rs +++ b/programs/loader-v4/src/lib.rs @@ -17,6 +17,9 @@ use { state::{LoaderV4State, LoaderV4Status}, DEPLOYMENT_COOLDOWN_IN_SLOTS, }, + solana_log_collector::{ic_logger_msg, LogCollector}, + solana_measure::measure::Measure, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_program_runtime::{ invoke_context::InvokeContext, loaded_programs::{ProgramCacheEntry, ProgramCacheEntryOwner, ProgramCacheEntryType}, @@ -452,7 +455,7 @@ fn process_instruction_inner<'a>( let program_id = instruction_context.get_program_key()?; if loader_v4::check_id(program_id) { invoke_context.consume_checked(DEFAULT_COMPUTE_UNITS)?; - match limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)? { + match limited_deserialize(instruction_data, QUIC_MAX_STREAM_SIZE as u64)? { LoaderV4Instruction::Write { offset, bytes } => { process_instruction_write(invoke_context, offset, bytes) } diff --git a/programs/system/Cargo.toml b/programs/system/Cargo.toml index f478c3aa920830..efa7252fdcbb8b 100644 --- a/programs/system/Cargo.toml +++ b/programs/system/Cargo.toml @@ -30,6 +30,7 @@ solana-instruction = { workspace = true } solana-nonce = { workspace = true, features = ["serde"] } solana-nonce-account = { workspace = true } solana-packet = { workspace = true } +solana-perf = { workspace = true } solana-program-runtime = { workspace = true } solana-pubkey = { workspace = true, features = ["sha2"] } solana-sdk-ids = { workspace = true } diff --git a/programs/system/src/system_processor.rs b/programs/system/src/system_processor.rs index 9879ad54ae4d8f..e02ca252093822 100644 --- a/programs/system/src/system_processor.rs +++ b/programs/system/src/system_processor.rs @@ -7,6 +7,7 @@ use { solana_bincode::limited_deserialize, solana_instruction::error::InstructionError, solana_nonce as nonce, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_program_runtime::{ declare_process_instruction, invoke_context::InvokeContext, sysvar_cache::get_sysvar_with_account_check, @@ -288,8 +289,7 @@ declare_process_instruction!(Entrypoint, DEFAULT_COMPUTE_UNITS, |invoke_context| let transaction_context = &invoke_context.transaction_context; let instruction_context = transaction_context.get_current_instruction_context()?; let instruction_data = instruction_context.get_instruction_data(); - let instruction = - limited_deserialize(instruction_data, solana_packet::PACKET_DATA_SIZE as u64)?; + let instruction = limited_deserialize(instruction_data, QUIC_MAX_STREAM_SIZE as u64)?; trace!("process_instruction: {instruction:?}"); diff --git a/quic-client/tests/quic_client.rs b/quic-client/tests/quic_client.rs index a3bdb7bd196bb4..28b0ad06f30ab5 100644 --- a/quic-client/tests/quic_client.rs +++ b/quic-client/tests/quic_client.rs @@ -8,8 +8,7 @@ mod tests { }, solana_keypair::Keypair, solana_net_utils::sockets::{bind_to, localhost_port_range_for_tests}, - solana_packet::PACKET_DATA_SIZE, - solana_perf::packet::PacketBatch, + solana_perf::packet::{PacketBatch, QUIC_MAX_STREAM_SIZE}, solana_quic_client::nonblocking::quic_client::{QuicClient, QuicLazyInitializedEndpoint}, solana_streamer::{ nonblocking::{quic::SpawnNonBlockingServerResult, swqos::SwQosConfig}, @@ -98,9 +97,9 @@ mod tests { ); // Send a full size packet with single byte writes. - let num_bytes = PACKET_DATA_SIZE; + let num_bytes = QUIC_MAX_STREAM_SIZE; let num_expected_packets: usize = 3000; - let packets = vec![vec![0u8; PACKET_DATA_SIZE]; num_expected_packets]; + let packets = vec![vec![0u8; QUIC_MAX_STREAM_SIZE]; num_expected_packets]; assert!(client.send_data_batch_async(packets).is_ok()); @@ -179,9 +178,9 @@ mod tests { ); // Send a full size packet with single byte writes. - let num_bytes = PACKET_DATA_SIZE; + let num_bytes = QUIC_MAX_STREAM_SIZE; let num_expected_packets: usize = 3000; - let packets = vec![vec![0u8; PACKET_DATA_SIZE]; num_expected_packets]; + let packets = vec![vec![0u8; QUIC_MAX_STREAM_SIZE]; num_expected_packets]; for packet in packets { let _ = client.send_data(&packet).await; } @@ -273,9 +272,9 @@ mod tests { let request_sender = QuicClientConnection::new(Arc::new(endpoint), tpu_addr, connection_cache_stats); // Send a full size packet with single byte writes as a request. - let num_bytes = PACKET_DATA_SIZE; + let num_bytes = QUIC_MAX_STREAM_SIZE; let num_expected_packets: usize = 3000; - let packets = vec![vec![0u8; PACKET_DATA_SIZE]; num_expected_packets]; + let packets = vec![vec![0u8; QUIC_MAX_STREAM_SIZE]; num_expected_packets]; assert!(request_sender.send_data_batch_async(packets).is_ok()); check_packets(receiver, num_bytes, num_expected_packets); @@ -295,9 +294,9 @@ mod tests { QuicClientConnection::new(Arc::new(endpoint2), server_addr, connection_cache_stats2); // Send a full size packet with single byte writes. - let num_bytes = PACKET_DATA_SIZE; + let num_bytes = QUIC_MAX_STREAM_SIZE; let num_expected_packets: usize = 3000; - let packets = vec![vec![0u8; PACKET_DATA_SIZE]; num_expected_packets]; + let packets = vec![vec![0u8; QUIC_MAX_STREAM_SIZE]; num_expected_packets]; assert!(response_sender.send_data_batch_async(packets).is_ok()); check_packets(receiver2, num_bytes, num_expected_packets); @@ -346,9 +345,9 @@ mod tests { let client = QuicClient::new(Arc::new(QuicLazyInitializedEndpoint::default()), tpu_addr); // Send a full size packet with single byte writes. - let num_bytes = PACKET_DATA_SIZE; + let num_bytes = QUIC_MAX_STREAM_SIZE; let num_expected_packets: usize = 3; - let packets = vec![vec![0u8; PACKET_DATA_SIZE]; num_expected_packets]; + let packets = vec![vec![0u8; QUIC_MAX_STREAM_SIZE]; num_expected_packets]; let client_stats = ClientStats::default(); for packet in packets { let _ = client diff --git a/rpc/src/rpc.rs b/rpc/src/rpc.rs index 63db5ce8b99498..28c83c2e3d6a31 100644 --- a/rpc/src/rpc.rs +++ b/rpc/src/rpc.rs @@ -48,7 +48,7 @@ use { }, solana_message::{AddressLoader, SanitizedMessage}, solana_metrics::inc_new_counter_info, - solana_perf::packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_program_pack::Pack, solana_pubkey::{Pubkey, PUBKEY_BYTES}, solana_rpc_client_api::{ @@ -4338,8 +4338,8 @@ fn rpc_perf_sample_from_perf_sample(slot: u64, sample: PerfSample) -> RpcPerfSam } } -const MAX_BASE58_SIZE: usize = 1683; // Golden, bump if PACKET_DATA_SIZE changes -const MAX_BASE64_SIZE: usize = 1644; // Golden, bump if PACKET_DATA_SIZE changes +const MAX_BASE58_SIZE: usize = 5594; // Golden, bump if QUIC_MAX_STREAM_SIZE changes +const MAX_BASE64_SIZE: usize = 5464; // Golden, bump if QUIC_MAX_STREAM_SIZE changes fn decode_and_deserialize( encoded: String, encoding: TransactionBinaryEncoding, @@ -4356,7 +4356,7 @@ where type_name::(), encoded.len(), MAX_BASE58_SIZE, - PACKET_DATA_SIZE, + QUIC_MAX_STREAM_SIZE, ))); } bs58::decode(encoded) @@ -4371,7 +4371,7 @@ where type_name::(), encoded.len(), MAX_BASE64_SIZE, - PACKET_DATA_SIZE, + QUIC_MAX_STREAM_SIZE, ))); } BASE64_STANDARD @@ -4379,16 +4379,16 @@ where .map_err(|e| Error::invalid_params(format!("invalid base64 encoding: {e:?}")))? } }; - if wire_output.len() > PACKET_DATA_SIZE { + if wire_output.len() > QUIC_MAX_STREAM_SIZE { return Err(Error::invalid_params(format!( "decoded {} too large: {} bytes (max: {} bytes)", type_name::(), wire_output.len(), - PACKET_DATA_SIZE + QUIC_MAX_STREAM_SIZE ))); } bincode::options() - .with_limit(PACKET_DATA_SIZE as u64) + .with_limit(QUIC_MAX_STREAM_SIZE as u64) .with_fixint_encoding() .allow_trailing_bytes() .deserialize_from(&wire_output[..]) @@ -9082,7 +9082,7 @@ pub mod tests { #[test] fn test_worst_case_encoded_tx_goldens() { - let ff_tx = vec![0xffu8; PACKET_DATA_SIZE]; + let ff_tx = vec![0xffu8; QUIC_MAX_STREAM_SIZE]; let tx58 = bs58::encode(&ff_tx).into_string(); assert_eq!(tx58.len(), MAX_BASE58_SIZE); let tx64 = BASE64_STANDARD.encode(&ff_tx); @@ -9092,7 +9092,7 @@ pub mod tests { #[test] fn test_decode_and_deserialize_too_large_payloads_fail() { // +2 because +1 still fits in base64 encoded worst-case - let too_big = PACKET_DATA_SIZE + 2; + let too_big = QUIC_MAX_STREAM_SIZE + 2; let tx_ser = vec![0xffu8; too_big]; let tx58 = bs58::encode(&tx_ser).into_string(); @@ -9101,31 +9101,27 @@ pub mod tests { decode_and_deserialize::(tx58, TransactionBinaryEncoding::Base58) .unwrap_err(), Error::invalid_params(format!( - "base58 encoded solana_transaction::Transaction too large: {tx58_len} bytes (max: \ - encoded/raw {MAX_BASE58_SIZE}/{PACKET_DATA_SIZE})", - )) - ); + "base58 encoded solana_transaction::Transaction too large: {tx58_len} bytes (max: encoded/raw {MAX_BASE58_SIZE}/{QUIC_MAX_STREAM_SIZE})", + ) + )); let tx64 = BASE64_STANDARD.encode(&tx_ser); - let tx64_len = tx64.len(); assert_eq!( decode_and_deserialize::(tx64, TransactionBinaryEncoding::Base64) .unwrap_err(), Error::invalid_params(format!( - "base64 encoded solana_transaction::Transaction too large: {tx64_len} bytes (max: \ - encoded/raw {MAX_BASE64_SIZE}/{PACKET_DATA_SIZE})", + "decoded solana_transaction::Transaction too large: {too_big} bytes (max: {QUIC_MAX_STREAM_SIZE} bytes)", )) ); - let too_big = PACKET_DATA_SIZE + 1; + let too_big = QUIC_MAX_STREAM_SIZE + 1; let tx_ser = vec![0x00u8; too_big]; let tx58 = bs58::encode(&tx_ser).into_string(); assert_eq!( decode_and_deserialize::(tx58, TransactionBinaryEncoding::Base58) .unwrap_err(), Error::invalid_params(format!( - "decoded solana_transaction::Transaction too large: {too_big} bytes (max: \ - {PACKET_DATA_SIZE} bytes)" + "decoded solana_transaction::Transaction too large: {too_big} bytes (max: {QUIC_MAX_STREAM_SIZE} bytes)" )) ); @@ -9134,12 +9130,11 @@ pub mod tests { decode_and_deserialize::(tx64, TransactionBinaryEncoding::Base64) .unwrap_err(), Error::invalid_params(format!( - "decoded solana_transaction::Transaction too large: {too_big} bytes (max: \ - {PACKET_DATA_SIZE} bytes)" + "decoded solana_transaction::Transaction too large: {too_big} bytes (max: {QUIC_MAX_STREAM_SIZE} bytes)", )) ); - let tx_ser = vec![0xffu8; PACKET_DATA_SIZE - 2]; + let tx_ser = vec![0xffu8; QUIC_MAX_STREAM_SIZE - 2]; let mut tx64 = BASE64_STANDARD.encode(&tx_ser); assert_eq!( decode_and_deserialize::(tx64.clone(), TransactionBinaryEncoding::Base64) @@ -9155,7 +9150,7 @@ pub mod tests { assert_eq!( decode_and_deserialize::(tx64, TransactionBinaryEncoding::Base64) .unwrap_err(), - Error::invalid_params("invalid base64 encoding: InvalidByte(1640, 33)".to_string()) + Error::invalid_params("invalid base64 encoding: InvalidByte(5460, 33)".to_string()) ); let mut tx58 = bs58::encode(&tx_ser).into_string(); @@ -9174,7 +9169,7 @@ pub mod tests { decode_and_deserialize::(tx58, TransactionBinaryEncoding::Base58) .unwrap_err(), Error::invalid_params( - "invalid base58 encoding: InvalidCharacter { character: '!', index: 1680 }" + "invalid base58 encoding: InvalidCharacter { character: '!', index: 5592 }" .to_string(), ) ); diff --git a/runtime/src/bank.rs b/runtime/src/bank.rs index 13eec05488c469..b0882a46ae246f 100644 --- a/runtime/src/bank.rs +++ b/runtime/src/bank.rs @@ -112,7 +112,8 @@ use { solana_lattice_hash::lt_hash::LtHash, solana_measure::{measure::Measure, measure_time, measure_us}, solana_message::{inner_instruction::InnerInstructions, AccountKeys, SanitizedMessage}, - solana_packet::PACKET_DATA_SIZE, + solana_native_token::LAMPORTS_PER_SOL, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_precompile_error::PrecompileError, solana_program_runtime::{ invoke_context::BuiltinFunctionWithContext, @@ -4735,7 +4736,7 @@ impl Bank { let sanitized_tx = { let size = bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?; - if size > PACKET_DATA_SIZE as u64 { + if size > QUIC_MAX_STREAM_SIZE as u64 { return Err(TransactionError::SanitizeFailure); } let message_hash = if verification_mode == TransactionVerificationMode::FullVerification diff --git a/runtime/src/bank/tests.rs b/runtime/src/bank/tests.rs index d9a605a86ce07a..9d0772f7dc712f 100644 --- a/runtime/src/bank/tests.rs +++ b/runtime/src/bank/tests.rs @@ -73,7 +73,7 @@ use { }, solana_native_token::LAMPORTS_PER_SOL, solana_nonce::{self as nonce, state::DurableNonce}, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_poh_config::PohConfig, solana_program_runtime::{ declare_process_instruction, @@ -9086,18 +9086,19 @@ fn test_verify_transactions_packet_data_size() { let message = Message::new(&ixs[..], Some(&pubkey)); Transaction::new(&[&keypair], message, recent_blockhash) }; + // Small transaction. { - let tx = make_transaction(5); - assert!(bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64); + let tx = make_transaction(80); + assert!(bincode::serialized_size(&tx).unwrap() <= QUIC_MAX_STREAM_SIZE as u64); assert!(bank .verify_transaction(tx.into(), TransactionVerificationMode::FullVerification) .is_ok(),); } // Big transaction. { - let tx = make_transaction(25); - assert!(bincode::serialized_size(&tx).unwrap() > PACKET_DATA_SIZE as u64); + let tx = make_transaction(81); + assert!(bincode::serialized_size(&tx).unwrap() > QUIC_MAX_STREAM_SIZE as u64); assert_matches!( bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification), Err(TransactionError::SanitizeFailure) @@ -9105,10 +9106,10 @@ fn test_verify_transactions_packet_data_size() { } // Assert that verify fails as soon as serialized // size exceeds packet data size. - for size in 1..30 { + for size in (1..85).step_by(5) { let tx = make_transaction(size); assert_eq!( - bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64, + bincode::serialized_size(&tx).unwrap() <= QUIC_MAX_STREAM_SIZE as u64, bank.verify_transaction(tx.into(), TransactionVerificationMode::FullVerification) .is_ok(), ); diff --git a/streamer/src/nonblocking/quic.rs b/streamer/src/nonblocking/quic.rs index 16cc09855c5948..f15f759988555d 100644 --- a/streamer/src/nonblocking/quic.rs +++ b/streamer/src/nonblocking/quic.rs @@ -19,8 +19,13 @@ use { solana_measure::measure::Measure, solana_net_utils::token_bucket::TokenBucket, solana_packet::{Meta, PACKET_DATA_SIZE}, - solana_perf::packet::{BytesPacket, PacketBatch}, + solana_perf::packet::{ + BytesPacket, BytesPacketBatch, PacketBatch, PACKETS_PER_BATCH, QUIC_MAX_STREAM_SIZE, + }, solana_pubkey::Pubkey, + solana_quic_definitions::{ + QUIC_MAX_STAKED_RECEIVE_WINDOW_RATIO, QUIC_MIN_STAKED_RECEIVE_WINDOW_RATIO, + }, solana_signature::Signature, solana_tls_utils::get_pubkey_from_tls_certificate, solana_transaction_metrics_tracker::signature_if_should_track_packet, @@ -429,9 +434,93 @@ pub(crate) fn update_open_connections_stat( stats .peak_open_unstaked_connections .fetch_max(connection_table.table_size(), Ordering::Relaxed); + // connection_table.close( + // CONNECTION_CLOSE_CODE_EXCEED_MAX_STREAM_COUNT.into(), + // CONNECTION_CLOSE_REASON_EXCEED_MAX_STREAM_COUNT, + // ); + + // stats + // .connection_add_failed_invalid_stream_count + // .fetch_add(1, Ordering::Relaxed); + // Err(ConnectionHandlerError::MaxStreamError) } } +// async fn prune_unstaked_connections_and_add_new_connection( +// client_connection_tracker: ClientConnectionTracker, +// connection: Connection, +// connection_table: Arc>, +// max_connections: usize, +// params: &NewConnectionHandlerParams, +// wait_for_chunk_timeout: Duration, +// stream_load_ema: Arc, +// ) -> Result<(), ConnectionHandlerError> { +// let stats = params.stats.clone(); +// if max_connections > 0 { +// let connection_table_clone = connection_table.clone(); +// let mut connection_table = connection_table.lock().await; +// prune_unstaked_connection_table(&mut connection_table, max_connections, stats); +// handle_and_cache_new_connection( +// client_connection_tracker, +// connection, +// connection_table, +// connection_table_clone, +// params, +// wait_for_chunk_timeout, +// stream_load_ema, +// ) +// } else { +// connection.close( +// CONNECTION_CLOSE_CODE_DISALLOWED.into(), +// CONNECTION_CLOSE_REASON_DISALLOWED, +// ); +// Err(ConnectionHandlerError::ConnectionAddError) +// } +// } + +/// Calculate the ratio for per connection receive window from a staked peer +// fn compute_receive_window_ratio_for_staked_node(max_stake: u64, min_stake: u64, stake: u64) -> u64 { +// // Testing shows the maximum througput from a connection is achieved at receive_window = +// // QUIC_MAX_STREAM_SIZE * 10. Beyond that, there is not much gain. We linearly map the +// // stake to the ratio range from QUIC_MIN_STAKED_RECEIVE_WINDOW_RATIO to +// // QUIC_MAX_STAKED_RECEIVE_WINDOW_RATIO. Where the linear algebra of finding the ratio 'r' +// // for stake 's' is, +// // r(s) = a * s + b. Given the max_stake, min_stake, max_ratio, min_ratio, we can find +// // a and b. + +// if stake > max_stake { +// return QUIC_MAX_STAKED_RECEIVE_WINDOW_RATIO; +// } + +// let max_ratio = QUIC_MAX_STAKED_RECEIVE_WINDOW_RATIO; +// let min_ratio = QUIC_MIN_STAKED_RECEIVE_WINDOW_RATIO; +// if max_stake > min_stake { +// let a = (max_ratio - min_ratio) as f64 / (max_stake - min_stake) as f64; +// let b = max_ratio as f64 - ((max_stake as f64) * a); +// let ratio = (a * stake as f64) + b; +// ratio.round() as u64 +// } else { +// QUIC_MAX_STAKED_RECEIVE_WINDOW_RATIO +// } +// } + +// fn compute_recieve_window( +// max_stake: u64, +// min_stake: u64, +// peer_type: ConnectionPeerType, +// ) -> Result { +// match peer_type { +// ConnectionPeerType::Unstaked => { +// VarInt::from_u64(QUIC_MAX_STREAM_SIZE as u64 * QUIC_UNSTAKED_RECEIVE_WINDOW_RATIO) +// } +// ConnectionPeerType::Staked(peer_stake) => { +// let ratio = +// compute_receive_window_ratio_for_staked_node(max_stake, min_stake, peer_stake); +// VarInt::from_u64(QUIC_MAX_STREAM_SIZE as u64 * ratio) +// } +// } +// } + #[allow(clippy::too_many_arguments)] async fn setup_connection( connecting: Connecting, @@ -640,6 +729,7 @@ async fn handle_connection( // Bytes values are small, so overall the array takes only 128 bytes, and the "cost" of // overallocating a few bytes is negligible compared to the cost of having to do multiple // read_chunks() calls. + // TODO(klykov): Do we want to increase the size of the array if the size of txs is increased? let mut chunks: [Bytes; 4] = array::from_fn(|_| Bytes::new()); loop { @@ -740,8 +830,8 @@ fn handle_chunks( let n_chunks = chunks.len(); for chunk in chunks { accum.meta.size += chunk.len(); - if accum.meta.size > PACKET_DATA_SIZE { - // The stream window size is set to PACKET_DATA_SIZE, so one individual chunk can + if accum.meta.size > QUIC_MAX_STREAM_SIZE { + // The stream window size is set to QUIC_MAX_STREAM_SIZE, so one individual chunk can // never exceed this size. A peer can send two chunks that together exceed the size // tho, in which case we report the error. stats.invalid_stream_size.fetch_add(1, Ordering::Relaxed); @@ -1164,7 +1254,7 @@ pub mod test { // Send enough data to create more than 1 chunks. // The first will try to open the connection (which should fail). // The following chunks will enable the detection of connection failure. - let data = vec![1u8; PACKET_DATA_SIZE * 2]; + let data = vec![1u8; QUIC_MAX_STREAM_SIZE * 2]; s2.write_all(&data) .await .expect_err("shouldn't be able to open 2 connections"); @@ -1184,7 +1274,7 @@ pub mod test { let conn1 = Arc::new(make_client_endpoint(&server_address, client_keypair).await); // Send a full size packet with single byte writes. - let num_bytes = PACKET_DATA_SIZE; + let num_bytes = QUIC_MAX_STREAM_SIZE; let num_expected_packets = 1; let mut s1 = conn1.open_uni().await.unwrap(); for _ in 0..num_bytes { @@ -1249,7 +1339,7 @@ pub mod test { // Send a full size packet with single byte writes. if let Ok(mut s1) = conn1.open_uni().await { - for _ in 0..PACKET_DATA_SIZE { + for _ in 0..QUIC_MAX_STREAM_SIZE { // Ignoring any errors here. s1.finish() will test the error condition s1.write_all(&[0u8]).await.unwrap_or_default(); } @@ -1994,7 +2084,7 @@ pub mod test { let mut send_stream = client_connection.open_uni().await.unwrap(); send_stream - .write_all(&[42; PACKET_DATA_SIZE + 1]) + .write_all(&[42; QUIC_MAX_STREAM_SIZE + 1]) .await .unwrap(); match client_connection.closed().await { diff --git a/streamer/src/packet.rs b/streamer/src/packet.rs index a3d647b6c1f888..4ad55f94763d42 100644 --- a/streamer/src/packet.rs +++ b/streamer/src/packet.rs @@ -18,6 +18,7 @@ use { }, }; pub use { + // TODO(klykov): this code is for UDP solana_packet::{Meta, Packet, PACKET_DATA_SIZE}, solana_perf::packet::{ PacketBatch, PacketBatchRecycler, PacketRef, PacketRefMut, RecycledPacketBatch, diff --git a/streamer/src/quic.rs b/streamer/src/quic.rs index 4df06de3975a62..5dd9944b31fad1 100644 --- a/streamer/src/quic.rs +++ b/streamer/src/quic.rs @@ -16,8 +16,7 @@ use { }, rustls::KeyLogFile, solana_keypair::Keypair, - solana_packet::PACKET_DATA_SIZE, - solana_perf::packet::PacketBatch, + solana_perf::packet::{PacketBatch, QUIC_MAX_STREAM_SIZE}, solana_quic_definitions::{ NotifyKeyUpdate, QUIC_MAX_TIMEOUT, QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS, }, @@ -104,8 +103,8 @@ pub(crate) fn configure_server( const MAX_CONCURRENT_UNI_STREAMS: u32 = (QUIC_MAX_UNSTAKED_CONCURRENT_STREAMS.saturating_mul(2)) as u32; config.max_concurrent_uni_streams(MAX_CONCURRENT_UNI_STREAMS.into()); - config.stream_receive_window((PACKET_DATA_SIZE as u32).into()); - config.receive_window((PACKET_DATA_SIZE as u32).into()); + config.stream_receive_window((QUIC_MAX_STREAM_SIZE as u32).into()); + config.receive_window((QUIC_MAX_STREAM_SIZE as u32).into()); let timeout = IdleTimeout::try_from(QUIC_MAX_TIMEOUT).unwrap(); config.max_idle_timeout(Some(timeout)); diff --git a/transaction-view/Cargo.toml b/transaction-view/Cargo.toml index bed4d78fe48adc..294ba9e552144c 100644 --- a/transaction-view/Cargo.toml +++ b/transaction-view/Cargo.toml @@ -16,7 +16,7 @@ dev-context-only-utils = [] [dependencies] solana-hash = { workspace = true } solana-message = { workspace = true } -solana-packet = { workspace = true } +solana-perf = { workspace = true } solana-pubkey = { workspace = true } solana-sdk-ids = { workspace = true } solana-short-vec = { workspace = true } diff --git a/transaction-view/benches/bytes.rs b/transaction-view/benches/bytes.rs index dad920ba452af6..bda6b82d9dffb8 100644 --- a/transaction-view/benches/bytes.rs +++ b/transaction-view/benches/bytes.rs @@ -2,7 +2,7 @@ use { agave_transaction_view::bytes::{optimized_read_compressed_u16, read_compressed_u16}, bincode::{serialize_into, DefaultOptions, Options}, criterion::{black_box, criterion_group, criterion_main, Criterion, Throughput}, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_short_vec::{decode_shortu16_len, ShortU16}, }; @@ -10,8 +10,8 @@ fn setup() -> Vec<(u16, usize, Vec)> { let options = DefaultOptions::new().with_fixint_encoding(); // Ensure fixed-int encoding // Create a vector of all valid u16 values serialized into 16-byte buffers. - let mut values = Vec::with_capacity(PACKET_DATA_SIZE); - for value in 0..PACKET_DATA_SIZE as u16 { + let mut values = Vec::with_capacity(QUIC_MAX_STREAM_SIZE); + for value in 0..QUIC_MAX_STREAM_SIZE as u16 { let short_u16 = ShortU16(value); let mut buffer = vec![0u8; 16]; let serialized_len = options diff --git a/transaction-view/src/address_table_lookup_frame.rs b/transaction-view/src/address_table_lookup_frame.rs index b56f7c8c937dcc..1a289aeb36831e 100644 --- a/transaction-view/src/address_table_lookup_frame.rs +++ b/transaction-view/src/address_table_lookup_frame.rs @@ -8,7 +8,7 @@ use { }, core::fmt::{Debug, Formatter}, solana_hash::Hash, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_pubkey::Pubkey, solana_signature::Signature, solana_svm_transaction::message_address_table_lookup::SVMMessageAddressTableLookup, @@ -47,7 +47,7 @@ const MIN_SIZED_PACKET_WITH_ATLS: usize = { /// The maximum number of ATLS that can fit in a valid packet. const MAX_ATLS_PER_PACKET: u8 = - ((PACKET_DATA_SIZE - MIN_SIZED_PACKET_WITH_ATLS) / MIN_SIZED_ATL) as u8; + ((QUIC_MAX_STREAM_SIZE - MIN_SIZED_PACKET_WITH_ATLS) / MIN_SIZED_ATL) as u8; /// Contains metadata about the address table lookups in a transaction packet. #[derive(Debug)] diff --git a/transaction-view/src/bytes.rs b/transaction-view/src/bytes.rs index 0045b2be303a65..39dc223d3944f7 100644 --- a/transaction-view/src/bytes.rs +++ b/transaction-view/src/bytes.rs @@ -240,7 +240,7 @@ mod tests { use { super::*, bincode::{serialize_into, DefaultOptions, Options}, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_short_vec::ShortU16, }; @@ -334,7 +334,7 @@ mod tests { let options = DefaultOptions::new().with_fixint_encoding(); // Ensure fixed-int encoding // Test all possible u16 values under the packet length - for value in 0..=PACKET_DATA_SIZE as u16 { + for value in 0..=QUIC_MAX_STREAM_SIZE as u16 { let mut offset; let short_u16 = ShortU16(value); diff --git a/transaction-view/src/signature_frame.rs b/transaction-view/src/signature_frame.rs index 5dee5902c20815..e27c3cb7cada81 100644 --- a/transaction-view/src/signature_frame.rs +++ b/transaction-view/src/signature_frame.rs @@ -3,7 +3,7 @@ use { bytes::{advance_offset_for_array, read_byte}, result::{Result, TransactionViewError}, }, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_pubkey::Pubkey, solana_signature::Signature, }; @@ -15,8 +15,9 @@ use { // In our u16 encoding scheme, 12 would be encoded as a single byte. // Rather than using the u16 decoding, we can simply read the byte and // verify that the MSB is not set. -const MAX_SIGNATURES_PER_PACKET: u8 = - (PACKET_DATA_SIZE / (core::mem::size_of::() + core::mem::size_of::())) as u8; +const MAX_SIGNATURES_PER_PACKET: u8 = (QUIC_MAX_STREAM_SIZE + / (core::mem::size_of::() + core::mem::size_of::())) + as u8; /// Metadata for accessing transaction-level signatures in a transaction view. #[derive(Debug)] @@ -78,9 +79,9 @@ mod tests { let bytes = bincode::serialize(&ShortVec(signatures)).unwrap(); let mut offset = 0; let frame = SignatureFrame::try_new(&bytes, &mut offset).unwrap(); - assert_eq!(frame.num_signatures, 12); + assert_eq!(frame.num_signatures, 42); assert_eq!(frame.offset, 1); - assert_eq!(offset, 1 + 12 * core::mem::size_of::()); + assert_eq!(offset, 1 + 42 * core::mem::size_of::()); } #[test] diff --git a/transaction-view/src/static_account_keys_frame.rs b/transaction-view/src/static_account_keys_frame.rs index 73ea8887ccf8d9..18cce1e116d5ba 100644 --- a/transaction-view/src/static_account_keys_frame.rs +++ b/transaction-view/src/static_account_keys_frame.rs @@ -3,16 +3,16 @@ use { bytes::{advance_offset_for_array, read_byte}, result::{Result, TransactionViewError}, }, - solana_packet::PACKET_DATA_SIZE, + solana_perf::packet::QUIC_MAX_STREAM_SIZE, solana_pubkey::Pubkey, }; -// The packet has a maximum length of 1232 bytes. -// This means the maximum number of 32 byte keys is 38. -// 38 as an min-sized encoded u16 is 1 byte. -// We can simply read this byte, if it's >38 we can return None. +// The packet has a maximum length of 4096 bytes. This means the maximum number +// of 32 byte keys is 128. +// 128 as an min-sized encoded u16 is 1 byte. We can simply read this +// byte, if it's >=128 we can return None. pub const MAX_STATIC_ACCOUNTS_PER_PACKET: u8 = - (PACKET_DATA_SIZE / core::mem::size_of::()) as u8; + (QUIC_MAX_STREAM_SIZE / core::mem::size_of::()) as u8; /// Contains metadata about the static account keys in a transaction packet. #[derive(Debug, Default)] @@ -27,7 +27,7 @@ impl StaticAccountKeysFrame { #[inline(always)] pub(crate) fn try_new(bytes: &[u8], offset: &mut usize) -> Result { // Max size must not have the MSB set so that it is size 1. - const _: () = assert!(MAX_STATIC_ACCOUNTS_PER_PACKET & 0b1000_0000 == 0); + //const _: () = assert!(MAX_STATIC_ACCOUNTS_PER_PACKET & 0b1000_0000 == 0); let num_static_accounts = read_byte(bytes, offset)?; if num_static_accounts == 0 || num_static_accounts > MAX_STATIC_ACCOUNTS_PER_PACKET { @@ -75,9 +75,9 @@ mod tests { let bytes = bincode::serialize(&ShortVec(signatures)).unwrap(); let mut offset = 0; let frame = StaticAccountKeysFrame::try_new(&bytes, &mut offset).unwrap(); - assert_eq!(frame.num_static_accounts, 38); + assert_eq!(frame.num_static_accounts, 128); assert_eq!(frame.offset, 1); - assert_eq!(offset, 1 + 38 * core::mem::size_of::()); + assert_eq!(offset, 1 + 128 * core::mem::size_of::()); } #[test]