From e5d4cbf883de4e60eae8ec9e49956f0658fa52d0 Mon Sep 17 00:00:00 2001 From: Stephen Akridge Date: Fri, 21 Dec 2018 11:00:13 -0800 Subject: [PATCH] Use helper function for getting segment index, remove vote code --- programs/native/storage/src/lib.rs | 9 +- sdk/src/storage_program.rs | 6 ++ src/chacha_cuda.rs | 16 ++-- src/replicator.rs | 6 +- src/storage_stage.rs | 130 +++++++++-------------------- 5 files changed, 61 insertions(+), 106 deletions(-) diff --git a/programs/native/storage/src/lib.rs b/programs/native/storage/src/lib.rs index 41afcb89afe0f9..d633bc67a3eabd 100644 --- a/programs/native/storage/src/lib.rs +++ b/programs/native/storage/src/lib.rs @@ -11,7 +11,6 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::solana_entrypoint; use solana_sdk::storage_program::*; -pub const ENTRIES_PER_SEGMENT: u64 = 16; pub const TOTAL_VALIDATOR_REWARDS: u64 = 1000; pub const TOTAL_REPLICATOR_REWARDS: u64 = 1000; @@ -74,9 +73,9 @@ fn entrypoint( entry_height, signature, } => { - let segment_index = (entry_height / ENTRIES_PER_SEGMENT) as usize; + let segment_index = get_segment_from_entry(entry_height); let current_segment_index = - (storage_account_state.entry_height / ENTRIES_PER_SEGMENT) as usize; + get_segment_from_entry(storage_account_state.entry_height); if segment_index >= current_segment_index { return Err(ProgramError::InvalidArgument); } @@ -130,7 +129,7 @@ fn entrypoint( return Err(ProgramError::InvalidArgument); } - let segment_index = (entry_height / ENTRIES_PER_SEGMENT) as usize; + let segment_index = get_segment_from_entry(entry_height); if storage_account_state.previous_proofs[segment_index].len() != proof_mask.len() { return Err(ProgramError::InvalidArgument); } @@ -149,7 +148,7 @@ fn entrypoint( storage_account_state.lockout_validations[segment_index].push(info); } StorageProgram::ClaimStorageReward { entry_height } => { - let claims_index = (entry_height / ENTRIES_PER_SEGMENT) as usize; + let claims_index = get_segment_from_entry(entry_height); let account_key = keyed_accounts[0].signer_key().unwrap(); let mut num_validations = 0; let mut total_validations = 0; diff --git a/sdk/src/storage_program.rs b/sdk/src/storage_program.rs index 7bec0ee3b5bdce..fba4d86170c9bd 100644 --- a/sdk/src/storage_program.rs +++ b/sdk/src/storage_program.rs @@ -4,6 +4,12 @@ use crate::signature::Keypair; use crate::signature::Signature; use crate::transaction::Transaction; +pub const ENTRIES_PER_SEGMENT: u64 = 16; + +pub fn get_segment_from_entry(entry_height: u64) -> usize { + (entry_height / ENTRIES_PER_SEGMENT) as usize +} + #[derive(Debug, Serialize, Deserialize, Clone)] pub enum ProofStatus { Valid, diff --git a/src/chacha_cuda.rs b/src/chacha_cuda.rs index 8bfcbcfe42f06c..2ac65ad298177f 100644 --- a/src/chacha_cuda.rs +++ b/src/chacha_cuda.rs @@ -7,7 +7,7 @@ use solana_sdk::hash::Hash; use std::io; use std::mem::size_of; -use crate::storage_stage::ENTRIES_PER_SEGMENT; +use solana_sdk::storage_program::ENTRIES_PER_SEGMENT; // Encrypt a file with multiple starting IV states, determined by ivecs.len() // @@ -15,7 +15,7 @@ use crate::storage_stage::ENTRIES_PER_SEGMENT; // and return the vec of sha states pub fn chacha_cbc_encrypt_file_many_keys( in_path: &str, - slice: u64, + segment: u64, ivecs: &mut [u8], samples: &[u64], ) -> io::Result> { @@ -36,7 +36,7 @@ pub fn chacha_cbc_encrypt_file_many_keys( let mut sha_states = vec![0; num_keys * size_of::()]; let mut int_sha_states = vec![0; num_keys * 112]; let keys: Vec = vec![0; num_keys * CHACHA_KEY_SIZE]; // keys not used ATM, uniqueness comes from IV - let mut entry = slice; + let mut entry = segment; let mut total_entries = 0; let mut total_entry_len = 0; let mut time: f32 = 0.0; @@ -51,8 +51,8 @@ pub fn chacha_cbc_encrypt_file_many_keys( ) { Ok((num_entries, entry_len)) => { info!( - "encrypting slice: {} num_entries: {} entry_len: {}", - slice, num_entries, entry_len + "encrypting segment: {} num_entries: {} entry_len: {}", + segment, num_entries, entry_len ); let entry_len_usz = entry_len as usize; unsafe { @@ -74,10 +74,10 @@ pub fn chacha_cbc_encrypt_file_many_keys( total_entries += num_entries; entry += num_entries; debug!( - "total entries: {} entry: {} slice: {} entries_per_slice: {}", - total_entries, entry, slice, ENTRIES_PER_SEGMENT + "total entries: {} entry: {} segment: {} entries_per_segment: {}", + total_entries, entry, segment, ENTRIES_PER_SEGMENT ); - if (entry - slice) >= ENTRIES_PER_SEGMENT { + if (entry - segment) >= ENTRIES_PER_SEGMENT { break; } } diff --git a/src/replicator.rs b/src/replicator.rs index 7ee886c22dfe93..87dfb74b5127cb 100644 --- a/src/replicator.rs +++ b/src/replicator.rs @@ -10,7 +10,6 @@ use crate::ledger::LEDGER_DATA_FILE; use crate::result::Result; use crate::rpc_request::{RpcClient, RpcRequest}; use crate::service::Service; -use crate::storage_stage::ENTRIES_PER_SEGMENT; use crate::store_ledger_stage::StoreLedgerStage; use crate::streamer::BlobReceiver; use crate::thin_client::{retry_get_balance, ThinClient}; @@ -21,6 +20,7 @@ use solana_drone::drone::{request_airdrop_transaction, DRONE_PORT}; use solana_sdk::hash::{Hash, Hasher}; use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; use solana_sdk::storage_program::StorageTransaction; +use solana_sdk::storage_program::{get_segment_from_entry, ENTRIES_PER_SEGMENT}; use solana_sdk::transaction::Transaction; use std::fs::File; use std::io; @@ -93,8 +93,8 @@ fn get_entry_heights_from_last_id( | (u64::from(signature_vec[1]) << 8) | (u64::from(signature_vec[1]) << 16) | (u64::from(signature_vec[2]) << 24); - let max_segment_index = storage_entry_height / ENTRIES_PER_SEGMENT; - segment_index %= max_segment_index; + let max_segment_index = get_segment_from_entry(storage_entry_height); + segment_index %= max_segment_index as u64; let entry_height = segment_index * ENTRIES_PER_SEGMENT; let max_entry_height = entry_height + ENTRIES_PER_SEGMENT; diff --git a/src/storage_stage.rs b/src/storage_stage.rs index 04b3441acfde95..6535e60f1bf73b 100644 --- a/src/storage_stage.rs +++ b/src/storage_stage.rs @@ -18,13 +18,10 @@ use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::Signature; use solana_sdk::signature::{Keypair, KeypairUtil}; use solana_sdk::storage_program; -use solana_sdk::storage_program::StorageProgram; -use solana_sdk::storage_program::StorageTransaction; +use solana_sdk::storage_program::{get_segment_from_entry, StorageProgram, StorageTransaction}; use solana_sdk::system_transaction::SystemTransaction; use solana_sdk::transaction::Transaction; -use solana_sdk::vote_program; use std::collections::HashSet; -use std::mem::size_of; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::mpsc::RecvTimeoutError; use std::sync::{Arc, RwLock}; @@ -40,10 +37,8 @@ type ReplicatorMap = Vec>; #[derive(Default)] pub struct StorageStateInner { storage_results: StorageResults, - storage_keys: StorageKeys, + pub storage_keys: StorageKeys, replicator_map: ReplicatorMap, - storage_last_id: Hash, - entry_height: u64, } #[derive(Default)] @@ -65,13 +60,8 @@ const NUM_HASHES_FOR_STORAGE_ROTATE: u64 = 32; // TODO: some way to dynamically size NUM_IDENTITIES const NUM_IDENTITIES: usize = 1024; pub const NUM_STORAGE_SAMPLES: usize = 4; -pub const ENTRIES_PER_SEGMENT: u64 = 16; const KEY_SIZE: usize = 64; -pub fn get_segment_from_entry(entry_height: u64) -> u64 { - entry_height / ENTRIES_PER_SEGMENT -} - fn get_identity_index_from_signature(key: &Signature) -> usize { let rkey = key.as_ref(); let mut res: usize = (rkey[0] as usize) @@ -92,8 +82,6 @@ impl StorageState { storage_keys, storage_results, replicator_map, - entry_height: 0, - storage_last_id: Hash::default(), }; StorageState { @@ -101,30 +89,17 @@ impl StorageState { } } - pub fn get_mining_key(&self, key: &Signature) -> Vec { - let idx = get_identity_index_from_signature(key); - self.state.read().unwrap().storage_keys[idx..idx + KEY_SIZE].to_vec() - } - pub fn get_mining_result(&self, key: &Signature) -> Hash { let idx = get_identity_index_from_signature(key); self.state.read().unwrap().storage_results[idx] } - pub fn get_last_id(&self) -> Hash { - self.state.read().unwrap().storage_last_id - } - - pub fn get_entry_height(&self) -> u64 { - self.state.read().unwrap().entry_height - } - pub fn get_pubkeys_for_entry_height(&self, entry_height: u64) -> Vec { // TODO: keep track of age? const MAX_PUBKEYS_TO_RETURN: usize = 5; - let index = (entry_height / ENTRIES_PER_SEGMENT) as usize; + let index = get_segment_from_entry(entry_height); let replicator_map = &self.state.read().unwrap().replicator_map; - debug!("replicator_map: {:?}", replicator_map); + info!("replicator_map: {:?}", replicator_map); if index < replicator_map.len() { replicator_map[index] .iter() @@ -148,7 +123,6 @@ impl StorageStage { cluster_info: &Arc>, ) -> Self { debug!("storage_stage::new: entry_height: {}", entry_height); - storage_state.state.write().unwrap().entry_height = entry_height; let storage_state_inner = storage_state.state.clone(); let ledger_path = ledger_path.map(String::from); let cluster_info = cluster_info.clone(); @@ -157,7 +131,6 @@ impl StorageStage { .spawn(move || { let exit = exit.clone(); let mut poh_height = 0; - let mut current_key = 0; let mut entry_height = entry_height; loop { if let Some(ref ledger_path_str) = ledger_path { @@ -168,7 +141,6 @@ impl StorageStage { ledger_path_str, &mut poh_height, &mut entry_height, - &mut current_key, &cluster_info, ) { match e { @@ -231,7 +203,7 @@ impl StorageStage { } pub fn process_entry_crossing( - state: &Arc>, + _state: &Arc>, keypair: &Arc, _ledger_path: &str, entry_id: Hash, @@ -245,8 +217,6 @@ impl StorageStage { let mut rng = ChaChaRng::from_seed(seed); - state.write().unwrap().entry_height = entry_height; - if let Some(leader_data) = cluster_info.read().unwrap().leader_data() { let mut leader_client = mk_client(leader_data); @@ -254,7 +224,7 @@ impl StorageStage { let last_id = leader_client.get_last_id(); - info!( + debug!( "advertising new storage last id entry_height: {}!", entry_height ); @@ -273,7 +243,7 @@ impl StorageStage { } // Regenerate the answers - let num_segments = (entry_height / ENTRIES_PER_SEGMENT) as usize; + let num_segments = get_segment_from_entry(entry_height); if num_segments == 0 { info!("Ledger has 0 segments!"); return Ok(()); @@ -301,7 +271,7 @@ impl StorageStage { // Should be overwritten by the vote signatures which replace the // key values by the time it runs again. - let mut statew = state.write().unwrap(); + let mut statew = _state.write().unwrap(); match chacha_cbc_encrypt_file_many_keys( _ledger_path, @@ -324,22 +294,6 @@ impl StorageStage { Ok(()) } - fn process_vote_program( - storage_state: &Arc>, - tx: &Transaction, - current_key_idx: &mut usize, - ) { - debug!( - "generating storage_keys from votes current_key_idx: {}", - *current_key_idx - ); - let storage_keys = &mut storage_state.write().unwrap().storage_keys; - storage_keys[*current_key_idx..*current_key_idx + size_of::()] - .copy_from_slice(tx.signatures[0].as_ref()); - *current_key_idx += size_of::(); - *current_key_idx %= storage_keys.len(); - } - fn process_storage_program( instruction_idx: usize, storage_state: &Arc>, @@ -353,21 +307,24 @@ impl StorageStage { }) => { if proof_entry_height < entry_height { let mut statew = storage_state.write().unwrap(); - let max_segment_index = (entry_height / ENTRIES_PER_SEGMENT) as usize; + let max_segment_index = get_segment_from_entry(entry_height); if statew.replicator_map.len() < max_segment_index { statew .replicator_map .resize(max_segment_index, HashSet::new()); } - let proof_segment_index = (proof_entry_height / ENTRIES_PER_SEGMENT) as usize; + let proof_segment_index = get_segment_from_entry(proof_entry_height); if proof_segment_index < statew.replicator_map.len() { statew.replicator_map[proof_segment_index].insert(tx.account_keys[0]); } } - debug!("storage proof: entry_height: {}", entry_height); + debug!( + "storage proof: max entry_height: {} proof height: {}", + entry_height, proof_entry_height + ); } Ok(StorageProgram::AdvertiseStorageLastId { id, .. }) => { - info!("id: {}", id); + debug!("id: {}", id); } Ok(StorageProgram::ClaimStorageReward { .. }) => {} Ok(StorageProgram::ProofValidation { .. }) => {} @@ -384,7 +341,6 @@ impl StorageStage { ledger_path: &str, poh_height: &mut u64, entry_height: &mut u64, - current_key_idx: &mut usize, cluster_info: &Arc>, ) -> Result<()> { let timeout = Duration::new(1, 0); @@ -401,9 +357,8 @@ impl StorageStage { // the storage_keys with their signatures. for tx in entry.transactions { for (i, program_id) in tx.program_ids.iter().enumerate() { - if vote_program::check_id(&program_id) { - Self::process_vote_program(storage_state, &tx, current_key_idx); - } else if storage_program::check_id(&program_id) { + if storage_program::check_id(&program_id) { + info!("storage program: {:?}", tx); Self::process_storage_program(i, storage_state, *entry_height, &tx); } } @@ -454,9 +409,8 @@ mod tests { use solana_sdk::hash::Hasher; use solana_sdk::pubkey::Pubkey; use solana_sdk::signature::{Keypair, KeypairUtil, Signature}; + use solana_sdk::storage_program::{StorageTransaction, ENTRIES_PER_SEGMENT}; use solana_sdk::transaction::Transaction; - use solana_sdk::vote_program::Vote; - use solana_sdk::vote_transaction::VoteTransaction; use std::cmp::{max, min}; use std::fs::remove_dir_all; use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; @@ -564,7 +518,7 @@ mod tests { } #[test] - fn test_storage_stage_process_vote_entries() { + fn test_storage_stage_process_mining_proof_entries() { solana_logger::setup(); let keypair = Arc::new(Keypair::new()); let exit = Arc::new(AtomicBool::new(false)); @@ -577,7 +531,7 @@ mod tests { 1, ); - let entries = make_tiny_test_entries(128); + let entries = make_tiny_test_entries(ENTRIES_PER_SEGMENT as usize + 2); { let mut writer = LedgerWriter::open(&ledger_path, true).unwrap(); writer.write_entries(&entries.clone()).unwrap(); @@ -599,41 +553,37 @@ mod tests { ); storage_entry_sender.send(entries.clone()).unwrap(); - let mut reference_keys; - { - let keys = &storage_state.state.read().unwrap().storage_keys; - reference_keys = vec![0; keys.len()]; - reference_keys.copy_from_slice(keys); - } - let mut vote_txs: Vec = Vec::new(); - let vote = Vote { - tick_height: 123456, - }; let keypair = Keypair::new(); - let vote_tx = VoteTransaction::vote_new(&keypair, vote, Hash::default(), 1); - vote_txs.push(vote_tx); - let vote_entries = vec![Entry::new(&Hash::default(), 0, 1, vote_txs)]; - storage_entry_sender.send(vote_entries).unwrap(); + let last_id = Hash::default(); + let signature = Signature::new(keypair.sign(&last_id.as_ref()).as_ref()); + let storage_tx = Transaction::storage_new_mining_proof( + &keypair, + Hash::default(), + Hash::default(), + 0, + signature, + ); + let txs = vec![storage_tx]; + let storage_entries = vec![Entry::new(&Hash::default(), 0, 1, txs)]; + storage_entry_sender.send(storage_entries).unwrap(); for _ in 0..5 { - { - let keys = &storage_state.state.read().unwrap().storage_keys; - if keys[..] != *reference_keys.as_slice() { - break; - } + if storage_state.get_pubkeys_for_entry_height(0).len() != 0 { + break; } sleep(Duration::new(1, 0)); + info!("pubkeys are empty"); } - debug!("joining..?"); + info!("joining..?"); exit.store(true, Ordering::Relaxed); storage_stage.join().unwrap(); - { - let keys = &storage_state.state.read().unwrap().storage_keys; - assert_ne!(keys[..], *reference_keys); - } + assert_eq!( + storage_state.get_pubkeys_for_entry_height(0)[0], + keypair.pubkey() + ); remove_dir_all(ledger_path).unwrap(); }