Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix jh_hash function optimize bug in gcc11.4 #3978

Merged
merged 16 commits into from
Nov 20, 2023
Merged
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -550,3 +550,6 @@ starcoin-vm-runtime.debug = 1

[profile.release.package."*"]
debug = false

#[profile.release.package.cryptonight-rs]
#opt-level = 2
2 changes: 2 additions & 0 deletions consensus/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ thiserror = { workspace = true }
proptest = { workspace = true }
proptest-derive = { workspace = true }
stest = { workspace = true }
serde = { features = ["derive"], workspace = true }
serde_json = { features = ["arbitrary_precision"], workspace = true }

[features]
default = []
Expand Down
10 changes: 6 additions & 4 deletions consensus/cryptonight-rs/ext/c_jh.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,16 +213,17 @@ static void E8(hashState *state)
/*The compression function F8 */
static void F8(hashState *state)
{
uint64 i;
uint64_t* x = (uint64_t*)state->x;
const uint64_t* buf = (uint64*)state->buffer;

/*xor the 512-bit message with the fist half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[i >> 1][i & 1] ^= ((uint64*)state->buffer)[i];
/*xor the 512-bit message with the fist half of the 1024-bit hash state*/
for (int i = 0; i < 8; ++i) x[i] ^= buf[i];

/*the bijective function E8 */
E8(state);

/*xor the 512-bit message with the second half of the 1024-bit hash state*/
for (i = 0; i < 8; i++) state->x[(8+i) >> 1][(8+i) & 1] ^= ((uint64*)state->buffer)[i];
for (int i = 0; i < 8; ++i) x[i + 8] ^= buf[i];
}

/*before hashing a message, initialize the hash state as H0 */
Expand All @@ -240,6 +241,7 @@ static HashReturn Init(hashState *state, int hashbitlen)
case 224: memcpy(state->x,JH224_H0,128); break;
case 256: memcpy(state->x,JH256_H0,128); break;
case 384: memcpy(state->x,JH384_H0,128); break;
default:
case 512: memcpy(state->x,JH512_H0,128); break;
}

Expand Down
6 changes: 6 additions & 0 deletions consensus/cryptonight-rs/ext/hash-ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,11 @@ void cn_slow_hash(const void *data, size_t length, char *hash, int variant, int

void hash_extra_blake(const void *data, size_t length, char *hash);
void hash_extra_groestl(const void *data, size_t length, char *hash);
#ifdef __cplusplus
extern "C" {
#endif
void hash_extra_jh(const void *data, size_t length, char *hash);
#ifdef __cplusplus
}
#endif
void hash_extra_skein(const void *data, size_t length, char *hash);
24 changes: 21 additions & 3 deletions consensus/cryptonight-rs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,26 @@ use libc::{c_char, c_int, c_void, size_t};
extern "C" {
fn cryptonight_hash(
data: *const c_char,
hash: *const c_char,
hash: *mut c_char,
length: size_t,
variant: c_int,
height: u64,
) -> c_void;
}

#[link(name = "cryptonight", kind = "static")]
extern "C" {
fn hash_extra_jh(data: *const c_char, length: size_t, hash: *mut c_char) -> c_void;
}
const VARIANT: i32 = 4;
const HEIGHT: u64 = 0;

// https://github.com/paritytech/rust-snappy/blob/master/snappy-sys/src/lib.rs#L19
#[allow(clippy::unsound_collection_transmute)]
pub fn cryptonight_r(data: &[u8], size: usize) -> Vec<u8> {
let hash: Vec<i8> = vec![0i8; 32];
let mut hash: Vec<i8> = vec![0i8; 32];
let data_ptr: *const c_char = data.as_ptr() as *const c_char;
let hash_ptr: *const c_char = hash.as_ptr() as *const c_char;
let hash_ptr: *mut c_char = hash.as_mut_ptr() as *mut c_char;
let mut hash = unsafe {
cryptonight_hash(data_ptr, hash_ptr, size, VARIANT, HEIGHT);
std::mem::transmute::<Vec<i8>, Vec<u8>>(hash)
Expand All @@ -27,5 +32,18 @@ pub fn cryptonight_r(data: &[u8], size: usize) -> Vec<u8> {
hash
}

#[allow(clippy::unsound_collection_transmute)]
pub fn hash_extra_jh_r(data: &[u8], size: usize) -> Vec<u8> {
let mut hash: Vec<i8> = vec![0i8; 32];
let data_ptr: *const c_char = data.as_ptr() as *const c_char;
let hash_ptr: *mut c_char = hash.as_mut_ptr() as *mut c_char;
let mut hash = unsafe {
hash_extra_jh(data_ptr, size, hash_ptr);
std::mem::transmute::<Vec<i8>, Vec<u8>>(hash)
};
hash.reverse();
hash
}

#[cfg(test)]
mod tests;
13 changes: 12 additions & 1 deletion consensus/cryptonight-rs/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,21 @@ fn test_amd_ryzen() {
assert_eq!(hash, data.output);
}

// this test is same test_amd_ryzen, trace the inner produce can get this data
#[test]
fn test_main_block2_jh_on_ubuntu22() {
let data = TestCase {
input: "d6a11a431fd56dc29c5927328e83eef11590362b70aef492f12c449bde657b4e3ac4e15816314613ca7339d152294b185ed86709acc1266259580d4aba729d37c733a89eb15ea91b28bbe49bd151cb1b947bb239c4ff10cfe24aa05f31a8cdb8e71345ea45cffeff6bbf9d2c7fe58f13f190b2921a531fb65841221d3e3e8483830a9b4a9c2e2843e74db1792c739d3ee27a973b61c838f300a54951cf8ac5fe99c2ced05d8b4cffa20a24f84dba4a4528b2b2cf035ae5b06b49f12364fcb5776db3692bfb6f029d".from_hex().unwrap(),
output: "0000008e67af69c3c670dab325e8fc3a9dc045c6e339aa35f43b415604513742".from_hex().unwrap(),
};
let hash = hash_extra_jh_r(&data.input[..], data.input.len());
assert_eq!(hash, data.output);
}

// add a test for ubuntu22
// add -Ofast in build.rs, this test will failed on unbuntu22
// the data is gen from verify_header_test_barnard_block3_ubuntu22
// The test with 'ofast' flag passes using clang compiler under ubuntu22, but fails with using gcc
// The test with 'Ofast' flag passes using clang compiler under ubuntu22, but fails with using gcc
#[test]
fn test_barnard_block3_on_ubuntu22() {
let data = TestCase {
Expand Down
19 changes: 17 additions & 2 deletions consensus/src/consensus_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@

use crate::consensus::Consensus;
use crate::difficulty::{get_next_target_helper, BlockDiffInfo};
use crate::{difficult_to_target, target_to_difficulty, G_CRYPTONIGHT};
use crate::{difficult_to_target, target_to_difficulty, G_ARGON, G_CRYPTONIGHT};
use starcoin_crypto::hash::PlainCryptoHash;
use starcoin_crypto::HashValue;
use starcoin_time_service::{duration_since_epoch, MockTimeService, TimeService, TimeServiceType};
use starcoin_types::account_address::AccountAddress;
use starcoin_types::block::{BlockHeader, BlockHeaderBuilder, BlockHeaderExtra, RawBlockHeader};
use starcoin_types::block::{
Block, BlockHeader, BlockHeaderBuilder, BlockHeaderExtra, RawBlockHeader,
};
use starcoin_types::U256;
use starcoin_vm_types::genesis_config::ChainId;
use std::collections::VecDeque;
Expand Down Expand Up @@ -94,6 +96,19 @@ fn verify_header_test_barnard_block3_ubuntu22() {
.verify_header_difficulty(header.difficulty(), &header)
.unwrap()
}
// see https://stcscan.io/barnard/address/0x01/resources
// 0x00000000000000000000000000000001::Config::Config<0x00000000000000000000000000000001::ConsensusConfig::ConsensusConfig> "strategy":1
// see https://stcscan.io/main/address/0x01/resources
// 0x00000000000000000000000000000001::Config::Config<0x00000000000000000000000000000001::ConsensusConfig::ConsensusConfig> "strategy":3
#[stest::test]
fn verify_header_test_barnard_block5061847_ubuntu20() {
let str = r#"{"header":{"parent_hash":"0x45efb7914f0fe6bcd6baf4ed7a67da076953cf18128a25227e575a689236942f","timestamp":1654174610768,"number":5061847,"author":"0x7eec55ea1bafa8c4919101135b90b17b","author_auth_key":null,"txn_accumulator_root":"0x8c35c3d34ee16ca395c2a17668b61894b347c037d49d30477e7d2506dc69e936","block_accumulator_root":"0x0e602da30ea3f2f91b505f8a788dfc1c2b73619f328661a80ec6d59197527936","state_root":"0x42c63a367951160b01ce4e2c1e4559f08e786cf1e56a5e423da6db459f9507f7","gas_used":0,"difficulty":"0x0bee","body_hash":"0xc01e0329de6d899348a8ef4bd51db56175b3fa0988e57c3dcec8eaf13a164d97","chain_id":{"id":251},"nonce":2771673659,"extra":"0x00000000"},"body":{"transactions":[],"uncles":null}}"#;
let block: Block = serde_json::from_str(str).unwrap();
let header = block.header;
G_ARGON
.verify_header_difficulty(header.difficulty(), &header)
.unwrap()
}

fn simulate_blocks(time_plan: u64, init_difficulty: U256) -> u64 {
fn liner_hash_pow(difficulty: U256, current: u64) -> u64 {
Expand Down
4 changes: 2 additions & 2 deletions scripts/dev_setup.sh
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,9 @@ set -eo pipefail

SHELLCHECK_VERSION=0.7.1
HADOLINT_VERSION=1.17.4
SCCACHE_VERSION=0.2.16-alpha.0
SCCACHE_VERSION=0.3.0
#If installing sccache from a git repp set url@revision.
SCCACHE_GIT='https://github.com/diem/sccache.git@ef50d87a58260c30767520045e242ccdbdb965af'
#SCCACHE_GIT='https://github.com/diem/sccache.git@ef50d87a58260c30767520045e242ccdbdb965af'
GRCOV_VERSION=0.8.2
GUPPY_GIT='https://github.com/facebookincubator/cargo-guppy@39ec940f36b0a0df96a330243d127cbe2db9f919'
KUBECTL_VERSION=1.18.6
Expand Down
11 changes: 4 additions & 7 deletions scripts/verify_header.sh
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,13 @@ function download() {
}

function usage() {
echo -e "usage: verify_header.sh net to_dir"
echo -e "usage: verify_header.sh net"
echo -e "net is main, barnard, proxima, halley"
echo -e "to_dir like ~/.starcoin/main,~/.starcoin/barnard"
}

function import_block() {
function verify_header() {
net=$1
block_list=$2
to_dir=$3

download "$net" "$block_list"

Expand All @@ -62,15 +60,14 @@ function import_block() {
echo -e "$net verify-header succ"
}

if [ $# != 2 ]; then
if [ $# != 1 ]; then
usage
exit 1
fi
net=$1
to_dir=$2
case $net in
"main" | "barnard" | "proxima" |"halley")
import_block "$net" block_list.csv "$to_dir"
verify_header "$net" block_list.csv
;;
*)
echo "$net not supported"
Expand Down
Loading