diff --git a/Cargo.toml b/Cargo.toml index 645c388..fd73308 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "spectrex" -version = "0.3.19" +version = "0.3.20" edition = "2021" authors = ["Spectre developers"] repository = "https://github.com/spectre-project/rusty-spectrex" @@ -12,12 +12,12 @@ categories = ["algorithms", "cryptography"] homepage = "https://spectre-network.org" [dependencies] +cdivsufsort = "2.0.0" fnv = "1.0.7" rc4 = "0.1.0" salsa20 = "0.10.2" sha2 = "0.10.8" siphasher = "1.0.1" -suffix_array = "0.5.0" xxhash-rust = { version = "0.8.10", features = ["xxh64"] } [dev-dependencies] diff --git a/benches/astrobwtv3.rs b/benches/astrobwtv3.rs index 1efa646..4572668 100644 --- a/benches/astrobwtv3.rs +++ b/benches/astrobwtv3.rs @@ -10,13 +10,9 @@ fn astrobwtv3_bench(input: &[u8; 32]) { } fn criterion_benchmark(c: &mut Criterion) { - c.bench_function("astrobwtv3_zeros", |b| { - b.iter(|| astrobwtv3_bench(&[0; 32])) - }); + c.bench_function("astrobwtv3_zeros", |b| b.iter(|| astrobwtv3_bench(&[0; 32]))); - c.bench_function("astrobwtv3_ones", |b| { - b.iter(|| astrobwtv3_bench(&[0xFF; 32])) - }); + c.bench_function("astrobwtv3_ones", |b| b.iter(|| astrobwtv3_bench(&[0xFF; 32]))); c.bench_function("astrobwtv3_random", |b| { let random_data = random::<[u8; 32]>(); diff --git a/rustfmt.toml b/rustfmt.toml new file mode 100644 index 0000000..6fe7a4e --- /dev/null +++ b/rustfmt.toml @@ -0,0 +1,6 @@ +max_width = 135 +use_field_init_shorthand = true +use_try_shorthand = true +use_small_heuristics = "Max" +newline_style = "auto" +edition = "2021" diff --git a/src/astrobwtv3.rs b/src/astrobwtv3.rs index caec90a..036b927 100644 --- a/src/astrobwtv3.rs +++ b/src/astrobwtv3.rs @@ -1,15 +1,17 @@ // Public crates. +use cdivsufsort::sort_in_place as dss; use rc4::{KeyInit, Rc4, StreamCipher}; use salsa20::{cipher::KeyIvInit, Salsa20}; use sha2::{Digest, Sha256}; use siphasher::sip::SipHasher24; use std::hash::Hasher; -use suffix_array::SuffixArray; +use std::slice::from_raw_parts_mut; // This is the maximum. const MAX_LENGTH: u32 = (256 * 384) - 1; // The base for the following code was contributed by @Wolf9466 on Discord. +#[rustfmt::skip] const BRANCH_TABLE: [u32; 256] = [ 0x090F020A, 0x060B0500, 0x09080609, 0x0A0D030B, 0x04070A01, 0x09030607, 0x060D0401, 0x000A0904, 0x040F0F06, 0x030E070C, 0x04020D02, 0x0B0F050A, 0x0C020C04, 0x0B03070F, 0x07060206, 0x0C060501, @@ -123,57 +125,23 @@ pub fn astrobwtv3_hash(input: &[u8]) -> [u8; 32] { for j in (0..=3).rev() { let op = (opcode >> (j * 8)) & 0xFF; match op { - 0x00 => { - tmp = tmp.wrapping_add(tmp); // + - } - 0x01 => { - tmp = tmp.wrapping_sub(tmp ^ 97); // XOR and - - } - 0x02 => { - tmp = tmp.wrapping_mul(tmp); // * - } - 0x03 => { - tmp ^= data[pos2 as usize]; // XOR - } - 0x04 => { - tmp = !tmp; // binary NOT operator - } - 0x05 => { - tmp &= data[pos2 as usize]; // AND - } - 0x06 => { - tmp = tmp.wrapping_shl((tmp & 3) as u32); // shift left - } - 0x07 => { - tmp = tmp.wrapping_shr((tmp & 3) as u32); // shift right - } - 0x08 => { - tmp = tmp.reverse_bits(); // reverse bits - } - 0x09 => { - tmp = tmp ^ tmp.count_ones() as u8; // ones count bits - } - 0x0A => { - tmp = tmp.rotate_left(tmp as u32); // rotate bits by random - } - 0x0B => { - tmp = tmp.rotate_left(1); // rotate bits by 1 - } - 0x0C => { - tmp = tmp ^ tmp.rotate_left(2); // rotate bits by 2 - } - 0x0D => { - tmp = tmp.rotate_left(3); // rotate bits by 3 - } - 0x0E => { - tmp = tmp ^ tmp.rotate_left(4); // rotate bits by 4 - } - 0x0F => { - tmp = tmp.rotate_left(5); // rotate bits by 5 - } - _ => { - unreachable!(); - } + 0x00 => tmp = tmp.wrapping_add(tmp), // + + 0x01 => tmp = tmp.wrapping_sub(tmp ^ 97), // XOR and - + 0x02 => tmp = tmp.wrapping_mul(tmp), // * + 0x03 => tmp ^= data[pos2 as usize], // XOR + 0x04 => tmp = !tmp, // binary NOT operator + 0x05 => tmp &= data[pos2 as usize], // AND + 0x06 => tmp = tmp.wrapping_shl((tmp & 3) as u32), // shift left + 0x07 => tmp = tmp.wrapping_shr((tmp & 3) as u32), // shift right + 0x08 => tmp = tmp.reverse_bits(), // reverse bits + 0x09 => tmp = tmp ^ tmp.count_ones() as u8, // ones count bits + 0x0A => tmp = tmp.rotate_left(tmp as u32), // rotate bits by random + 0x0B => tmp = tmp.rotate_left(1), // rotate bits by 1 + 0x0C => tmp = tmp ^ tmp.rotate_left(2), // rotate bits by 2 + 0x0D => tmp = tmp.rotate_left(3), // rotate bits by 3 + 0x0E => tmp = tmp ^ tmp.rotate_left(4), // rotate bits by 4 + 0x0F => tmp = tmp.rotate_left(5), // rotate bits by 5 + _ => unreachable!(), } } data[i as usize] = tmp; @@ -233,13 +201,20 @@ pub fn astrobwtv3_hash(input: &[u8]) -> [u8; 32] { } // We may discard up to ~ 1KiB data from the stream to ensure that wide number of variants exists. - let data_len = (tries - 4) as u32 * 256 - + ((((data[253] as u64) << 8) | (data[254] as u64)) as u32 & 0x3ff); + let data_len = (tries - 4) as u32 * 256 + ((((data[253] as u64) << 8) | (data[254] as u64)) as u32 & 0x3ff); // Step 6: build our suffix array. - let scratch_sa = SuffixArray::new(&scratch_data[..data_len as usize]); - let mut scratch_sa_bytes: Vec = vec![]; - for vector in &scratch_sa.into_parts().1[1..(data_len as usize + 1)] { + let mut sa = vec![0u32; data_len as usize + 1]; + sa[0] = data_len; + + // i32 slice for cdivsufsort + let sa_i32 = unsafe { from_raw_parts_mut(sa[1..].as_mut_ptr() as *mut i32, data_len as usize) }; + + // Build suffix array + dss(&scratch_data[..data_len as usize], sa_i32); + + let mut scratch_sa_bytes: Vec = Vec::with_capacity(data_len as usize * 4); + for vector in &sa[1..(data_len as usize + 1)] { // Little and big endian. if cfg!(target_endian = "little") { scratch_sa_bytes.extend_from_slice(&vector.to_le_bytes()); diff --git a/tests/astrobwtv3.rs b/tests/astrobwtv3.rs index cf77020..79e3513 100644 --- a/tests/astrobwtv3.rs +++ b/tests/astrobwtv3.rs @@ -2,91 +2,33 @@ use spectrex::astrobwtv3; // Source hashes. +#[rustfmt::skip] const INPUT_HASHES: [[u8; 32]; 10] = [ - [ - 88, 101, 183, 41, 212, 156, 190, 48, 230, 97, 94, 105, 177, 86, 88, 84, 60, 239, 203, 124, - 63, 32, 160, 222, 34, 141, 50, 108, 138, 16, 90, 230, - ], - [ - 131, 190, 160, 208, 86, 121, 144, 207, 78, 235, 188, 253, 251, 0, 62, 161, 72, 225, 55, - 184, 202, 212, 91, 125, 56, 204, 174, 214, 100, 28, 150, 15, - ], - [ - 179, 131, 188, 255, 206, 72, 67, 215, 143, 44, 37, 210, 230, 54, 1, 114, 91, 104, 33, 126, - 162, 70, 130, 110, 176, 105, 75, 122, 212, 119, 158, 216, - ], - [ - 39, 225, 250, 46, 101, 197, 139, 171, 106, 53, 239, 59, 245, 146, 31, 67, 140, 201, 190, - 86, 193, 24, 88, 104, 86, 69, 166, 231, 214, 240, 167, 63, - ], - [ - 245, 133, 43, 254, 160, 213, 125, 60, 90, 42, 50, 123, 188, 209, 219, 125, 176, 250, 51, - 158, 201, 167, 122, 244, 98, 108, 163, 110, 66, 26, 110, 177, - ], - [ - 209, 138, 166, 16, 5, 177, 37, 64, 133, 13, 211, 172, 189, 223, 107, 148, 194, 78, 132, 23, - 181, 25, 69, 149, 229, 95, 41, 73, 236, 217, 1, 119, - ], - [ - 74, 36, 121, 180, 94, 215, 192, 195, 231, 0, 113, 44, 66, 171, 214, 173, 223, 29, 224, 201, - 26, 217, 139, 162, 153, 31, 15, 158, 221, 165, 97, 74, - ], - [ - 49, 189, 89, 13, 141, 86, 53, 198, 164, 148, 121, 198, 40, 219, 66, 13, 251, 73, 38, 16, - 94, 71, 244, 44, 236, 119, 243, 202, 211, 199, 161, 164, - ], - [ - 36, 23, 55, 103, 91, 244, 203, 137, 143, 244, 115, 22, 197, 152, 241, 34, 94, 40, 61, 246, - 64, 251, 232, 23, 91, 203, 48, 233, 13, 70, 19, 6, - ], - [ - 19, 247, 78, 146, 5, 164, 136, 199, 248, 218, 200, 24, 110, 186, 2, 253, 192, 139, 161, 70, - 92, 156, 177, 77, 63, 124, 209, 236, 105, 130, 229, 218, - ], + [88, 101, 183, 41, 212, 156, 190, 48, 230, 97, 94, 105, 177, 86, 88, 84, 60, 239, 203, 124, 63, 32, 160, 222, 34, 141, 50, 108, 138, 16, 90, 230], + [131, 190, 160, 208, 86, 121, 144, 207, 78, 235, 188, 253, 251, 0, 62, 161, 72, 225, 55, 184, 202, 212, 91, 125, 56, 204, 174, 214, 100, 28, 150, 15], + [179, 131, 188, 255, 206, 72, 67, 215, 143, 44, 37, 210, 230, 54, 1, 114, 91, 104, 33, 126, 162, 70, 130, 110, 176, 105, 75, 122, 212, 119, 158, 216], + [39, 225, 250, 46, 101, 197, 139, 171, 106, 53, 239, 59, 245, 146, 31, 67, 140, 201, 190, 86, 193, 24, 88, 104, 86, 69, 166, 231, 214, 240, 167, 63], + [245, 133, 43, 254, 160, 213, 125, 60, 90, 42, 50, 123, 188, 209, 219, 125, 176, 250, 51, 158, 201, 167, 122, 244, 98, 108, 163, 110, 66, 26, 110, 177], + [209, 138, 166, 16, 5, 177, 37, 64, 133, 13, 211, 172, 189, 223, 107, 148, 194, 78, 132, 23, 181, 25, 69, 149, 229, 95, 41, 73, 236, 217, 1, 119], + [74, 36, 121, 180, 94, 215, 192, 195, 231, 0, 113, 44, 66, 171, 214, 173, 223, 29, 224, 201, 26, 217, 139, 162, 153, 31, 15, 158, 221, 165, 97, 74], + [49, 189, 89, 13, 141, 86, 53, 198, 164, 148, 121, 198, 40, 219, 66, 13, 251, 73, 38, 16, 94, 71, 244, 44, 236, 119, 243, 202, 211, 199, 161, 164], + [36, 23, 55, 103, 91, 244, 203, 137, 143, 244, 115, 22, 197, 152, 241, 34, 94, 40, 61, 246, 64, 251, 232, 23, 91, 203, 48, 233, 13, 70, 19, 6], + [19, 247, 78, 146, 5, 164, 136, 199, 248, 218, 200, 24, 110, 186, 2, 253, 192, 139, 161, 70, 92, 156, 177, 77, 63, 124, 209, 236, 105, 130, 229, 218] ]; // Expected hashes. +#[rustfmt::skip] const OUTPUT_HASHES: [[u8; 32]; 10] = [ - [ - 245, 38, 108, 237, 82, 247, 189, 19, 237, 82, 86, 55, 2, 184, 61, 119, 46, 92, 244, 227, - 116, 149, 198, 219, 96, 114, 78, 176, 95, 100, 70, 108, - ], - [ - 253, 32, 214, 213, 188, 194, 70, 228, 112, 24, 6, 44, 126, 57, 113, 161, 136, 239, 160, - 105, 186, 240, 50, 226, 251, 170, 152, 240, 56, 198, 210, 155, - ], - [ - 65, 74, 3, 63, 226, 164, 225, 88, 106, 53, 218, 166, 144, 241, 106, 229, 179, 70, 126, 4, - 251, 123, 47, 222, 21, 59, 215, 107, 158, 120, 220, 231, - ], - [ - 155, 216, 182, 230, 186, 65, 127, 57, 112, 0, 112, 151, 217, 159, 28, 9, 108, 203, 111, - 197, 28, 57, 187, 106, 119, 43, 187, 152, 185, 232, 76, 39, - ], - [ - 142, 168, 196, 185, 54, 135, 241, 38, 229, 163, 12, 77, 61, 148, 126, 102, 91, 39, 191, - 175, 181, 12, 18, 132, 39, 161, 222, 157, 170, 145, 13, 135, - ], - [ - 35, 178, 78, 186, 52, 161, 140, 179, 209, 163, 146, 6, 40, 117, 215, 227, 154, 174, 92, - 246, 212, 77, 96, 243, 94, 87, 135, 193, 151, 155, 220, 19, - ], - [ - 176, 117, 190, 212, 164, 159, 17, 220, 116, 184, 102, 106, 61, 148, 204, 230, 46, 171, 41, - 20, 214, 91, 151, 11, 48, 93, 240, 8, 37, 189, 240, 125, - ], - [ - 60, 248, 1, 238, 24, 248, 240, 206, 56, 147, 254, 66, 226, 246, 107, 22, 164, 135, 124, 15, - 102, 244, 33, 117, 126, 87, 71, 160, 243, 245, 34, 38, - ], - [ - 76, 190, 131, 164, 182, 28, 224, 104, 232, 94, 56, 15, 28, 185, 196, 63, 149, 235, 83, 228, - 139, 1, 112, 29, 30, 83, 30, 92, 29, 71, 75, 217, - ], - [ - 147, 234, 41, 103, 132, 162, 41, 23, 249, 180, 98, 124, 32, 81, 107, 133, 162, 73, 44, 135, - 179, 55, 228, 194, 113, 179, 161, 235, 85, 5, 111, 121, - ], + [245, 38, 108, 237, 82, 247, 189, 19, 237, 82, 86, 55, 2, 184, 61, 119, 46, 92, 244, 227, 116, 149, 198, 219, 96, 114, 78, 176, 95, 100, 70, 108], + [253, 32, 214, 213, 188, 194, 70, 228, 112, 24, 6, 44, 126, 57, 113, 161, 136, 239, 160, 105, 186, 240, 50, 226, 251, 170, 152, 240, 56, 198, 210, 155], + [65, 74, 3, 63, 226, 164, 225, 88, 106, 53, 218, 166, 144, 241, 106, 229, 179, 70, 126, 4, 251, 123, 47, 222, 21, 59, 215, 107, 158, 120, 220, 231], + [155, 216, 182, 230, 186, 65, 127, 57, 112, 0, 112, 151, 217, 159, 28, 9, 108, 203, 111, 197, 28, 57, 187, 106, 119, 43, 187, 152, 185, 232, 76, 39], + [142, 168, 196, 185, 54, 135, 241, 38, 229, 163, 12, 77, 61, 148, 126, 102, 91, 39, 191, 175, 181, 12, 18, 132, 39, 161, 222, 157, 170, 145, 13, 135], + [35, 178, 78, 186, 52, 161, 140, 179, 209, 163, 146, 6, 40, 117, 215, 227, 154, 174, 92, 246, 212, 77, 96, 243, 94, 87, 135, 193, 151, 155, 220, 19], + [176, 117, 190, 212, 164, 159, 17, 220, 116, 184, 102, 106, 61, 148, 204, 230, 46, 171, 41, 20, 214, 91, 151, 11, 48, 93, 240, 8, 37, 189, 240, 125], + [60, 248, 1, 238, 24, 248, 240, 206, 56, 147, 254, 66, 226, 246, 107, 22, 164, 135, 124, 15, 102, 244, 33, 117, 126, 87, 71, 160, 243, 245, 34, 38], + [76, 190, 131, 164, 182, 28, 224, 104, 232, 94, 56, 15, 28, 185, 196, 63, 149, 235, 83, 228, 139, 1, 112, 29, 30, 83, 30, 92, 29, 71, 75, 217], + [147, 234, 41, 103, 132, 162, 41, 23, 249, 180, 98, 124, 32, 81, 107, 133, 162, 73, 44, 135, 179, 55, 228, 194, 113, 179, 161, 235, 85, 5, 111, 121] ]; // AstroBWTv3 tests.