| 
						
					 | 
					 | 
					@@ -2,20 +2,22 @@
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::cuda_runtime::PinnedVec;
 | 
					 | 
					 | 
					 | 
					use crate::cuda_runtime::PinnedVec;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::packet::{Packet, Packets};
 | 
					 | 
					 | 
					 | 
					use crate::packet::{Packet, Packets};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::recycler::Recycler;
 | 
					 | 
					 | 
					 | 
					use crate::recycler::Recycler;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::recycler::Reset;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::sigverify::{self, TxOffset};
 | 
					 | 
					 | 
					 | 
					use crate::sigverify::{self, TxOffset};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use crate::sigverify_stage::SigVerifier;
 | 
					 | 
					 | 
					 | 
					use crate::sigverify_stage::SigVerifier;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use bincode::deserialize;
 | 
					 | 
					 | 
					 | 
					use bincode::deserialize;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					use rayon::iter::IndexedParallelIterator;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use rayon::iter::IntoParallelIterator;
 | 
					 | 
					 | 
					 | 
					use rayon::iter::IntoParallelIterator;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					use rayon::iter::IntoParallelRefMutIterator;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use rayon::iter::ParallelIterator;
 | 
					 | 
					 | 
					 | 
					use rayon::iter::ParallelIterator;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use rayon::ThreadPool;
 | 
					 | 
					 | 
					 | 
					use rayon::ThreadPool;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					use sha2::{Digest, Sha512};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					use solana_ed25519_dalek::{Keypair, PublicKey, SecretKey};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use solana_ledger::bank_forks::BankForks;
 | 
					 | 
					 | 
					 | 
					use solana_ledger::bank_forks::BankForks;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use solana_ledger::leader_schedule_cache::LeaderScheduleCache;
 | 
					 | 
					 | 
					 | 
					use solana_ledger::leader_schedule_cache::LeaderScheduleCache;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use solana_ledger::perf_libs;
 | 
					 | 
					 | 
					 | 
					use solana_ledger::perf_libs;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use solana_ledger::shred::ShredType;
 | 
					 | 
					 | 
					 | 
					use solana_ledger::shred::ShredType;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					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::pubkey::Pubkey;
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use solana_sdk::signature::Signature;
 | 
					 | 
					 | 
					 | 
					use solana_sdk::signature::Signature;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::collections::{HashMap, HashSet};
 | 
					 | 
					 | 
					 | 
					use std::collections::{HashMap, HashSet};
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					use std::mem::size_of;
 | 
					 | 
					 | 
					 | 
					use std::mem::size_of;
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -28,7 +30,7 @@ pub struct ShredSigVerifier {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    bank_forks: Arc<RwLock<BankForks>>,
 | 
					 | 
					 | 
					 | 
					    bank_forks: Arc<RwLock<BankForks>>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    leader_schedule_cache: Arc<LeaderScheduleCache>,
 | 
					 | 
					 | 
					 | 
					    leader_schedule_cache: Arc<LeaderScheduleCache>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_offsets: Recycler<TxOffset>,
 | 
					 | 
					 | 
					 | 
					    recycler_offsets: Recycler<TxOffset>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_pubkeys: Recycler<PinnedVec<Pubkey>>,
 | 
					 | 
					 | 
					 | 
					    recycler_keys: Recycler<PinnedVec<[u8; 32]>>,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_out: Recycler<PinnedVec<u8>>,
 | 
					 | 
					 | 
					 | 
					    recycler_out: Recycler<PinnedVec<u8>>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -42,7 +44,7 @@ impl ShredSigVerifier {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            bank_forks,
 | 
					 | 
					 | 
					 | 
					            bank_forks,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            leader_schedule_cache,
 | 
					 | 
					 | 
					 | 
					            leader_schedule_cache,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            recycler_offsets: Recycler::default(),
 | 
					 | 
					 | 
					 | 
					            recycler_offsets: Recycler::default(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            recycler_pubkeys: Recycler::default(),
 | 
					 | 
					 | 
					 | 
					            recycler_keys: Recycler::default(),
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            recycler_out: Recycler::default(),
 | 
					 | 
					 | 
					 | 
					            recycler_out: Recycler::default(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -70,23 +72,22 @@ impl SigVerifier for ShredSigVerifier {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fn verify_batch(&self, mut batches: Vec<Packets>) -> Vec<Packets> {
 | 
					 | 
					 | 
					 | 
					    fn verify_batch(&self, mut batches: Vec<Packets>) -> Vec<Packets> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let r_bank = self.bank_forks.read().unwrap().working_bank();
 | 
					 | 
					 | 
					 | 
					        let r_bank = self.bank_forks.read().unwrap().working_bank();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let slots: HashSet<u64> = Self::read_slots(&batches);
 | 
					 | 
					 | 
					 | 
					        let slots: HashSet<u64> = Self::read_slots(&batches);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let mut leader_slots: HashMap<u64, Pubkey> = slots
 | 
					 | 
					 | 
					 | 
					        let mut leader_slots: HashMap<u64, [u8; 32]> = slots
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .into_iter()
 | 
					 | 
					 | 
					 | 
					            .into_iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .filter_map(|slot| {
 | 
					 | 
					 | 
					 | 
					            .filter_map(|slot| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                Some((
 | 
					 | 
					 | 
					 | 
					                let key = self
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    slot,
 | 
					 | 
					 | 
					 | 
					                    .leader_schedule_cache
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    self.leader_schedule_cache
 | 
					 | 
					 | 
					 | 
					                    .slot_leader_at(slot, Some(&r_bank))?;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        .slot_leader_at(slot, Some(&r_bank))?,
 | 
					 | 
					 | 
					 | 
					                Some((slot, key.to_bytes()))
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                ))
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            })
 | 
					 | 
					 | 
					 | 
					            })
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .collect();
 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        leader_slots.insert(std::u64::MAX, Pubkey::default());
 | 
					 | 
					 | 
					 | 
					        leader_slots.insert(std::u64::MAX, [0u8; 32]);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let r = verify_shreds_gpu(
 | 
					 | 
					 | 
					 | 
					        let r = verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &batches,
 | 
					 | 
					 | 
					 | 
					            &batches,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &self.recycler_offsets,
 | 
					 | 
					 | 
					 | 
					            &self.recycler_offsets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &self.recycler_pubkeys,
 | 
					 | 
					 | 
					 | 
					            &self.recycler_keys,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &self.recycler_out,
 | 
					 | 
					 | 
					 | 
					            &self.recycler_out,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        );
 | 
					 | 
					 | 
					 | 
					        );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        sigverify::mark_disabled(&mut batches, &r);
 | 
					 | 
					 | 
					 | 
					        sigverify::mark_disabled(&mut batches, &r);
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -100,12 +101,6 @@ thread_local!(static PAR_THREAD_POOL: RefCell<ThreadPool> = RefCell::new(rayon::
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    .build()
 | 
					 | 
					 | 
					 | 
					                    .build()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    .unwrap()));
 | 
					 | 
					 | 
					 | 
					                    .unwrap()));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					impl Reset for PinnedVec<Pubkey> {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fn reset(&mut self) {
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        self.resize(0, Pubkey::default());
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/// Assuming layout is
 | 
					 | 
					 | 
					 | 
					/// Assuming layout is
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/// signature: Signature
 | 
					 | 
					 | 
					 | 
					/// signature: Signature
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/// signed_msg: {
 | 
					 | 
					 | 
					 | 
					/// signed_msg: {
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -114,7 +109,7 @@ impl Reset for PinnedVec<Pubkey> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					///   ...
 | 
					 | 
					 | 
					 | 
					///   ...
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/// }
 | 
					 | 
					 | 
					 | 
					/// }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					/// Signature is the first thing in the packet, and slot is the first thing in the signed message.
 | 
					 | 
					 | 
					 | 
					/// Signature is the first thing in the packet, and slot is the first thing in the signed message.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn verify_shred_cpu(packet: &Packet, slot_leaders: &HashMap<u64, Pubkey>) -> Option<u8> {
 | 
					 | 
					 | 
					 | 
					fn verify_shred_cpu(packet: &Packet, slot_leaders: &HashMap<u64, [u8; 32]>) -> Option<u8> {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let sig_start = 0;
 | 
					 | 
					 | 
					 | 
					    let sig_start = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let sig_end = size_of::<Signature>();
 | 
					 | 
					 | 
					 | 
					    let sig_end = size_of::<Signature>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let slot_start = sig_end + size_of::<ShredType>();
 | 
					 | 
					 | 
					 | 
					    let slot_start = sig_end + size_of::<ShredType>();
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -127,19 +122,19 @@ fn verify_shred_cpu(packet: &Packet, slot_leaders: &HashMap<u64, Pubkey>) -> Opt
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let slot: u64 = deserialize(&packet.data[slot_start..slot_end]).ok()?;
 | 
					 | 
					 | 
					 | 
					    let slot: u64 = deserialize(&packet.data[slot_start..slot_end]).ok()?;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("slot {}", slot);
 | 
					 | 
					 | 
					 | 
					    trace!("slot {}", slot);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let pubkey: &Pubkey = slot_leaders.get(&slot)?;
 | 
					 | 
					 | 
					 | 
					    let pubkey = slot_leaders.get(&slot)?;
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if packet.meta.size < sig_end {
 | 
					 | 
					 | 
					 | 
					    if packet.meta.size < sig_end {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return Some(0);
 | 
					 | 
					 | 
					 | 
					        return Some(0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let signature = Signature::new(&packet.data[sig_start..sig_end]);
 | 
					 | 
					 | 
					 | 
					    let signature = Signature::new(&packet.data[sig_start..sig_end]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("signature {}", signature);
 | 
					 | 
					 | 
					 | 
					    trace!("signature {}", signature);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    if !signature.verify(pubkey.as_ref(), &packet.data[msg_start..msg_end]) {
 | 
					 | 
					 | 
					 | 
					    if !signature.verify(pubkey, &packet.data[msg_start..msg_end]) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        return Some(0);
 | 
					 | 
					 | 
					 | 
					        return Some(0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    Some(1)
 | 
					 | 
					 | 
					 | 
					    Some(1)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn verify_shreds_cpu(batches: &[Packets], slot_leaders: &HashMap<u64, Pubkey>) -> Vec<Vec<u8>> {
 | 
					 | 
					 | 
					 | 
					fn verify_shreds_cpu(batches: &[Packets], slot_leaders: &HashMap<u64, [u8; 32]>) -> Vec<Vec<u8>> {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use rayon::prelude::*;
 | 
					 | 
					 | 
					 | 
					    use rayon::prelude::*;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let count = sigverify::batch_size(batches);
 | 
					 | 
					 | 
					 | 
					    let count = sigverify::batch_size(batches);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    debug!("CPU SHRED ECDSA for {}", count);
 | 
					 | 
					 | 
					 | 
					    debug!("CPU SHRED ECDSA for {}", count);
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -149,7 +144,7 @@ fn verify_shreds_cpu(batches: &[Packets], slot_leaders: &HashMap<u64, Pubkey>) -
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .into_par_iter()
 | 
					 | 
					 | 
					 | 
					                .into_par_iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .map(|p| {
 | 
					 | 
					 | 
					 | 
					                .map(|p| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                    p.packets
 | 
					 | 
					 | 
					 | 
					                    p.packets
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        .par_iter()
 | 
					 | 
					 | 
					 | 
					                        .iter()
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        .map(|p| verify_shred_cpu(p, slot_leaders).unwrap_or(0))
 | 
					 | 
					 | 
					 | 
					                        .map(|p| verify_shred_cpu(p, slot_leaders).unwrap_or(0))
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        .collect()
 | 
					 | 
					 | 
					 | 
					                        .collect()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                })
 | 
					 | 
					 | 
					 | 
					                })
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -160,14 +155,17 @@ fn verify_shreds_cpu(batches: &[Packets], slot_leaders: &HashMap<u64, Pubkey>) -
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    rv
 | 
					 | 
					 | 
					 | 
					    rv
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn shred_gpu_pubkeys(
 | 
					 | 
					 | 
					 | 
					fn slot_key_data_for_gpu<
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    T: Sync + Sized + Default + std::fmt::Debug + Eq + std::hash::Hash + Clone + Copy,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					>(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    offset_start: usize,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    batches: &[Packets],
 | 
					 | 
					 | 
					 | 
					    batches: &[Packets],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    slot_leaders: &HashMap<u64, Pubkey>,
 | 
					 | 
					 | 
					 | 
					    slot_keys: &HashMap<u64, T>,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_pubkeys: &Recycler<PinnedVec<Pubkey>>,
 | 
					 | 
					 | 
					 | 
					    recycler_keys: &Recycler<PinnedVec<T>>,
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					) -> (PinnedVec<Pubkey>, TxOffset, usize) {
 | 
					 | 
					 | 
					 | 
					) -> (PinnedVec<T>, TxOffset, usize) {
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //TODO: mark Pubkey::default shreds as failed after the GPU returns
 | 
					 | 
					 | 
					 | 
					    //TODO: mark Pubkey::default shreds as failed after the GPU returns
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    assert_eq!(slot_leaders.get(&std::u64::MAX), Some(&Pubkey::default()));
 | 
					 | 
					 | 
					 | 
					    assert_eq!(slot_keys.get(&std::u64::MAX), Some(&T::default()));
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let slots: Vec<Vec<u64>> = PAR_THREAD_POOL.with(|thread_pool| {
 | 
					 | 
					 | 
					 | 
					    let slots: Vec<Vec<u64>> = PAR_THREAD_POOL.with(|thread_pool| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        thread_pool.borrow().install(|| {
 | 
					 | 
					 | 
					 | 
					        thread_pool.borrow().install(|| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            batches
 | 
					 | 
					 | 
					 | 
					            batches
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -184,7 +182,7 @@ fn shred_gpu_pubkeys(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                            let slot: Option<u64> =
 | 
					 | 
					 | 
					 | 
					                            let slot: Option<u64> =
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                deserialize(&packet.data[slot_start..slot_end]).ok();
 | 
					 | 
					 | 
					 | 
					                                deserialize(&packet.data[slot_start..slot_end]).ok();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                            match slot {
 | 
					 | 
					 | 
					 | 
					                            match slot {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                Some(slot) if slot_leaders.get(&slot).is_some() => slot,
 | 
					 | 
					 | 
					 | 
					                                Some(slot) if slot_keys.get(&slot).is_some() => slot,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                                _ => std::u64::MAX,
 | 
					 | 
					 | 
					 | 
					                                _ => std::u64::MAX,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                            }
 | 
					 | 
					 | 
					 | 
					                            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                        })
 | 
					 | 
					 | 
					 | 
					                        })
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -193,20 +191,20 @@ fn shred_gpu_pubkeys(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .collect()
 | 
					 | 
					 | 
					 | 
					                .collect()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        })
 | 
					 | 
					 | 
					 | 
					        })
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    });
 | 
					 | 
					 | 
					 | 
					    });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let mut keys_to_slots: HashMap<Pubkey, Vec<u64>> = HashMap::new();
 | 
					 | 
					 | 
					 | 
					    let mut keys_to_slots: HashMap<T, Vec<u64>> = HashMap::new();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for batch in slots.iter() {
 | 
					 | 
					 | 
					 | 
					    for batch in slots.iter() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for slot in batch.iter() {
 | 
					 | 
					 | 
					 | 
					        for slot in batch.iter() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let key = slot_leaders.get(slot).unwrap();
 | 
					 | 
					 | 
					 | 
					            let key = slot_keys.get(slot).unwrap();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            keys_to_slots
 | 
					 | 
					 | 
					 | 
					            keys_to_slots
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .entry(*key)
 | 
					 | 
					 | 
					 | 
					                .entry(*key)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .or_insert_with(|| vec![])
 | 
					 | 
					 | 
					 | 
					                .or_insert_with(|| vec![])
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                .push(*slot);
 | 
					 | 
					 | 
					 | 
					                .push(*slot);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let mut pubkeys: PinnedVec<Pubkey> = recycler_pubkeys.allocate("shred_gpu_pubkeys");
 | 
					 | 
					 | 
					 | 
					    let mut keyvec = recycler_keys.allocate("shred_gpu_pubkeys");
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let mut slot_to_key_ix = HashMap::new();
 | 
					 | 
					 | 
					 | 
					    let mut slot_to_key_ix = HashMap::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for (i, (k, slots)) in keys_to_slots.iter().enumerate() {
 | 
					 | 
					 | 
					 | 
					    for (i, (k, slots)) in keys_to_slots.iter().enumerate() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        pubkeys.push(*k);
 | 
					 | 
					 | 
					 | 
					        keyvec.push(*k);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for s in slots {
 | 
					 | 
					 | 
					 | 
					        for s in slots {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            slot_to_key_ix.insert(s, i);
 | 
					 | 
					 | 
					 | 
					            slot_to_key_ix.insert(s, i);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -214,33 +212,34 @@ fn shred_gpu_pubkeys(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let mut offsets = recycler_offsets.allocate("shred_offsets");
 | 
					 | 
					 | 
					 | 
					    let mut offsets = recycler_offsets.allocate("shred_offsets");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    slots.iter().for_each(|packet_slots| {
 | 
					 | 
					 | 
					 | 
					    slots.iter().for_each(|packet_slots| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        packet_slots.iter().for_each(|slot| {
 | 
					 | 
					 | 
					 | 
					        packet_slots.iter().for_each(|slot| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            offsets.push((slot_to_key_ix.get(slot).unwrap() * size_of::<Pubkey>()) as u32);
 | 
					 | 
					 | 
					 | 
					            offsets
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                .push((offset_start + (slot_to_key_ix.get(slot).unwrap() * size_of::<T>())) as u32);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        });
 | 
					 | 
					 | 
					 | 
					        });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    });
 | 
					 | 
					 | 
					 | 
					    });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //HACK: Pubkeys vector is passed along as a `Packets` buffer to the GPU
 | 
					 | 
					 | 
					 | 
					    //HACK: Pubkeys vector is passed along as a `Packets` buffer to the GPU
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //TODO: GPU needs a more opaque interface, which can handle variable sized structures for data
 | 
					 | 
					 | 
					 | 
					    //TODO: GPU needs a more opaque interface, which can handle variable sized structures for data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //Pad the Pubkeys buffer such that it is bigger than a buffer of Packet sized elems
 | 
					 | 
					 | 
					 | 
					    //Pad the Pubkeys buffer such that it is bigger than a buffer of Packet sized elems
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let num_in_packets =
 | 
					 | 
					 | 
					 | 
					    let num_in_packets =
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        (pubkeys.len() * size_of::<Pubkey>() + (size_of::<Packet>() - 1)) / size_of::<Packet>();
 | 
					 | 
					 | 
					 | 
					        (keyvec.len() * size_of::<T>() + (size_of::<Packet>() - 1)) / size_of::<Packet>();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("num_in_packets {}", num_in_packets);
 | 
					 | 
					 | 
					 | 
					    trace!("num_in_packets {}", num_in_packets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //number of bytes missing
 | 
					 | 
					 | 
					 | 
					    //number of bytes missing
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let missing = num_in_packets * size_of::<Packet>() - pubkeys.len() * size_of::<Pubkey>();
 | 
					 | 
					 | 
					 | 
					    let missing = num_in_packets * size_of::<Packet>() - keyvec.len() * size_of::<T>();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("missing {}", missing);
 | 
					 | 
					 | 
					 | 
					    trace!("missing {}", missing);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //extra Pubkeys needed to fill the buffer
 | 
					 | 
					 | 
					 | 
					    //extra Pubkeys needed to fill the buffer
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let extra = (missing + size_of::<Pubkey>() - 1) / size_of::<Pubkey>();
 | 
					 | 
					 | 
					 | 
					    let extra = (missing + size_of::<T>() - 1) / size_of::<T>();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("extra {}", extra);
 | 
					 | 
					 | 
					 | 
					    trace!("extra {}", extra);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("pubkeys {}", pubkeys.len());
 | 
					 | 
					 | 
					 | 
					    trace!("keyvec {}", keyvec.len());
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    for _ in 0..extra {
 | 
					 | 
					 | 
					 | 
					    for _ in 0..extra {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        pubkeys.push(Pubkey::default());
 | 
					 | 
					 | 
					 | 
					        keyvec.push(T::default());
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        trace!("pubkeys {}", pubkeys.len());
 | 
					 | 
					 | 
					 | 
					        trace!("keyvec {}", keyvec.len());
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("pubkeys {:?}", pubkeys);
 | 
					 | 
					 | 
					 | 
					    trace!("keyvec {:?}", keyvec);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("offsets {:?}", offsets);
 | 
					 | 
					 | 
					 | 
					    trace!("offsets {:?}", offsets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    (pubkeys, offsets, num_in_packets)
 | 
					 | 
					 | 
					 | 
					    (keyvec, offsets, num_in_packets)
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn shred_gpu_offsets(
 | 
					 | 
					 | 
					 | 
					fn shred_gpu_offsets(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    mut pubkeys_end: u32,
 | 
					 | 
					 | 
					 | 
					    mut pubkeys_end: usize,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    batches: &[Packets],
 | 
					 | 
					 | 
					 | 
					    batches: &[Packets],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					) -> (TxOffset, TxOffset, TxOffset, Vec<Vec<u32>>) {
 | 
					 | 
					 | 
					 | 
					) -> (TxOffset, TxOffset, TxOffset, Vec<Vec<u32>>) {
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -252,19 +251,19 @@ fn shred_gpu_offsets(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let mut sig_lens = Vec::new();
 | 
					 | 
					 | 
					 | 
					        let mut sig_lens = Vec::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        for packet in &batch.packets {
 | 
					 | 
					 | 
					 | 
					        for packet in &batch.packets {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let sig_start = pubkeys_end;
 | 
					 | 
					 | 
					 | 
					            let sig_start = pubkeys_end;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let sig_end = sig_start + size_of::<Signature>() as u32;
 | 
					 | 
					 | 
					 | 
					            let sig_end = sig_start + size_of::<Signature>();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let msg_start = sig_end;
 | 
					 | 
					 | 
					 | 
					            let msg_start = sig_end;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let msg_end = sig_start + packet.meta.size as u32;
 | 
					 | 
					 | 
					 | 
					            let msg_end = sig_start + packet.meta.size;
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            signature_offsets.push(sig_start);
 | 
					 | 
					 | 
					 | 
					            signature_offsets.push(sig_start as u32);
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            msg_start_offsets.push(msg_start);
 | 
					 | 
					 | 
					 | 
					            msg_start_offsets.push(msg_start as u32);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            let msg_size = if msg_end < msg_start {
 | 
					 | 
					 | 
					 | 
					            let msg_size = if msg_end < msg_start {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                0
 | 
					 | 
					 | 
					 | 
					                0
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            } else {
 | 
					 | 
					 | 
					 | 
					            } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					                msg_end - msg_start
 | 
					 | 
					 | 
					 | 
					                msg_end - msg_start
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            };
 | 
					 | 
					 | 
					 | 
					            };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            msg_sizes.push(msg_size);
 | 
					 | 
					 | 
					 | 
					            msg_sizes.push(msg_size as u32);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            sig_lens.push(1);
 | 
					 | 
					 | 
					 | 
					            sig_lens.push(1);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            pubkeys_end += size_of::<Packet>() as u32;
 | 
					 | 
					 | 
					 | 
					            pubkeys_end += size_of::<Packet>();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        }
 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        v_sig_lens.push(sig_lens);
 | 
					 | 
					 | 
					 | 
					        v_sig_lens.push(sig_lens);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -273,9 +272,9 @@ fn shred_gpu_offsets(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					fn verify_shreds_gpu(
 | 
					 | 
					 | 
					 | 
					fn verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    batches: &[Packets],
 | 
					 | 
					 | 
					 | 
					    batches: &[Packets],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    slot_leaders: &HashMap<u64, Pubkey>,
 | 
					 | 
					 | 
					 | 
					    slot_leaders: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_pubkeys: &Recycler<PinnedVec<Pubkey>>,
 | 
					 | 
					 | 
					 | 
					    recycler_pubkeys: &Recycler<PinnedVec<[u8; 32]>>,
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    recycler_out: &Recycler<PinnedVec<u8>>,
 | 
					 | 
					 | 
					 | 
					    recycler_out: &Recycler<PinnedVec<u8>>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					) -> Vec<Vec<u8>> {
 | 
					 | 
					 | 
					 | 
					) -> Vec<Vec<u8>> {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let api = perf_libs::api();
 | 
					 | 
					 | 
					 | 
					    let api = perf_libs::api();
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -288,10 +287,10 @@ fn verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let mut rvs = Vec::new();
 | 
					 | 
					 | 
					 | 
					    let mut rvs = Vec::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let count = sigverify::batch_size(batches);
 | 
					 | 
					 | 
					 | 
					    let count = sigverify::batch_size(batches);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let (pubkeys, pubkey_offsets, mut num_packets) =
 | 
					 | 
					 | 
					 | 
					    let (pubkeys, pubkey_offsets, mut num_packets) =
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        shred_gpu_pubkeys(batches, slot_leaders, recycler_offsets, recycler_pubkeys);
 | 
					 | 
					 | 
					 | 
					        slot_key_data_for_gpu(0, batches, slot_leaders, recycler_offsets, recycler_pubkeys);
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //HACK: Pubkeys vector is passed along as a `Packets` buffer to the GPU
 | 
					 | 
					 | 
					 | 
					    //HACK: Pubkeys vector is passed along as a `Packets` buffer to the GPU
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    //TODO: GPU needs a more opaque interface, which can handle variable sized structures for data
 | 
					 | 
					 | 
					 | 
					    //TODO: GPU needs a more opaque interface, which can handle variable sized structures for data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let pubkeys_len = (num_packets * size_of::<Packet>()) as u32;
 | 
					 | 
					 | 
					 | 
					    let pubkeys_len = num_packets * size_of::<Packet>();
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("num_packets: {}", num_packets);
 | 
					 | 
					 | 
					 | 
					    trace!("num_packets: {}", num_packets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    trace!("pubkeys_len: {}", pubkeys_len);
 | 
					 | 
					 | 
					 | 
					    trace!("pubkeys_len: {}", pubkeys_len);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    let (signature_offsets, msg_start_offsets, msg_sizes, v_sig_lens) =
 | 
					 | 
					 | 
					 | 
					    let (signature_offsets, msg_start_offsets, msg_sizes, v_sig_lens) =
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -355,6 +354,217 @@ fn verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    rvs
 | 
					 | 
					 | 
					 | 
					    rvs
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					}
 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/// Assuming layout is
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/// signature: Signature
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/// signed_msg: {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					///   type: ShredType
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					///   slot: u64,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					///   ...
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/// }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					/// Signature is the first thing in the packet, and slot is the first thing in the signed message.
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					fn sign_shred_cpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    packet: &mut Packet,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    slot_leaders_pubkeys: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    slot_leaders_privkeys: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let sig_start = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let sig_end = sig_start + size_of::<Signature>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let slot_start = sig_end + size_of::<ShredType>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let slot_end = slot_start + size_of::<u64>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let msg_start = sig_end;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let msg_end = packet.meta.size;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("slot start and end {} {}", slot_start, slot_end);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    assert!(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        packet.meta.size >= slot_end,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        "packet is not large enough for a slot"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let slot: u64 =
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        deserialize(&packet.data[slot_start..slot_end]).expect("can't deserialize slot");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("slot {}", slot);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let pubkey = slot_leaders_pubkeys
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .get(&slot)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .expect("slot pubkey missing");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let privkey = slot_leaders_privkeys
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .get(&slot)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .expect("slot privkey missing");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let keypair = Keypair {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        secret: SecretKey::from_bytes(&privkey[0..32]).expect("dalek privkey parser"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        public: PublicKey::from_bytes(&pubkey[0..32]).expect("dalek pubkey parser"),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    };
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    assert!(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        packet.meta.size >= sig_end,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        "packet is not large enough for a signature"
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let signature = keypair.sign(&packet.data[msg_start..msg_end]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("signature {:?}", signature);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    packet.data[0..sig_end].copy_from_slice(&signature.to_bytes());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					fn sign_shreds_cpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    batches: &mut [Packets],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    slot_leaders_pubkeys: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    slot_leaders_privkeys: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    use rayon::prelude::*;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let count = sigverify::batch_size(batches);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    debug!("CPU SHRED ECDSA for {}", count);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    PAR_THREAD_POOL.with(|thread_pool| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        thread_pool.borrow().install(|| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            batches.par_iter_mut().for_each(|p| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                p.packets.iter_mut().for_each(|mut p| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    sign_shred_cpu(&mut p, slot_leaders_pubkeys, slot_leaders_privkeys)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        })
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    inc_new_counter_debug!("ed25519_shred_verify_cpu", count);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					pub fn sign_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    batches: &mut [Packets],
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    slot_leaders_pubkeys: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    slot_leaders_privkeys: &HashMap<u64, [u8; 32]>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_offsets: &Recycler<TxOffset>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_pubkeys: &Recycler<PinnedVec<[u8; 32]>>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_secrets: &Recycler<PinnedVec<Signature>>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_out: &Recycler<PinnedVec<u8>>,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					) {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let sig_size = size_of::<Signature>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let api = perf_libs::api();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    if api.is_none() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        return sign_shreds_cpu(batches, slot_leaders_pubkeys, slot_leaders_privkeys);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let slot_leaders_secrets: HashMap<u64, Signature> = slot_leaders_privkeys
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .map(|(k, v)| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            if *k == std::u64::MAX {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                (*k, Signature::default())
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            } else {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                let mut hasher = Sha512::default();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                hasher.input(&v);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                let mut result = hasher.result();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                result[0] &= 248;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                result[31] &= 63;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                result[31] |= 64;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                let sig = Signature::new(result.as_slice());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                (*k, sig)
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        })
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let api = api.unwrap();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let mut elems = Vec::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let count = sigverify::batch_size(batches);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let mut offset: usize = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let mut num_packets = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let (pubkeys, pubkey_offsets, num_pubkey_packets) = slot_key_data_for_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        offset,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batches,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        slot_leaders_pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        recycler_offsets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        recycler_pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    offset += num_pubkey_packets * size_of::<Packet>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    num_packets += num_pubkey_packets;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("offset: {}", offset);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let (secrets, secret_offsets, num_secret_packets) = slot_key_data_for_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        offset,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batches,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        &slot_leaders_secrets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        recycler_offsets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        recycler_secrets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    offset += num_secret_packets * size_of::<Packet>();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    num_packets += num_secret_packets;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    //HACK: Pubkeys vector is passed along as a `Packets` buffer to the GPU
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    //TODO: GPU needs a more opaque interface, which can handle variable sized structures for data
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("offset: {}", offset);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let (signature_offsets, msg_start_offsets, msg_sizes, _v_sig_lens) =
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        shred_gpu_offsets(offset, batches, recycler_offsets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let total_sigs = signature_offsets.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let mut signatures_out = recycler_out.allocate("ed25519 signatures");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    signatures_out.resize(total_sigs * sig_size, 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    elems.push(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        perf_libs::Elems {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            #![allow(clippy::cast_ptr_alignment)]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            elems: pubkeys.as_ptr() as *const solana_sdk::packet::Packet,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            num: num_pubkey_packets as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        },
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    elems.push(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        perf_libs::Elems {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            #![allow(clippy::cast_ptr_alignment)]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            elems: secrets.as_ptr() as *const solana_sdk::packet::Packet,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            num: num_secret_packets as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        },
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    for p in batches.iter() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        elems.push(perf_libs::Elems {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            elems: p.packets.as_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            num: p.packets.len() as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let mut v = Vec::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        v.resize(p.packets.len(), 0);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        num_packets += p.packets.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("Starting verify num packets: {}", num_packets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("elem len: {}", elems.len() as u32);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("packet sizeof: {}", size_of::<Packet>() as u32);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    const USE_NON_DEFAULT_STREAM: u8 = 1;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    unsafe {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let res = (api.ed25519_sign_many)(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            elems.as_mut_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            elems.len() as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            size_of::<Packet>() as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            num_packets as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            total_sigs as u32,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            msg_sizes.as_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            pubkey_offsets.as_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            secret_offsets.as_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            msg_start_offsets.as_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            signatures_out.as_mut_ptr(),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            USE_NON_DEFAULT_STREAM,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        if res != 0 {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            trace!("RETURN!!!: {}", res);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    trace!("done sign");
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    let mut sizes: Vec<usize> = vec![0];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    sizes.extend(batches.iter().map(|b| b.packets.len()));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    PAR_THREAD_POOL.with(|thread_pool| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        thread_pool.borrow().install(|| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            batches
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                .par_iter_mut()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                .enumerate()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                .for_each(|(batch_ix, batch)| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    let num_packets = sizes[batch_ix];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                    batch
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        .packets
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        .iter_mut()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        .enumerate()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        .for_each(|(packet_ix, packet)| {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                            let sig_ix = packet_ix + num_packets;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                            let sig_start = sig_ix * sig_size;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                            let sig_end = sig_start + sig_size;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                            packet.data[0..sig_size]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                                .copy_from_slice(&signatures_out[sig_start..sig_end]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                        });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					                });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    });
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    inc_new_counter_debug!("ed25519_shred_sign_gpu", count);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_out.recycle(signatures_out);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_offsets.recycle(signature_offsets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_offsets.recycle(pubkey_offsets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_offsets.recycle(msg_sizes);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_offsets.recycle(msg_start_offsets);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    recycler_pubkeys.recycle(pubkeys);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					}
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					#[cfg(test)]
 | 
					 | 
					 | 
					 | 
					#[cfg(test)]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					pub mod tests {
 | 
					 | 
					 | 
					 | 
					pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    use super::*;
 | 
					 | 
					 | 
					 | 
					    use super::*;
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -375,12 +585,18 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        packet.data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
					 | 
					 | 
					 | 
					        packet.data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        packet.meta.size = shred.payload.len();
 | 
					 | 
					 | 
					 | 
					        packet.meta.size = shred.payload.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey())].iter().cloned().collect();
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey().to_bytes())]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shred_cpu(&packet, &leader_slots);
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shred_cpu(&packet, &leader_slots);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, Some(1));
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, Some(1));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let wrong_keypair = Keypair::new();
 | 
					 | 
					 | 
					 | 
					        let wrong_keypair = Keypair::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, wrong_keypair.pubkey())].iter().cloned().collect();
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, wrong_keypair.pubkey().to_bytes())]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shred_cpu(&packet, &leader_slots);
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shred_cpu(&packet, &leader_slots);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, Some(0));
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, Some(0));
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -401,12 +617,18 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = shred.payload.len();
 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = shred.payload.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey())].iter().cloned().collect();
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey().to_bytes())]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![1]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![1]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let wrong_keypair = Keypair::new();
 | 
					 | 
					 | 
					 | 
					        let wrong_keypair = Keypair::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, wrong_keypair.pubkey())].iter().cloned().collect();
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, wrong_keypair.pubkey().to_bytes())]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -414,7 +636,10 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey())].iter().cloned().collect();
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey().to_bytes())]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = 0;
 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &leader_slots);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -436,10 +661,13 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = shred.payload.len();
 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = shred.payload.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey()), (std::u64::MAX, Pubkey::default())]
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .iter()
 | 
					 | 
					 | 
					 | 
					            (slot, keypair.pubkey().to_bytes()),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .cloned()
 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .collect();
 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &batch,
 | 
					 | 
					 | 
					 | 
					            &batch,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -451,8 +679,8 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let wrong_keypair = Keypair::new();
 | 
					 | 
					 | 
					 | 
					        let wrong_keypair = Keypair::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            (slot, wrong_keypair.pubkey()),
 | 
					 | 
					 | 
					 | 
					            (slot, wrong_keypair.pubkey().to_bytes()),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            (std::u64::MAX, Pubkey::default()),
 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        ]
 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        .iter()
 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        .cloned()
 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -466,10 +694,7 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        );
 | 
					 | 
					 | 
					 | 
					        );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(std::u64::MAX, Pubkey::default())]
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [(std::u64::MAX, [0u8; 32])].iter().cloned().collect();
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .iter()
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .cloned()
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .collect();
 | 
					 | 
					 | 
					 | 
					 | 
				
			
			
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &batch,
 | 
					 | 
					 | 
					 | 
					            &batch,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -480,10 +705,13 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = 0;
 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = 0;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let leader_slots = [(slot, keypair.pubkey()), (std::u64::MAX, Pubkey::default())]
 | 
					 | 
					 | 
					 | 
					        let leader_slots = [
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .iter()
 | 
					 | 
					 | 
					 | 
					            (slot, keypair.pubkey().to_bytes()),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .cloned()
 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
				
				
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            .collect();
 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
				
				
			
		
	
		
		
	
		
		
	
		
		
	
		
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &batch,
 | 
					 | 
					 | 
					 | 
					            &batch,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
					 | 
					 | 
					 | 
					            &leader_slots,
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					@@ -494,6 +722,101 @@ pub mod tests {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    }
 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					
 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    #[test]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fn test_sigverify_shreds_sign_gpu() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        solana_logger::setup();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let recycler_offsets = Recycler::default();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let recycler_pubkeys = Recycler::default();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let recycler_secrets = Recycler::default();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let recycler_out = Recycler::default();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let mut batch = [Packets::default()];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let slot = 0xdeadc0de;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let keypair = Keypair::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let shred = Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batch[0].packets.resize(1, Packet::default());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = shred.payload.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let pubkeys = [
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (slot, keypair.pubkey().to_bytes()),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let privkeys = [
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (slot, keypair.secret.to_bytes()),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        //unsigned
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &batch,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_offsets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_out,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        //signed
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sign_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &mut batch,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &privkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_offsets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_secrets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_out,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &pubkeys);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![1]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_gpu(
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &batch,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_offsets,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_pubkeys,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            &recycler_out,
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        );
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![1]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    #[test]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    fn test_sigverify_shreds_sign_cpu() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        solana_logger::setup();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let mut batch = [Packets::default()];
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let slot = 0xdeadc0de;
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let keypair = Keypair::new();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let shred = Shred::new_from_data(slot, 0xc0de, 0xdead, Some(&[1, 2, 3, 4]), true, true);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batch[0].packets.resize(1, Packet::default());
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].data[0..shred.payload.len()].copy_from_slice(&shred.payload);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        batch[0].packets[0].meta.size = shred.payload.len();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let pubkeys = [
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (slot, keypair.pubkey().to_bytes()),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let privkeys = [
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (slot, keypair.secret.to_bytes()),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					            (std::u64::MAX, [0u8; 32]),
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        ]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .iter()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .cloned()
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        .collect();
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        //unsigned
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &pubkeys);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![0]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        //signed
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        sign_shreds_cpu(&mut batch, &pubkeys, &privkeys);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        let rv = verify_shreds_cpu(&batch, &pubkeys);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					        assert_eq!(rv, vec![vec![1]]);
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					    }
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					 | 
					
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    #[test]
 | 
					 | 
					 | 
					 | 
					    #[test]
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					    fn test_sigverify_shreds_read_slots() {
 | 
					 | 
					 | 
					 | 
					    fn test_sigverify_shreds_read_slots() {
 | 
				
			
			
		
	
		
		
			
				
					
					 | 
					 | 
					 | 
					        solana_logger::setup();
 | 
					 | 
					 | 
					 | 
					        solana_logger::setup();
 | 
				
			
			
		
	
	
		
		
			
				
					
					| 
						
					 | 
					 | 
					 
 |