Refactor chacha cuda to be able to test cuda crate but not in OpenCL (#7685)

* Refactor chacha cuda to be able to test cuda crate but not in OpenCL

chacha not implemeted in OpenCL

* Get off core::Error
This commit is contained in:
sakridge
2020-01-16 08:29:36 -08:00
committed by GitHub
parent ed0129f881
commit 8572b57834
23 changed files with 444 additions and 175 deletions

View File

@@ -42,7 +42,6 @@ serde_derive = "1.0.103"
serde_json = "1.0.44"
solana-budget-program = { path = "../programs/budget", version = "0.23.0" }
solana-clap-utils = { path = "../clap-utils", version = "0.23.0" }
solana-chacha-sys = { path = "../chacha-sys", version = "0.23.0" }
solana-client = { path = "../client", version = "0.23.0" }
solana-faucet = { path = "../faucet", version = "0.23.0" }
ed25519-dalek = "=1.0.0-pre.1"
@@ -52,6 +51,7 @@ solana-merkle-tree = { path = "../merkle-tree", version = "0.23.0" }
solana-metrics = { path = "../metrics", version = "0.23.0" }
solana-measure = { path = "../measure", version = "0.23.0" }
solana-net-utils = { path = "../net-utils", version = "0.23.0" }
solana-chacha-cuda = { path = "../chacha-cuda", version = "0.23.0" }
solana-perf = { path = "../perf", version = "0.23.0" }
solana-runtime = { path = "../runtime", version = "0.23.0" }
solana-sdk = { path = "../sdk", version = "0.23.0" }
@@ -73,7 +73,6 @@ solana-rayon-threadlimit = { path = "../rayon-threadlimit", version = "0.23.0" }
reed-solomon-erasure = { package = "solana-reed-solomon-erasure", version = "4.0.1-3", features = ["simd-accel"] }
[dev-dependencies]
hex-literal = "0.2.1"
matches = "0.1.6"
reqwest = { version = "0.10.1", default-features = false, features = ["blocking", "rustls-tls"] }
serial_test = "0.3.2"

File diff suppressed because it is too large Load Diff

View File

@@ -1,182 +0,0 @@
use solana_ledger::blockstore::Blockstore;
use solana_sdk::clock::Slot;
use std::fs::File;
use std::io;
use std::io::{BufWriter, Write};
use std::path::Path;
use std::sync::Arc;
pub use solana_chacha_sys::chacha_cbc_encrypt;
pub const CHACHA_BLOCK_SIZE: usize = 64;
pub const CHACHA_KEY_SIZE: usize = 32;
pub fn chacha_cbc_encrypt_ledger(
blockstore: &Arc<Blockstore>,
start_slot: Slot,
slots_per_segment: u64,
out_path: &Path,
ivec: &mut [u8; CHACHA_BLOCK_SIZE],
) -> io::Result<usize> {
let mut out_file =
BufWriter::new(File::create(out_path).expect("Can't open ledger encrypted data file"));
const BUFFER_SIZE: usize = 8 * 1024;
let mut buffer = [0; BUFFER_SIZE];
let mut encrypted_buffer = [0; BUFFER_SIZE];
let key = [0; CHACHA_KEY_SIZE];
let mut total_size = 0;
let mut current_slot = start_slot;
let mut start_index = 0;
loop {
match blockstore.get_data_shreds(current_slot, start_index, std::u64::MAX, &mut buffer) {
Ok((last_index, mut size)) => {
debug!(
"chacha: encrypting slice: {} num_shreds: {} data_len: {}",
current_slot,
last_index.saturating_sub(start_index),
size
);
debug!("read {} bytes", size);
if size == 0 {
if current_slot.saturating_sub(start_slot) < slots_per_segment {
current_slot += 1;
start_index = 0;
continue;
} else {
break;
}
}
if size < BUFFER_SIZE {
// round to the nearest key_size boundary
size = (size + CHACHA_KEY_SIZE - 1) & !(CHACHA_KEY_SIZE - 1);
}
total_size += size;
chacha_cbc_encrypt(&buffer[..size], &mut encrypted_buffer[..size], &key, ivec);
if let Err(res) = out_file.write(&encrypted_buffer[..size]) {
warn!("Error writing file! {:?}", res);
return Err(res);
}
start_index = last_index + 1;
}
Err(e) => {
info!("Error encrypting file: {:?}", e);
break;
}
}
}
Ok(total_size)
}
#[cfg(test)]
mod tests {
use crate::chacha::chacha_cbc_encrypt_ledger;
use crate::gen_keys::GenKeys;
use solana_ledger::blockstore::Blockstore;
use solana_ledger::entry::Entry;
use solana_ledger::get_tmp_ledger_path;
use solana_sdk::hash::{hash, Hash, Hasher};
use solana_sdk::pubkey::Pubkey;
use solana_sdk::signature::KeypairUtil;
use solana_sdk::system_transaction;
use std::fs::remove_file;
use std::fs::File;
use std::io::Read;
use std::sync::Arc;
fn make_tiny_deterministic_test_entries(num: usize) -> Vec<Entry> {
let zero = Hash::default();
let one = hash(&zero.as_ref());
let seed = [2u8; 32];
let mut rnd = GenKeys::new(seed);
let keypair = rnd.gen_keypair();
let mut id = one;
let mut num_hashes = 0;
(0..num)
.map(|_| {
Entry::new_mut(
&mut id,
&mut num_hashes,
vec![system_transaction::transfer(
&keypair,
&keypair.pubkey(),
1,
one,
)],
)
})
.collect()
}
use std::{env, fs::create_dir_all, path::PathBuf};
fn tmp_file_path(name: &str) -> PathBuf {
let out_dir = env::var("FARF_DIR").unwrap_or_else(|_| "farf".to_string());
let mut path = PathBuf::new();
path.push(out_dir);
path.push("tmp");
create_dir_all(&path).unwrap();
path.push(format!("{}-{}", name, Pubkey::new_rand()));
path
}
#[test]
fn test_encrypt_ledger() {
solana_logger::setup();
let ledger_path = get_tmp_ledger_path!();
let ticks_per_slot = 16;
let slots_per_segment = 32;
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
let out_path = tmp_file_path("test_encrypt_ledger");
let seed = [2u8; 32];
let mut rnd = GenKeys::new(seed);
let keypair = rnd.gen_keypair();
let entries = make_tiny_deterministic_test_entries(slots_per_segment);
blockstore
.write_entries(
0,
0,
0,
ticks_per_slot,
None,
true,
&Arc::new(keypair),
entries,
0,
)
.unwrap();
let mut key = hex!(
"abcd1234abcd1234abcd1234abcd1234 abcd1234abcd1234abcd1234abcd1234
abcd1234abcd1234abcd1234abcd1234 abcd1234abcd1234abcd1234abcd1234"
);
chacha_cbc_encrypt_ledger(
&blockstore,
0,
slots_per_segment as u64,
&out_path,
&mut key,
)
.unwrap();
let mut out_file = File::open(&out_path).unwrap();
let mut buf = vec![];
let size = out_file.read_to_end(&mut buf).unwrap();
let mut hasher = Hasher::default();
hasher.hash(&buf[..size]);
// golden needs to be updated if shred structure changes....
let golden: Hash = "2rq8nR6rns2T5zsbQAGBDZb41NVtacneLgkCH17CVxZm"
.parse()
.unwrap();
assert_eq!(hasher.result(), golden);
remove_file(&out_path).unwrap();
}
}

View File

@@ -1,280 +0,0 @@
// Module used by validators to approve storage mining proofs in parallel using the GPU
use crate::chacha::{CHACHA_BLOCK_SIZE, CHACHA_KEY_SIZE};
use solana_ledger::blockstore::Blockstore;
use solana_perf::perf_libs;
use solana_sdk::hash::Hash;
use std::io;
use std::mem::size_of;
use std::sync::Arc;
// Encrypt a file with multiple starting IV states, determined by ivecs.len()
//
// Then sample each block at the offsets provided by samples argument with sha256
// and return the vec of sha states
pub fn chacha_cbc_encrypt_file_many_keys(
blockstore: &Arc<Blockstore>,
segment: u64,
slots_per_segment: u64,
ivecs: &mut [u8],
samples: &[u64],
) -> io::Result<Vec<Hash>> {
let api = perf_libs::api().expect("no perf libs");
if ivecs.len() % CHACHA_BLOCK_SIZE != 0 {
return Err(io::Error::new(
io::ErrorKind::Other,
format!(
"bad IV length({}) not divisible by {} ",
ivecs.len(),
CHACHA_BLOCK_SIZE,
),
));
}
const BUFFER_SIZE: usize = 8 * 1024;
let mut buffer = [0; BUFFER_SIZE];
let num_keys = ivecs.len() / CHACHA_BLOCK_SIZE;
let mut sha_states = vec![0; num_keys * size_of::<Hash>()];
let mut int_sha_states = vec![0; num_keys * 112];
let keys: Vec<u8> = vec![0; num_keys * CHACHA_KEY_SIZE]; // keys not used ATM, uniqueness comes from IV
let mut current_slot = segment * slots_per_segment;
let mut start_index = 0;
let start_slot = current_slot;
let mut total_size = 0;
let mut time: f32 = 0.0;
unsafe {
(api.chacha_init_sha_state)(int_sha_states.as_mut_ptr(), num_keys as u32);
}
loop {
match blockstore.get_data_shreds(current_slot, start_index, std::u64::MAX, &mut buffer) {
Ok((last_index, mut size)) => {
debug!(
"chacha_cuda: encrypting segment: {} num_shreds: {} data_len: {}",
segment,
last_index.saturating_sub(start_index),
size
);
if size == 0 {
if current_slot.saturating_sub(start_slot) < slots_per_segment {
current_slot += 1;
start_index = 0;
continue;
} else {
break;
}
}
if size < BUFFER_SIZE {
// round to the nearest key_size boundary
size = (size + CHACHA_KEY_SIZE - 1) & !(CHACHA_KEY_SIZE - 1);
}
unsafe {
(api.chacha_cbc_encrypt_many_sample)(
buffer[..size].as_ptr(),
int_sha_states.as_mut_ptr(),
size,
keys.as_ptr(),
ivecs.as_mut_ptr(),
num_keys as u32,
samples.as_ptr(),
samples.len() as u32,
total_size,
&mut time,
);
}
total_size += size as u64;
start_index = last_index + 1;
}
Err(e) => {
info!("Error encrypting file: {:?}", e);
break;
}
}
}
unsafe {
(api.chacha_end_sha_state)(
int_sha_states.as_ptr(),
sha_states.as_mut_ptr(),
num_keys as u32,
);
}
let mut res = Vec::new();
for x in 0..num_keys {
let start = x * size_of::<Hash>();
let end = start + size_of::<Hash>();
res.push(Hash::new(&sha_states[start..end]));
}
Ok(res)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::archiver::sample_file;
use crate::chacha::chacha_cbc_encrypt_ledger;
use solana_ledger::entry::create_ticks;
use solana_ledger::get_tmp_ledger_path;
use solana_sdk::clock::DEFAULT_SLOTS_PER_SEGMENT;
use solana_sdk::signature::{Keypair, KeypairUtil};
use std::fs::{remove_dir_all, remove_file};
use std::path::Path;
#[test]
fn test_encrypt_file_many_keys_single() {
solana_logger::setup();
if perf_libs::api().is_none() {
info!("perf-libs unavailable, skipped");
return;
}
let slots_per_segment = 32;
let entries = create_ticks(slots_per_segment, 0, Hash::default());
let ledger_path = get_tmp_ledger_path!();
let ticks_per_slot = 16;
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
blockstore
.write_entries(
0,
0,
0,
ticks_per_slot,
Some(0),
true,
&Arc::new(Keypair::new()),
entries,
0,
)
.unwrap();
let out_path = Path::new("test_chacha_encrypt_file_many_keys_single_output.txt.enc");
let samples = [0];
let mut ivecs = hex!(
"abcd1234abcd1234abcd1234abcd1234 abcd1234abcd1234abcd1234abcd1234
abcd1234abcd1234abcd1234abcd1234 abcd1234abcd1234abcd1234abcd1234"
);
let mut cpu_iv = ivecs.clone();
chacha_cbc_encrypt_ledger(
&blockstore,
0,
slots_per_segment as u64,
out_path,
&mut cpu_iv,
)
.unwrap();
let ref_hash = sample_file(&out_path, &samples).unwrap();
let hashes = chacha_cbc_encrypt_file_many_keys(
&blockstore,
0,
slots_per_segment as u64,
&mut ivecs,
&samples,
)
.unwrap();
assert_eq!(hashes[0], ref_hash);
let _ignored = remove_dir_all(&ledger_path);
let _ignored = remove_file(out_path);
}
#[test]
fn test_encrypt_file_many_keys_multiple_keys() {
solana_logger::setup();
if perf_libs::api().is_none() {
info!("perf-libs unavailable, skipped");
return;
}
let ledger_path = get_tmp_ledger_path!();
let ticks_per_slot = 90;
let entries = create_ticks(2 * ticks_per_slot, 0, Hash::default());
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
blockstore
.write_entries(
0,
0,
0,
ticks_per_slot,
Some(0),
true,
&Arc::new(Keypair::new()),
entries,
0,
)
.unwrap();
let out_path = Path::new("test_chacha_encrypt_file_many_keys_multiple_output.txt.enc");
let samples = [0, 1, 3, 4, 5, 150];
let mut ivecs = Vec::new();
let mut ref_hashes: Vec<Hash> = vec![];
for i in 0..2 {
let mut ivec = hex!(
"abc123abc123abc123abc123abc123abc123abababababababababababababab
abc123abc123abc123abc123abc123abc123abababababababababababababab"
);
ivec[0] = i;
ivecs.extend(ivec.clone().iter());
chacha_cbc_encrypt_ledger(
&blockstore.clone(),
0,
DEFAULT_SLOTS_PER_SEGMENT,
out_path,
&mut ivec,
)
.unwrap();
ref_hashes.push(sample_file(&out_path, &samples).unwrap());
info!(
"ivec: {:?} hash: {:?} ivecs: {:?}",
ivec.to_vec(),
ref_hashes.last(),
ivecs
);
}
let hashes = chacha_cbc_encrypt_file_many_keys(
&blockstore,
0,
DEFAULT_SLOTS_PER_SEGMENT,
&mut ivecs,
&samples,
)
.unwrap();
assert_eq!(hashes, ref_hashes);
let _ignored = remove_dir_all(&ledger_path);
let _ignored = remove_file(out_path);
}
#[test]
fn test_encrypt_file_many_keys_bad_key_length() {
solana_logger::setup();
if perf_libs::api().is_none() {
info!("perf-libs unavailable, skipped");
return;
}
let mut keys = hex!("abc123");
let ledger_path = get_tmp_ledger_path!();
let samples = [0];
let blockstore = Arc::new(Blockstore::open(&ledger_path).unwrap());
assert!(chacha_cbc_encrypt_file_many_keys(
&blockstore,
0,
DEFAULT_SLOTS_PER_SEGMENT,
&mut keys,
&samples,
)
.is_err());
}
}

View File

@@ -7,14 +7,11 @@
pub mod banking_stage;
pub mod broadcast_stage;
pub mod chacha;
pub mod chacha_cuda;
pub mod cluster_info_vote_listener;
pub mod commitment;
pub mod shred_fetch_stage;
#[macro_use]
pub mod contact_info;
pub mod archiver;
pub mod blockstream;
pub mod blockstream_service;
pub mod cluster_info;
@@ -63,10 +60,6 @@ pub mod window_service;
#[macro_use]
extern crate solana_budget_program;
#[cfg(test)]
#[macro_use]
extern crate hex_literal;
#[macro_use]
extern crate log;

View File

@@ -3,13 +3,13 @@
// to submit its proof for mining to be rewarded.
use crate::{
chacha_cuda::chacha_cbc_encrypt_file_many_keys,
cluster_info::ClusterInfo,
contact_info::ContactInfo,
result::{Error, Result},
};
use rand::{Rng, SeedableRng};
use rand_chacha::ChaChaRng;
use solana_chacha_cuda::chacha_cuda::chacha_cbc_encrypt_file_many_keys;
use solana_ledger::{bank_forks::BankForks, blockstore::Blockstore};
use solana_runtime::{bank::Bank, storage_utils::archiver_accounts};
use solana_sdk::{